0

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
    {
        ...
    });
Sergey
  • 11
  • 4
  • _“i'm afraid that one instance of Business assembly may send message to microservice, but second instance of Business assembly may receive the message from microservice”_ – I don’t understand this. Are you saying the same app receives the message it sends? Can you explain that more thoroughly? Also, since the “business assembly” is just a library but not a running application, please talk about which application/service is actually running instead. – poke Sep 17 '20 at 18:54
  • 1
    Not quite sure either what you mean. When a produce sends messages to a bus or queue, it doesn't wait for the consumer to receive and process the message. That would defile the whole purpose of a message queue. The produce sends the message not knowing who will receive it. And the consumer will process the message without knowing who sent it. Another thing to consider is that when working with queue, your logic must be [idempotent](https://stackoverflow.com/questions/1077412/what-is-an-idempotent-operation#:~:text=Idempotence%20means%20that%20applying%20an,the%20result%20is%20still%20zero.) – Michael Sep 17 '20 at 19:03
  • @poke I just moved code for working with RabbitMq to separated class library and use this library in web api app and in razor pages app. Another words, i have two instance of the same running simultaneously code, that works with rabbitmq. – Sergey Sep 17 '20 at 19:04
  • Okay, I think I got what you are asking. The two processes communicate through RabbitMQ in a duplex manner. One service sends messages and receives messages and so does the other service. Correct? – Michael Sep 17 '20 at 19:07
  • If the above is correct, you will need two queues. One to send from A to B and another to send from B to A. At least that is how I would do it. – Michael Sep 17 '20 at 19:08
  • @Michael you right. One more concern about following code running in two instances: var enableResult = await _bus.RequestAsync( new ContactRequest { ... }); Is it possible that one instance make request and second instance receives responce? – Sergey Sep 17 '20 at 19:10
  • @Michael **If the above is correct, you will need two queues. One to send from A to B and another to send from B to A.** I have, business sends to microservice using the one queue, microservice responds using another queue. – Sergey Sep 17 '20 at 19:13
  • I can't see how that could happen if you have two queues, but again it's hard to tell without getting the full picture. Could you write some tests that verifies that everything works as intended? – Michael Sep 17 '20 at 19:27

0 Answers0