Good time, Stack Overflow community.
I have some questions about software architecture i'm working on and i will appreciate for help with them.
The components of the app are following:
- Model project (net core class library). Here i define model classes & database context.
- Business project (net core class library). It has reference on the Model assembly and implements business logic. Also here, placed a HostedService with code for working with microservices through EasyNetQ using Send/Receive & Request/Response patterns.
- Web API project (net core web api app). It uses Business assembly and provides web api features. This app hosted on iis 10.
- Web frontend project (net core razor web app). It also uses Business assembly and provides web UI features. This app hosted on iis 10.
- Some microservice apps, that may communicate with Business assembly through EasyNetQ by receiving and sending messages. Every microservice runs in the one instance.
Web api app and web frontend app both working simultaneously. So we have two instances of business logic assembly working at the same time and both of them works with the same rabbitmq queues.
So, i'm afraid that one instance of Business assembly may send message to microservice (IBus.Send), but second instance of Business assembly may receive the message from microservice (IBus.Receive). In this case, as i understand, may be collision because the first instance of Business waits answer and does not receive it, at the same time second instance of Business receives not waitable answer.
A bit of code.
Web api app startup:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddBusiness(Configuration);
...
}
Web frontend app startup:
public void ConfigureServices(IServiceCollection services)
{
services.AddBusiness(Configuration);
...
}
Business logic assembly startup:
public static IServiceCollection AddBusiness(this IServiceCollection services, IConfiguration configuration)
{
...
services.AddSingleton(sp =>
{
var rabbitMqSettings = sp.GetRequiredService<IOptions<RabbitMqSettings>>();
return RabbitHutch.CreateBus(rabbitMqSettings.Value.Connection);
});
services.AddHostedService<RabbitMessagesReceiverService>();
return services;
}
Business logic assembly EasyNetQ code examples:
public class RabbitMessagesReceiverService : BackgroundService
{
readonly IBus _bus;
public RabbitMessagesReceiverService(IBus bus)
{
_bus = bus;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
// receives messages from microservice
_bus.Receive<OutgoingResult>(RabbitHelper.OUTGOING_RESPONSE, async response =>
{
...
}
}
}
or
// sends message to microservice
await _bus.SendAsync<OutgoingRequest>(RabbitHelper.OUTGOING_REQUEST, new OutgoingRequest
{
...
});