rebus-org / Rebus.RabbitMq

:bus: RabbitMQ transport for Rebus
https://mookid.dk/category/rebus
Other
63 stars 44 forks source link

Could not resolve Rebus.Bus.IBus; connection.start was never received, likely due to a network timeout; #70

Closed dekrevedko closed 3 years ago

dekrevedko commented 4 years ago

Hi, I have a weird issue with Rebus and RabbitMQ. I tried a simple example:

                        using (var activator = new BuiltinHandlerActivator())
            {
                // add handler for MyEvent
                activator.Handle<MyEvent>(async message => {
                    // handle event in here
                });

                // configure subscriber
                var subscriber = Configure.With(activator)
                    .Transport(t => t.UseRabbitMq("amqps://user:pswd@server:443/vhost", "testv"))
                    .Start();

                await subscriber.Subscribe<MyEvent>();
                                Console.WriteLine("Press ENTER to quit");
                Console.ReadLine();
            }

And face with exception:

Rebus.Injection.ResolutionException HResult=0x80131500 Message=Could not resolve Rebus.Bus.IBus with decorator depth 0 - registrations: Rebus.Injection.Injectionist+Handler Source=Rebus StackTrace: at Rebus.Injection.Injectionist.ResolutionContext.Get[TService]() at Rebus.Injection.Injectionist.Get[TService]() at Rebus.Config.RebusConfigurer.Start() at ConsoleApp1.Program.

d__0.MoveNext() in C:\Projects\tries\Rebus\ConsoleApp1\Program.cs:line 20

This exception was originally thrown at this call stack: [External Code]

Inner Exception 1: BrokerUnreachableException: None of the specified endpoints were reachable at RabbitMQ.Client.ConnectionFactory.CreateConnection(IEndpointResolver endpointResolver, String clientProvidedName) at RabbitMQ.Client.ConnectionFactory.CreateConnection(IList1 endpoints) at Rebus.Internals.ConnectionManager.GetConnection() at Rebus.RabbitMq.RabbitMqTransport.CreateQueue(String address) at Rebus.RabbitMq.RabbitMqTransport.Initialize() at Rebus.Config.RebusConfigurer.<>c__DisplayClass13_0.<Start>b__28(IResolutionContext c) at Rebus.Injection.Injectionist.Resolver1.InvokeResolver(IResolutionContext context) at Rebus.Injection.Injectionist.ResolutionContext.Get[TService]()

Inner Exception 2: IOException: connection.start was never received, likely due to a network timeout at RabbitMQ.Client.Framing.Impl.Connection.StartAndTune() at RabbitMQ.Client.Framing.Impl.Connection.Open(Boolean insist) at RabbitMQ.Client.Framing.Impl.Connection..ctor(IConnectionFactory factory, Boolean insist, IFrameHandler frameHandler, String clientProvidedName) at RabbitMQ.Client.Framing.Impl.AutorecoveringConnection.Init(IFrameHandler fh) at RabbitMQ.Client.Framing.Impl.AutorecoveringConnection.Init(IEndpointResolver endpoints) at RabbitMQ.Client.ConnectionFactory.CreateConnection(IEndpointResolver endpointResolver, String clientProvidedName)

But at the same time, Rabbit client example with the same connection string works well.

            var factory = new ConnectionFactory()
            {
                Uri = new Uri("amqps://user:pswd@server:443/vhost")
            };

            using var connection = factory.CreateConnection();

            using(var channel = factory.CreateConnection().CreateModel())
            {
                channel.QueueDeclare(queue: "testv",
                                     durable: true,
                                     exclusive: false,
                                     autoDelete: false,
                                     arguments: null);

                channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);

                var consumer = new EventingBasicConsumer(channel);

                consumer.Received += (model, ea) =>
                {
                    Console.WriteLine($"msg received");
                };

                channel.BasicConsume(queue: "hello",
                                     autoAck: false,
                                     consumer: consumer);              

                Console.ReadLine();
            }

RabbitMQ.Client 5.1.1 and 5.2.0 were tried.

mookid8000 commented 4 years ago

Ok, weird!

I can see that the Rebus code differs from your code in that it provides a list of AMQP endpoints when it calls CreateConnection on the connection factory.

image

The list of AMQP endpoints comes from this mapping, which seems to cause information about the scheme and the basic auth credentials to be lost.

Do you know the correct way to handle automatic failover?

dekrevedko commented 4 years ago

I see only one way, manually set properties to the factory. Like:

_connectionFactory.Port = 443;
_connectionFactory.UserName = "user";
_connectionFactory.Password = "pswd";
_connectionFactory.VirtualHost = "vhost";
_connectionFactory.Ssl = new SslOption(){...}

Of cause, all these options will be the same for all servers on the list. Fortunately, it can be done by CustomizeConnectionFactory. And one observation: Uri property from CustomizeConnectionFactory does not replace (or added) to the host list.

mookid8000 commented 4 years ago

Do I understand correctly that you made it work?

dekrevedko commented 3 years ago

Hi, sorry for the delay. Yes, it works. The only issue is I can't use ClientConnectionName with CustomizeConnectionFactory. May be, connection name should be added to CustomizeConnectionFactory.