I'm creating a client application with the idea of publish new messages to a remote RabbitMQ queue. I'm using MassTransit to create this client, and my code looks this way:
static IBusControl CreateBus()
{
return Bus.Factory.CreateUsingRabbitMq(x =>
{
var host = x.Host(new Uri(ConfigurationManager.AppSettings["RabbitMQHost"]), h =>
{
h.Username("user");
h.Password("password");
});
});
}
static IRequestClient<ISyncProject, IProjectSynced> CreateRequestClient(IBusControl busControl)
{
var serviceAddress = new Uri(ConfigurationManager.AppSettings["ServiceAddress"]);
IRequestClient<ISyncProject, IProjectSynced> client =
busControl.CreateRequestClient<ISyncProject, IProjectSynced>(serviceAddress, TimeSpan.FromDays(1));
return client;
}
private static async Task MainLogic(IBusControl busControl)
{
IRequestClient<ISyncProject, IProjectSynced> client = CreateRequestClient(busControl);
//I'm using the client here as I show below, this part is not important it works with localhost
IProjectSynced response = await client.Request(new ProjecToSync() { OriginalOOMID = OriginalOOMID });
}
And the config file looks like this:
<appSettings>
<add key="RabbitMQHost" value="rabbitmq://ServerName" />
<add key="ServiceQueueName" value="queueName" />
<add key="ServiceAddress" value="rabbitmq://ServerName/queueName" />
</appSettings>
I'm not using guest user, I created a new one and I added all the rights as administrator.
Now this code works if I run the client application in the same server where is running RabbitMQ and also changing ServerName by localhost. If I run the client in my local machine using whatever ServerName or IP address of server, RabbitMQ is blocking my connection:
I presume this is has to be with some configuration that I need to do in the server but I have not found it so far.
One thing I noticed now is disk space is in red and and a big amount of generic exchanges have been created
As your question shows, down at the bottom you have a connection, but it is blocked.
The RabbitMQ documentation lists some conditions where a connection is blocked. These generally have to do with resource limitations on the broker machine itself. In this case, we've managed to get a clear picture that the free disk space available to the broker is below its low-water mark. Thus, all connections will be blocked until this condition is resolved (either lower the mark - not recommended, or increase the available free space).
Related
I'm using a very basic example for testing my MassTransit connection to rabbitMq through C#. Whenever I run this code to connect to my rabbitMq endpoint, it works fine whenever I have a wildcard set as permission. However, when I add the permissions in the rabbitMq admin to only allow this user to access the test event, this code will fail.
For some reason it will first try to connect to an exchange name that I guess is generated (by MassTransit?):
RabbitMQ.Client.Exceptions.OperationInterruptedException: 'The AMQP operation was interrupted: AMQP close-reason, initiated by Peer, code=403, text="ACCESS_REFUSED - access to exchange '*ComputerName*_dotnet_bus_73451gfsgerqwrefxfddgf' in vhost '/' refused for user 'user'", classId=40, methodId=10, cause='
So the exchange *ComputerName*_dotnet_bus_73451gfsgerqwrefxfddgf, after that it will try to connect to the test exchange. Of course I can add the ComputerName.... exchange to the permissions but then this would need to be done for each computer trying to run this code. Why is MassTransit trying to connect to this exchange? Is the code incorrect or is this just how MassTransit works?
This is the code for the test application (I altered this a bit so it might not run right of the bat, but, in general the code runs fine):
using System;
using MassTransit;
namespace Test
{
public class Testing
{
public string Id { get; set; }
}
}
namespace Consumer
{
class Program
{
static void Main(string[] args)
{
var bus = Bus.Factory.CreateUsingRabbitMq(sbc =>
{
var host = sbc.Host(new Uri("rabbitmq://servername"), h =>
{
h.Username("user");
h.Password("user");
});
sbc.ReceiveEndpoint(host, "test", ep =>
{
ep.Handler<Testing>(context =>
{
return Console.Out.WriteLineAsync($"Received: {context.Message.Id}");
});
});
});
bus.Start();
// For testing purposes, we send a message ourselves.
bus.Publish(new Testing { Id = "X" });
Console.WriteLine("Waiting for messages. Press any key to exit");
Console.ReadKey();
bus.Stop();
}
}
}
Image of the rabbitMq admin user permission:
Is the code incorrect or is this just how MassTransit works?
More than likely this is just how MassTransit works. See this other question: Prevent MassTransit from creating a RabbitMQ exchange for a consumer host
Strangely enough I could not find this information anywhere in the MassTransit docs.
You'll have to grant the configure permission for exchanges containing the string dotnet_bus. More than likely other permissions like read and write will be required.
NOTE: the RabbitMQ team monitors the rabbitmq-users mailing list and only sometimes answers questions on StackOverflow.
I have two apps on two computers. These apps are communicating by .NET Remoting.
First app acts as server for access to database, second app acts as client and writes that data to another database.
When my client calls some method on my remote object on server, I get following error:
A connection attempt failed because the connected party did not
properly respond after a period of time, or established connection
failed because connected host has failed to respond
192.168.200.60:31621
Well, that's nice, but I don't know anything about IP address 192.168.200.60, I was connecting to 172.XXX.XXX.216. It seems that there are two network connections and it's somehow not good for remoting.
ipcongif on my server look like that:
Exactly the same solution works on another 3 computers with Windows 2000, Windows XP and Windows 7. Server is developed in .NET Framework 2.0.
Client and server have common DLL library with two interfaces ICAOFactory and ICAO. First I create factory CAOFactory, which has method CreateCAO, which returns CAO object. When I call some method oh that ICAO object, it fails.
This is how my server app registers remoting object:
TcpChannel channel = new TcpChannel(31621);
ChannelServices.RegisterChannel(channel, false);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(My_Server.CAOFactory), "My_Server", WellKnownObjectMode.Singleton);
This is how my client creates remote object:
My_Share.ICAOFactory srvFactory;
My_Share.ICAO srvCAO;
srvFactory = (My_Share.ICAOFactory)Activator.GetObject(typeof(Foerster_Share.ICAOFactory), "tcp://" + ip + ":" + port + "/My_Server");
srvCAO = srvFactory.CreateCAO(); // no problem
srvCAO.Init(dateTime); // problem
This is my CAOFactory object:
public class CAOFactory : MarshalByRefObject, ICAOFactory
{
public ICAO CreateCAO()
{
ICAO CAOObj = new CAO();
return CAOObj;
}
public void GetClientCount(out long clientCountSum, out long clientCountMax, out long clientCountActive)
{
clientCountSum = 0;
clientCountMax = 0;
clientCountActive = 0;
return;
}
public override object InitializeLifetimeService()
{
return null;
}
}
This is my CAO object:
public class CAO : MarshalByRefObject, ICAO
{
public void Ping()
{
return;
}
DateTime dtInit;
public void Init(DateTime dt)
{
dtInit = dt;
}
// + some other methods
}
Any help greatly appreciated!
What version of .NET are you targeting?
I think you need to use the bindTo property of the TcpChannel class https://msdn.microsoft.com/en-us/library/bb187434(v=vs.85).aspx to tell your server to bind to the correct NIC. This is probably most easily done in the configuration. Does your server project have an app.config? If not add one then add a section like this to it (this is copy/pasted from this question .Net Remoting: Indicate which local interface to use to connect to one server)
<configuration>
<system.runtime.remoting>
<application>
<channels>
<channel ref="tcp" port="0" bindTo="172.xxx.xxx.xxx" />
</channels>
</application>
</system.runtime.remoting>
</configuration>
This will tell the server to bind to the specific IP address.
Reordering network connection priority helped in my case.
http://ecross.mvps.org/howto/change-network-connection-priority-in-windows-10.htm
Press the Windows Key + X and select Network Connections from the menu.
Press the ALT key, click Advanced and then Advanced Settings.
Select the network connection and click the arrows to give priority to the network connection.
Click Ok when you are done organizing the priority of the network connection. The computer will now follow an order when connections are available.
I want to do black-box testing of a messaging client library that uses the WindowsAzure.ServiceBus nuget package nuget package (docs) to send and receive messages to/from Microsoft ServiceBus queues.
My goal is to create integration tests for the messaging client library, but not communicate with an actual Microsoft Service Bus server.
Looking at the amqplite library, I was hoping that I could create an AMQP host using amqplite, and configure the messaging client library to communicate with this host, instead of an actual Microsoft Service Bus.
Here is my custom AMQP host, using amqplite:
public class LinkProcessor : ILinkProcessor
{
public void Process(AttachContext attachContext)
{
Console.WriteLine("LinkProcessor.Attach!");
}
}
var containerHost = new ContainerHost(new Uri("amqp://localhost:9876/"));
containerHost.RegisterLinkProcessor(new LinkProcessor());
containerHost.Open();
I register a ILinkProcessor on the containerHost so I can see on the console any connection attempts (based on my limited understanding of AMQP/AMQPlite this is what I believe a ILinkProcessor does).
The AMQP client below can connect, the server process outputs "LinkProcessor.Attach!" on the console.
async Task Main()
{
await SendMessage("q2", "hello world");
}
async Task SendMessage(string queue, string message)
{
var connection = await Connection.Factory.CreateAsync(new Address("amqp://localhost:9876/"));
var session = new Session(connection);
var msg = new Message(message);
var sender = new SenderLink(session, "sender-link", queue);
await sender.SendAsync(msg);
await sender.CloseAsync();
await session.CloseAsync();
await connection.CloseAsync();
}
Back to the messaging client library that I want to test:
The library is configured using a connection string, a working connection string looks like this (I assume the connection string format is one defined by WindowsAzure.ServiceBus):
Endpoint=sb://xxx/yyy;StsEndpoint=https://nnn:NNNN/xxx;RuntimePort=NNNN;ManagementPort=NNNN;OAuthUsername=xxx;OAuthPassword=yyy
I changed the config string to the following:
Endpoint=amqp://localhost:9876/q2
When I run the test client, the following happens:
The client throws an exception: You have tried to create a channel to a service that does not support .Net Framing.
I see no activity on the AMQPlite host end, i.e. no "LinkProcessor.Attach!" message on the console.
Question:
Is what I'm trying to accomplish possible? I.e. is there a way to configure a AMQPlite host so that it can accept connections from a WindowsAzure.ServiceBus client ?
I have a distributed system of actors, some on Windows, and some on Linux machine. Sometimes one actor may need to connect other actor and make some communications. Of course, there are cases when one of them is on Windows, and other is on Linux system.
Actors connect each other via ActorSelection. There problem is, that when Windows actor is trying to communicate with Linux one, all works fine. But when Linux actor initiating communication, the ActorSelection.ResolveOne failes.
I've made a little sample here:
static void Main(string[] args)
{
ActorSystem system = ActorSystem.Create("TestSystem");
system.ActorOf(Props.Create(() => new ConnectActor()), "test");
while (true)
{
var address = Console.ReadLine();
if (string.IsNullOrEmpty(address))
{
system.Terminate();
return;
}
var remoteAddress = $"akka.tcp://{system.Name}#{address}/user/test";
try
{
var actor = system.ActorSelection(remoteAddress).ResolveOne(TimeSpan.FromMilliseconds(5000)).Result;
Console.WriteLine("Resolved: " + actor.Path);
}
catch (Exception ex)
{
Console.WriteLine("Failed: " + ex.Message);
}
}
}
Configuration in app.config is the following:
akka {
loggers = ["Akka.Logger.NLog.NLogLogger, Akka.Logger.NLog"]
suppress-json-serializer-warning = on
loglevel = "DEBUG"
log-config-on-start = on
actor {
provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote"
debug {
receive = on
autoreceive = on
lifecycle = on
event-stream = on
unhandled = on
}
}
remote {
log-remote-lifecycle-events = DEBUG
log-received-messages = on
helios.tcp {
transport-class = "Akka.Remote.Transport.Helios.HeliosTcpTransport, Akka.Remote"
transport-protocol = tcp
applied-adapters = []
port = 9000
hostname = "0.0.0.0"
public-hostname = "192.168.0.251" // This is different for different hosts, of course
}
}
}
The public-hostname is publicly available ip address.
So, here are the cases:
When running Windows/Windows, both instances see each other (I give them remote address - they output "Resolved ")
When running Windows/Linux, and give linux actor's address to windows actor, it outputs "Resolved". So windows connects linux with no problem. After that giving windows actor's address to linux actor also gives "Resolved" - I suppose, the connection is already established and there is no real handshakes passing
BUT when running Windiws/Linux and give windows actor's address to linux actor, it gives "Failed". No messages about any errors or dropping packages. At the end of the log there is the following:
Akka.Remote.Transport.AkkaProtocolManager|now supervising akka://TestSystem/system/transports/akkaprotocolmanager.tcp.0/akkaProtocol-tcp%3A%2F%2FTestSystem%40%5B%3A%3Affff%3A192.168.0.252%5D%3A36983-1||||
13:20:08.3766|DEBUGAkka.Remote.Transport.ProtocolStateActor|Started (Akka.Remote.Transport.ProtocolStateActor)||||
13:20:08.3922|DEBUG|Akka.Remote.Transport.ProtocolStateActor|Stopped||||
The issue with similar logs is described here: Akka.net starting and stopping with no activity
The reason there is that system protocols are not compatible. Is this the same issue? As I got from Akka.NET docs and release notes, it has full linux support...
So, am I missing something in configuration? Can anybody make this sample work with Linux -> Windows connection?
The issue here appears to be that Mono is using an IPV6 address mapped to IPV4 in its bound address for some reason.
akka://TestSystem/system/transports/akkaprotocolmanager.tcp.0/akkaProtocol-tcp%3A%2F%2FTestSystem%40%5B%3A%3Affff%3A192.168.0.252%5D%3A36983-1
If you decode this URL that gets translated to
akkaProtocol-tcp://TestSystem#[::ffff:192.168.0.252]:36983-
So I think what is happening here is that outbound address Helios is supposed to parse from that is getting screwed up on the Linux side, so it attempts to connect to a mal-formed address that isn't the same as the one Windows listens on. Something platform-specific in the actor selection URI parsing code is incorrect I suspect.
I've filed a bug here: https://github.com/akkadotnet/akka.net/issues/2254
I'm building an EF6 web app in Azure and I'm using Azure Cache.
I'm testing calls to my WCF service and I'm getting wildly erratic response times - between 300ms and 15sec!
I configured my code according to the this example and it runs fine locally
I've debugged remotely and I can see that the cache key is being found and the data is getting called from cache, so I'm struggling to understand why there is sych a huge variation in response times. Most of the time it's 5+sec which is obviously waaay too long.
The example I've been testing is as follows:
WCF service GET request to:
http://feniksdev-staging.azurewebsites.net/EkckoNewsService.svc/getFriends
// Cache client configured by settings in application configuration file.
public DataCacheFactory cacheFactory = new DataCacheFactory();
public DataCache _cache;
public DataCache cache
{
get
{
if (_cache == null)
_cache = cacheFactory.GetDefaultCache();
return _cache;
}
set { }
}
...
...
[OperationContract]
[System.ServiceModel.Web.WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "/getFriends")]
public string getFriends()
{
string cachekey = "getFriends/{" + user.Id + "}";
object result = cache.Get(cachekey);
if (result == null)
{
using (EkckoContext entities = new EkckoContext())
{
var frnds = entities.UserConnections.Where(uc => uc.UserId == user.Id).Select(uc => new { Name = uc.Friend.Username }).ToList();
JsonSerializerSettings jsonSettings = new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects };
string json = JsonConvert.SerializeObject(frnds, jsonSettings);
cache.Add(cachekey, json);
return json;
}
}
else
{
return (string)result;
}
}
UserConnection is a simple table in my db and currently has no data, so the call returns an empty JSON array. user is a Session object and currently defaults to 1 for user.Id
When remote-debugging this, the object is found in cache and the cached object is returned. So all good, except the response time still varies by a factor of 20 (300ms - 6sec).
When remote debugging one of the other web service methods, I got the following error when attempting to access the cached object using the corresponding key (object result = cache.Get(cachekey);):
{"ErrorCode:SubStatus:There is a temporary failure. Please retry later. (One or more specified cache servers are unavailable, which could be caused by busy network or servers. For on-premises cache clusters, also verify the following conditions. Ensure that security permission has been granted for this client account, and check that the AppFabric Caching Service is allowed through the firewall on all cache hosts. Also the MaxBufferSize on the server must be greater than or equal to the serialized object size sent from the client.). Additional Information : The client was trying to communicate with the server: net.tcp://ekckodev.cache.windows.net:22238."}
I then set the maxBufferSize in my config as follows:
<configSections>
<section name="dataCacheClients" type="Microsoft.ApplicationServer.Caching.DataCacheClientsSection, Microsoft.ApplicationServer.Caching.Core" allowLocation="true" allowDefinition="Everywhere" />
<section name="cacheDiagnostics" type="Microsoft.ApplicationServer.Caching.AzureCommon.DiagnosticsConfigurationSection, Microsoft.ApplicationServer.Caching.AzureCommon" allowLocation="true" allowDefinition="Everywhere" />
</configSections>
...
...
<system.web>
...
...
<caching>
<outputCache defaultProvider="AFCacheOutputCacheProvider">
<providers>
<add name="AFCacheOutputCacheProvider" type="Microsoft.Web.DistributedCache.DistributedCacheOutputCacheProvider, Microsoft.Web.DistributedCache" cacheName="default" dataCacheClientName="default" applicationName="AFCacheOutputCache" />
</providers>
</outputCache>
</caching>
</system.web>
....
....
...
<dataCacheClients>
<dataCacheClient name="default">
<autoDiscover isEnabled="true" identifier="ekckodev.cache.windows.net" />
<localCache isEnabled="true" sync="TimeoutBased" objectCount="100000" ttlValue="300" />
<securityProperties mode="Message" sslEnabled="false">
<messageSecurity authorizationInfo="xxxxxxxxxxxxxxxxxxxxxxx" />
</securityProperties>
<transportProperties connectionBufferSize="131072" maxBufferPoolSize="268435456"
maxBufferSize="8388608" maxOutputDelay="2" channelInitializationTimeout="60000"
receiveTimeout="600000"/>
</dataCacheClient>
</dataCacheClients>
But I still get such erratic response times - particularly when hitting the same service call repeatedly.
After adding the maxbuffersize config, the cache calls are still hit-and-miss. some fetch the object; other times I get the same exception, however the port is different
"... The client was trying to communicate with the server: net.tcp://ekckodev.cache.windows.net:22233."}"
Could this be a firewall issue? If so, how do I open the appropriate ports?
I also just got the following exception when instantiating the DataCache object:
_cache = cacheFactory.GetDefaultCache();
ErrorCode:SubStatus:There is a temporary failure. Please retry later.
(One or more specified cache servers are unavailable, which could be caused by busy network or servers.
For on-premises cache clusters, also verify the following conditions. Ensure that security permission has
been granted for this client account, and check that the AppFabric Caching Service is allowed through the
firewall on all cache hosts. Also the MaxBufferSize on the server must be greater than or equal to the
serialized object size sent from the client.)
Any thoughts on why I'm getting such results? it's certainly no quicker WITH the cache than WIHTOUT it, so it appears there is some sort of latency in the cache which doesn't seem right...
Thanks in advance for any help!
UPDATE:
After doing some more searching, it seems I'm not the only one with this issue:
poor performance with azure cache
I find it hard to believe that this is the performance I should expect
UPDATE 2
I have commented out all cache-related code from my service and ran the same tests again. The response times are appreciably lower WITHOUT the cache! the "getFriends" callaverages about 250ms wihtout the cache, but peaks at over 5sec WITH the cache.
My other method that fetches about 4kb of data, was peaking at 20+ seconds with cache and now averages about 2sec WITHOUT the cache.
Again: I find it hard to believe that this is the performance I should expect
UPDATE 3
I have now scrapped Azure Cache in favour of MemoryCache. Nice example here
My service calls are now consistently taking approx 300ms in the browser.
I've opened a ticket with Microsoft Azure support regarding Azure Cache, so I'll update this post when they get in touch and I've asked them why their cache is so rubbish. Just when my faith in Microsoft was climbing :/
Looks like you've arrived at the correct conclusion, which is don't use Azure Managed Cache. About 6 months ago, Microsoft started recommending all new development be done against their Redis-based cache offering in Azure.
We recommend all new developments use Azure Redis Cache.
Strangely, they don't show the option to create a Redis cache in the 'old' Azure management site (manage.windowsazure.com), but they do have it in the "preview" Azure management portal.