I'm trying to build a small AKka.NET Cluster Application but I'm having problems since I keep getting the following error:
[WARNING][7/14/2022 10:42:06 AM][Thread 0011][akka.tcp://accountsystem#localhost:57959/system/cluster/core/daemon/joinSeedNodeProcess-1] Couldn't join seed nodes after [2] attempts, will try again. seed-nodes=[akka.tcp://accountsystem#localhost:2551]
This is my docker-compose file for my lighthouse service:
version: '3'
services:
accountsystem.lighthouse:
image: petabridge/lighthouse:latest
hostname: accountsystem.lighthouse
ports:
- '2551:2551'
environment:
ACTORSYSTEM: "accountsystem"
CLUSTER_PORT: 2551
CLUSTER_IP: "accountsystem.lighthouse"
CLUSTER_SEEDS: "akka.tcp://accountsystem#accountsystem.lighthouse:2551"
And this is my AKka.NET configuration:
<![CDATA[
akka {
actor {
provider = cluster
}
remote {
log-remote-lifecycle-events = DEBUG
dot-netty.tcp {
hostname = "localhost"
port = 0
}
}
cluster {
seed-nodes = [
"akka.tcp://accountsystem#localhost:2551"]
#auto-down-unreachable-after = 30s
}
}
]]>
Also I am sharing my code setup for my AKkaService:
public Task StartAsync(CancellationToken cancellationToken)
{
var akkaConfig = (AkkaConfigurationSection) System.Configuration.ConfigurationManager.GetSection("akka");
var bootstrap = BootstrapSetup.Create()
.WithConfig(akkaConfig.AkkaConfig)
.WithActorRefProvider(ProviderSelection.Cluster.Instance); // launch Akka.Cluster
// enable DI support inside this ActorSystem, if needed
var diSetup = DependencyResolverSetup.Create(_serviceProvider);
// merge this setup (and any others) together into ActorSystemSetup
var actorSystemSetup = bootstrap.And(diSetup);
// start ActorSystem
_actorSystem = ActorSystem.Create("accountsystem", actorSystemSetup);
var props = DependencyResolver.For(_actorSystem).Props<AccountRouterActor>();
_actorRef = _actorSystem.ActorOf(props, "account");
_actorSystem.WhenTerminated.ContinueWith(tr => {
_applicationLifetime.StopApplication();
});
return Task.CompletedTask;
}
I have been reading about actor system and server mismatch, but I think the name is correct which would be accountsystem. I am also sharing my console after starting up my docker compose file with all the messages. Maybe that will help.
docker-compose up
WARNING: Found orphan containers (accountpoc_mssql_1, mysql) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up.
Starting accountpoc_accountsystem.lighthouse_1 ... done
Attaching to accountpoc_accountsystem.lighthouse_1
accountsystem.lighthouse_1 | [Docker-Bootstrap] IP=accountsystem.lighthouse
accountsystem.lighthouse_1 | [Docker-Bootstrap] PORT=2551
accountsystem.lighthouse_1 | [Docker-Bootstrap] SEEDS=["akka.tcp://accountsystem#accountsystem.lighthouse:2551"]
accountsystem.lighthouse_1 | [Lighthouse] ActorSystem: accountsystem; IP: accountsystem.lighthouse; PORT: 2551
accountsystem.lighthouse_1 | [Lighthouse] Performing pre-boot sanity check. Should be able to parse address [akka.tcp://accountsystem#accountsystem.lighthouse:2551]
accountsystem.lighthouse_1 | [Lighthouse] Parse successful.
accountsystem.lighthouse_1 | [INFO][07/14/2022 10:52:48][Thread 0001][remoting (akka://accountsystem)] Starting remoting
accountsystem.lighthouse_1 | [INFO][07/14/2022 10:52:48][Thread 0001][remoting (akka://accountsystem)] Remoting started; listening on addresses : [akka.tcp://accountsystem#accountsystem.lighthouse:2551]
accountsystem.lighthouse_1 | [INFO][07/14/2022 10:52:48][Thread 0001][remoting (akka://accountsystem)] Remoting now listens on addresses: [akka.tcp://accountsystem#accountsystem.lighthouse:2551]
accountsystem.lighthouse_1 | [INFO][07/14/2022 10:52:48][Thread 0001][Cluster (akka://accountsystem)] Cluster Node [akka.tcp://accountsystem#accountsystem.lighthouse:2551] - Starting up...
accountsystem.lighthouse_1 | [INFO][07/14/2022 10:52:48][Thread 0001][Cluster (akka://accountsystem)] Cluster Node [1.6.2] - Node [akka.tcp://accountsystem#accountsystem.lighthouse:2551] is JOINING itself (with roles [lighthouse], version [1.6.2]) and forming a new cluster
accountsystem.lighthouse_1 | [INFO][07/14/2022 10:52:48][Thread 0001][Cluster (akka://accountsystem)] Cluster Node [akka.tcp://accountsystem#accountsystem.lighthouse:2551] - is the new leader among reachable nodes (more leaders may exist)
accountsystem.lighthouse_1 | [INFO][07/14/2022 10:52:48][Thread 0001][Cluster (akka://accountsystem)] Cluster Node [akka.tcp://accountsystem#accountsystem.lighthouse:2551] - Leader is moving node [akka.tcp://accountsystem#accountsystem.lighthouse:2551] to [Up]
accountsystem.lighthouse_1 | [INFO][07/14/2022 10:52:49][Thread 0001][Cluster (akka://accountsystem)] Cluster Node [akka.tcp://accountsystem#accountsystem.lighthouse:2551] - Started up successfully
accountsystem.lighthouse_1 | [INFO][07/14/2022 10:52:49][Thread 0001][akka.tcp://accountsystem#accountsystem.lighthouse:2551/user/petabridge.cmd] petabridge.cmd host bound to [0.0.0.0:9110]
accountsystem.lighthouse_1 | [ERROR][07/14/2022 10:52:58][Thread 0008][akka.tcp://accountsystem#accountsystem.lighthouse:2551/system/endpointManager/reliableEndpointWriter-akka.tcp%3A%2F%2Faccountsystem%40localhost%3A59968-1/endpointWriter] Dropping message [Akka.Actor.ActorSelectionMessage] for non-local recipient [[akka.tcp://accountsystem#localhost:2551/]] arriving at [akka.tcp://accountsystem#localhost:2551] inbound addresses [akka.tcp://accountsystem#accountsystem.lighthouse:2551]
accountsystem.lighthouse_1 | [ERROR][07/14/2022 10:53:02][Thread 0008][akka.tcp://accountsystem#accountsystem.lighthouse:2551/system/endpointManager/reliableEndpointWriter-akka.tcp%3A%2F%2Faccountsystem%40localhost%3A59968-1/endpointWriter] Dropping message [Akka.Actor.ActorSelectionMessage] for non-local recipient [[akka.tcp://accountsystem#localhost:2551/]] arriving at [akka.tcp://accountsystem#localhost:2551] inbound addresses [akka.tcp://accountsystem#accountsystem.lighthouse:2551]
accountsystem.lighthouse_1 | [ERROR][07/14/2022 10:53:08][Thread 0008][akka.tcp://accountsystem#accountsystem.lighthouse:2551/system/endpointManager/reliableEndpointWriter-akka.tcp%3A%2F%2Faccountsystem%40localhost%3A59968-1/endpointWriter] Dropping message [Akka.Actor.ActorSelectionMessage] for non-local recipient [[akka.tcp://accountsystem#localhost:2551/]] arriving at [akka.tcp://accountsystem#localhost:2551] inbound addresses [akka.tcp://accountsystem#accountsystem.lighthouse:2551]
accountsystem.lighthouse_1 | [WARNING][07/14/2022 10:53:10][Thread 0008][akka.tcp://accountsystem#accountsystem.lighthouse:2551/system/endpointManager/reliableEndpointWriter-akka.tcp%3A%2F%2Faccountsystem%40localhost%3A59968-1] Association with remote system akka.tcp://accountsystem#localhost:59968 has failed; address is now gated for 5000 ms. Reason is: [Akka.Remote.EndpointDisassociatedException: Disassociated
accountsystem.lighthouse_1 | at Akka.Remote.EndpointWriter.PublishAndThrow(Exception reason, LogLevel level, Boolean needToThrow)
accountsystem.lighthouse_1 | at Akka.Remote.EndpointWriter.Unhandled(Object message)
accountsystem.lighthouse_1 | at Akka.Actor.UntypedActor.Receive(Object message)
accountsystem.lighthouse_1 | at Akka.Actor.ActorBase.AroundReceive(Receive receive, Object message)
accountsystem.lighthouse_1 | at Akka.Actor.ActorCell.ReceiveMessage(Object message)
accountsystem.lighthouse_1 | at Akka.Actor.ActorCell.ReceivedTerminated(Terminated t)
accountsystem.lighthouse_1 | at Akka.Actor.ActorCell.AutoReceiveMessage(Envelope envelope)
accountsystem.lighthouse_1 | at Akka.Actor.ActorCell.Invoke(Envelope envelope)]
accountsystem.lighthouse_1 | [ERROR][07/14/2022 10:53:10][Thread 0008][akka://accountsystem/system/endpointManager/reliableEndpointWriter-akka.tcp%3A%2F%2Faccountsystem%40localhost%3A59968-1/endpointWriter] Disassociated
accountsystem.lighthouse_1 | Cause: Akka.Remote.EndpointDisassociatedException: Disassociated
accountsystem.lighthouse_1 | at Akka.Remote.EndpointWriter.PublishAndThrow(Exception reason, LogLevel level, Boolean needToThrow)
accountsystem.lighthouse_1 | at Akka.Remote.EndpointWriter.Unhandled(Object message)
accountsystem.lighthouse_1 | at Akka.Actor.UntypedActor.Receive(Object message)
accountsystem.lighthouse_1 | at Akka.Actor.ActorBase.AroundReceive(Receive receive, Object message)
accountsystem.lighthouse_1 | at Akka.Actor.ActorCell.ReceiveMessage(Object message)
accountsystem.lighthouse_1 | at Akka.Actor.ActorCell.ReceivedTerminated(Terminated t)
accountsystem.lighthouse_1 | at Akka.Actor.ActorCell.AutoReceiveMessage(Envelope envelope)
accountsystem.lighthouse_1 | at Akka.Actor.ActorCell.Invoke(Envelope envelope)
Well, I just had to change the hocon configuration to the following:
<![CDATA[
akka {
actor {
provider = cluster
}
remote {
log-remote-lifecycle-events = DEBUG
dot-netty.tcp {
hostname = "localhost"
port = 2551
}
}
cluster {
seed-nodes = [
"akka.tcp://accountsystem#localhost:2551"]
#auto-down-unreachable-after = 30s
}
}
]]>
In order for these environment variables to work:
CLUSTER_PORT: 2551
CLUSTER_IP: "accountsystem.lighthouse"
CLUSTER_SEEDS: "akka.tcp://accountsystem#accountsystem.lighthouse:2551"
You'll need to install https://github.com/petabridge/akkadotnet-bootstrap/tree/dev/src/Akka.Bootstrap.Docker and call BootstrapFromDocker() on your Config object. That's what Lighthouse is doing internally.
You might also find using Akka.Cluster.Hosting to be an easier way of doing this since you can now extract those values from a typed Microsoft.Extensions.Configuration section and pass them in programmatically to the WithRemoting and WithClustering methods ala:
builder.Services.AddAkka("MyActorSystem", configurationBuilder =>
{
configurationBuilder
.WithRemoting("localhost", 8110)
.WithClustering(new ClusterOptions(){ Roles = new[]{ "myRole" },
SeedNodes = new[]{ Address.Parse("akka.tcp://MyActorSystem#localhost:8110")}})
.WithActors((system, registry) =>
{
var echo = system.ActorOf(act =>
{
act.ReceiveAny((o, context) =>
{
context.Sender.Tell($"{context.Self} rcv {o}");
});
}, "echo");
registry.TryRegister<Echo>(echo); // register for DI
});
});
Related
I am trying to connect with one activeMQ host using vertx (vertx client does not support failover, then I am trying do it manually):
And if the connection fail, I am trying to connect to second Host:
The connection method is:
private fun connectClient(vertx: Vertx, host: String, options: AmqpClientOptions,
address: String): Single<MQServerConnection> =
AmqpClient.create(vertx, options).rxConnect().flatMap { amqpConnection ->
amqpConnection.rxCreateDynamicReceiver().flatMap { receiver ->
amqpConnection.rxCreateSender(address).map { sender ->
MQServerConnection(amqpConnection, sender, receiver, host)
}
}
}
And i am calling using:
connectClient(vertx, host1, options, address).doOnError {
logger.warn("CONNECTION_REFUSED_WITH_HOST_[$host1]")
options = getConnectionOptions(host2)
connectClient(vertx, host2, options, address).doOnError {
Single.error<Connection>(Exception("Error"))
}
}
But if fails the connection with host1 the connection is opened, because i Am getting connecting with host2:
Caused by: io.netty.channel.AbstractChannel$AnnotatedConnectException: Conexión rehusada: HOSTXXX/54.166.103.68:5671
Caused by: java.net.ConnectException: Conexión rehusada
How can I avoid this error in the connection, because i don't have connection because it fail
Is there any provision to push message between two "Queues" by change the Queue name dynamically in cloud.stream #Input("suffix"+"SampleQueueA") and #Input("suffix"+"SampleQueueB")
This use case with Sprig cloud stream using messaging server RabbitMQ.
I tried pushing messages into two different Queues by dynamically changing the Queue name.
# Input bindings used for testing
spring:
rabbitmq:
host: 127.0.0.1
virtual-host: /defaultVH
username: guest
password: guest
cloud:
stream:
bindings:
ClientSampleQueueA:
binder: rabbit-A
contentType: application/x-java-object
group: groupA
destination: ClientSampleQueueA
VendorSampleQueueA:
binder: rabbit-A
contentType: application/x-java-object
group: groupA
destination: VendorSampleQueueA
# cloud.stream.bindings.input1.destination: customerId-1
# spring.cloud.stream.bindings.input2.destination: customerId-2
binders:
rabbit-A:
defaultCandidate: false
inheritEnvironment: false
type: rabbit
environment:
spring:
rabbitmq:
host: 127.0.0.1
virtualHost: /vhA
username: guest
password: guest
port: 5672
connection-timeout: 10000
interface Sink {
String INPUT1 = "ClientSampleQueueA";
String INPUT2 = "VendorSampleQueueA";
#Input(INPUT1)
SubscribableChannel input1();
#Input(INPUT2)
SubscribableChannel input2();
}
#Bean(name = "sourceChannel")
public MessageChannel localChannel() {
return new DirectChannel();
}
#Autowired
#Qualifier("sourceChannel")
private MessageChannel localChannel;
Want to resolve the Queue dynamically by Object parameter.
private void sendMessage(Object body, Object contentType) {
localChannel.send(MessageBuilder.createMessage(body,
new MessageHeaders(Collections.singletonMap(MessageHeaders.CONTENT_TYPE, contentType))));
}
But what is subscribed to localChannel.
As I said in my comment:
spring.cloud.stream.bindings.ClientSampleQueueA.destination=commonDest
spring.cloud.stream.bindings.ClientSampleQueueA.group=ClientSampleQueueA
spring.cloud.stream.rabbit.bindings.ClientSampleQueueA.bindingRoutingKey=ClientSampleQueueA
spring.cloud.stream.bindings.VendorSampleQueueA.destination=commonDest
spring.cloud.stream.rabbit.bindings.VendorSampleQueueA.bindingRoutingKey=VendorSampleQueueA
spring.cloud.stream.bindings.VendorSampleQueueA.group=ClientSampleQueueA
and
spring.cloud.stream.bindings.sourceChannel.destination=commonDest
spring.cloud.stream.rabbit.bindings.sourceChannel.routingKeyExpression=headers.routeTo
and then
private void sendMessage(Object body, Object contentType) {
localChannel.send(MessageBuilder.withPayload(body)
.setHeader(MessageHeaders.CONTENT_TYPE, contentType)
.setHeader("routeTo", "VendorSampleQueueA")
.build();
}
Is it possible to configure MassTransit to not create a RabbitMQ exchange for a consumer host? My RabbitMQ user has not enough rights to declare an exchange at the host where the consuming queue is located, so MassTransit fails to start with the following error:
Unhandled Exception: MassTransit.RabbitMqTransport.RabbitMqConnectionException:
Operation interrupted ---> RabbitMQ.Client.Exceptions.OperationInterruptedExcept
ion: The AMQP operation was interrupted: AMQP close-reason, initiated by Peer, c
ode=403, text="ACCESS_REFUSED - access to exchange '***' i
n vhost '***' refused for user '***'", classId=
40, methodId=10, cause=
Here is the code that I use:
var bus = Bus.Factory.CreateUsingRabbitMq(sbc =>
{
var host = sbc.Host(host: "***", port: 5671, virtualHost: "***", configure: configurator =>
{
configurator.UseSsl(sslConfigurator =>
{
sslConfigurator.Certificate = certificate;
sslConfigurator.UseCertificateAsAuthenticationIdentity = true;
sslConfigurator.ServerName = "***";
});
});
sbc.ReceiveEndpoint(host, "***", endpointConfigurator =>
{
endpointConfigurator.Consumer<UpdateCustomerConsumer>();
});
});
rabbit connection from console app :
var factory = new ConnectionFactory()
{
HostName = Environment.GetEnvironmentVariable("RabbitMq/Host"),
UserName = Environment.GetEnvironmentVariable("RabbitMq/Username"),
Password = Environment.GetEnvironmentVariable("RabbitMq/Password")
};
using (var connection = factory.CreateConnection()) // GETTING ERROR HERE
using (var channel = connection.CreateModel())
{
channel.QueueDeclare(queue: "rss",
durable: fa...
I'm getting this error :
Unhandled Exception:
RabbitMQ.Client.Exceptions.BrokerUnreachableException: None of the
specified endpoints were reachable --->
RabbitMQ.Client.Exceptions.ConnectFailureException: Connection failed
---> System.Net.Internals.SocketExceptionFactory+ExtendedSocketException:
Connection refused 127.0.0.1:5672
my docker-compose.yml file :
version: '3'
services:
message.api:
image: message.api
build:
context: ./message_api
dockerfile: Dockerfile
container_name: message.api
environment:
- "RabbitMq/Host=rabbit"
- "RabbitMq/Username=guest"
- "RabbitMq/Password=guest"
depends_on:
- rabbit
rabbit:
image: rabbitmq:3.7.2-management
hostname: rabbit
ports:
- "15672:15672"
- "5672:5672"
rsscomparator:
image: rsscomparator
build:
context: ./rss_comparator_app
dockerfile: Dockerfile
container_name: rsscomparator
environment:
- "RabbitMq/Host=rabbit"
- "RabbitMq/Username=guest"
- "RabbitMq/Password=guest"
depends_on:
- rabbit
I'm using dotnetcore console app. When I use this app in docker I'm getting error. I can reach rabbitmq web browser(http://192.168.99.100:15672) but app can not reach.
You are trying to connect from your container app to your rabbitmq app.
You try to achieve this with 127.0.0.1:5672 in your console app container.
But this is pointing to your localhost inside this container, and not to your localhost on your host.
You are deploying your services using the same docker-compose without specifying network settings which means they are all deployed inside the same docker bridge network. This will allow you to let the containers communicate with each other using their container or service names.
So try to connect to rabbit:5672 instead of 127.0.0.1:5672. This name will be translated to the container IP (172.xx.xx.xx) which means you'll create a private connection between your containers.
I created a simple .net core console application with docker support. Following
Masstransit code fails to connect to RabbitMQ instance on host machine. But similar implementation using RabitMq.Client is able to connect to host machine RabbitMQ instance.
Masstransit throws
MassTransit.RabbitMqTransport.RabbitMqConnectionException: Connect
failed: ctas#192.168.0.9:5672/ --->
RabbitMQ.Client.Exceptions.BrokerUnreachableException:
host machine ip : 192.168.0.9
using Masstransit
string rabbitMqUri = "rabbitmq://192.168.0.9/";
string userName = "ctas";
string password = "ctas#123";
string assetServiceQueue = "hello";
var bus = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
var host = cfg.Host(new Uri(rabbitMqUri), hst =>
{
hst.Username(userName);
hst.Password(password);
});
cfg.ReceiveEndpoint(host,
assetServiceQueue, e =>
{
e.Consumer<AddNewAssetReceivedConsumer>();
});
});
bus.Start();
Console.WriteLine("Service Running.... Press enter to exit");
Console.ReadLine();
bus.Stop();
Using RabbitMQ Client
public static void Main()
{
var factory = new ConnectionFactory();
factory.UserName = "ctas";
factory.Password = "ctas#123";
factory.VirtualHost = "watcherindustry";
factory.HostName = "192.168.0.9";
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
channel.QueueDeclare(queue: "hello",
durable: false,
exclusive: false,
autoDelete: false,
arguments: null);
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var body = ea.Body;
var message = Encoding.UTF8.GetString(body);
Console.WriteLine(" [x] Received {0}", message);
};
channel.BasicConsume(queue: "hello",
autoAck: true,
consumer: consumer);
Console.WriteLine(" Press [enter] to exit.");
Console.ReadLine();
}
}
Docker file
FROM microsoft/dotnet:1.1-runtime
ARG source
WORKDIR /app
COPY ${source:-obj/Docker/publish} .
ENTRYPOINT ["dotnet", "TestClient.dll"]
I created an example, and was able to connect my host, using the preview package from masstransit.
Start rabbitmq in docker and expose ports on the host
docker run -d -p 5672:5672 -p 15672:15672 --hostname my-rabbit --name some-rabbit rabbitmq:3-management
Build and run console app.
docker build -t dotnetapp .
docker run -d -e RABBITMQ_URI=rabbitmq://guest:guest#172.17.0.2:5672 --name some-dotnetapp dotnetapp
To verify your receiving messages run
docker logs some-dotnetapp --follow
you should see the following output
Application is starting...
Connecting to rabbitmq://guest:guest#172.17.0.2:5672
Received: Hello, World [08/12/2017 04:35:53]
Received: Hello, World [08/12/2017 04:35:58]
Received: Hello, World [08/12/2017 04:36:03]
Received: Hello, World [08/12/2017 04:36:08]
Received: Hello, World [08/12/2017 04:36:13]
...
Notes:
172.17.0.2 was my-rabbit container ip address but you can replace it with your machine ip address
http://localhost:15672 is the rabbitmq management console log in with guest as username and password.
Lastly portainer.io is a very useful application to visually view you local docker environment.
Thanks for the response. I managed to resolve this issue. My findings are as follows.
to connect to a rabbitmq instance on another docker container, they have to be moved/connected to the same network. To do this
create a newtork
docker network create -d bridge my_bridge
connect both app and rabbitmq containers to same network
docker network connect my_bridge <container name>
For masstransit uri use rabbitmq container IP on that network or container name
To connect rabbitmq instance of host machine from a app on docker container.
masstransit uri should include machine name( I tried IP, that did not work)
Try using virtual host in MassTransit configuration too, not sure why you decided to omit it.
var host = cfg.Host("192.168.0.9", "watcherindustry", hst =>
{
hst.Username(userName);
hst.Password(password);
});
Look at Alexey Zimarev comment to your question, if your rabbit runs on a container then it should be on your docker-compese file and then use that entry in your endpoint definition to connect to rabbit because docker creates an internal network on which you are agnostic from source code...
rabbitmq:
container_name: "rabbitmq-yournode01"
hostname: rabbit
image: rabbitmq:3.6.6-management
environment:
- RABBITMQ_DEFAULT_USER=yourusergoeshere
- RABBITMQ_DEFAULT_PASS=yourpasswordgoeshere
- RABBITMQ_DEFAULT_VHOST=vhost
volumes:
- rabbit-volume:/var/lib/rabbitmq
ports:
- "5672:5672"
- "15672:15672"
In your app settings you should have something lie:
"ConnectionString": "host=rabbitmq:5672;virtualHost=vhost;username=yourusergoeshere;password=yourpasswordgoeshere;timeout=0;prefetchcount=1",
And if you'd use EasyNEtQ you could do:
_bus = RabbitHutch.CreateBus(_connectionString); // The one above
I hope it helps,
Juan