Open Closed

General architecture questions #1946


0
rcalv002 created
  • ABP Framework version: vX.X.X
  • UI type: MVC
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): no
  • Exception message and stack trace:
  • Steps to reproduce the issue:"

Hi!

I have some general architecture questions. I'm starting a new project on 4.4.3. The idea is that this will be a multitenant sas app. I will create several modules under the main application, each module will be for a specific webcart software, for example magento, shopify, etc. The implementation of the endpoints that remote carts will call and domain data for each of these is contained inside the module. When new data comes in ( new orders for example ) the module will kick off a distributed event (these will be local initially but the code should work for when we move to microservice, per the docs). The main application then subscribes to these events and should record the transaction locally on abp database, and then schedule and process a background job (using the hangfire implementation) that posts the transactions into the appropriate remote backend.

Does this make sense to do? Also since the background jobs seems to be picked up from the queue sequentially and there could be many jobs and tenants, would we run into a problem where there could be a ton of transactions queued and they'd only be processed sequentially so a particular tenant could see huge delays getting their transactions in?

A bigger concern is the fact that creating a bunch of httpclients to make the outgoing requests to the remote backends could cause resource exhaustion. In the past I've used an httpclient in DI to make the requests, however there's a problem here, and that is that each tenant will configure via settings management their remote backend url, these are different servers (but all the same software so contracts are the same). When the transaction is processed and send to the remote backend, the url will be different because they are different servers. To complicate matters most, the remote backend requires Login -> Receive SesssionID -> Then send this in the header of every subsequent request. In non multi-tenant implementations where its only one backend the application is sending these requests to, i simply use an interceptor to modify the header on the outgoing request.In multi-tenant I assume the best thing to do would be to login -> send to redis cache for the tenant, and check this each time in the future when a request needs to go out and its for a particular tenant ID.

I'm looking for any suggestion on how to accomplish this reliably without collapsing the application, keeping in mind that thousands of transactions can be posted in to the abp app, from different web carts, from different tenants.

I know this is a loaded question. Just looking for direction to make the most of this framework using best practices.


13 Answer(s)
  • 0
    gterdem created
    Support Team

    I have some general architecture questions. I'm starting a new project on 4.4.3. The idea is that this will be a multitenant sas app. I will create several modules under the main application, each module will be for a specific webcart software, for example magento, shopify, etc. The implementation of the endpoints that remote carts will call and domain data for each of these is contained inside the module.

    Cool! Module Architecture is designed for flexibility.

    When new data comes in ( new orders for example ) the module will kick off a distributed event (these will be local initially but the code should work for when we move to microservice, per the docs). The main application then subscribes to these events and should record the transaction locally on abp database, and then schedule and process a background job (using the hangfire implementation) that posts the transactions into the appropriate remote backend.

    Okay, thinking that you have a microservice application now since you want to manage transactions with database and background jobs. There is also a pattern for microservice transactions, which is called inbox-outbox pattern. And it happens to be that ABP will be implementing this pattern in v5. Check the annoucements about it.

    Does this make sense to do? Also since the background jobs seems to be picked up from the queue sequentially and there could be many jobs and tenants, would we run into a problem where there could be a ton of transactions queued and they'd only be processed sequentially so a particular tenant could see huge delays getting their transactions in?

    I suggest checking transactional outbox pattern which we already implement. I don't think there will be a delay problem for tenants.

    A bigger concern is the fact that creating a bunch of httpclients to make the outgoing requests to the remote backends could cause resource exhaustion. In the past I've used an httpclient in DI to make the requests, however there's a problem here, and that is that each tenant will configure via settings management their remote backend url, these are different servers (but all the same software so contracts are the same).

    I fail to understand the usage of http requests in here. Since you are in distributed system, why not using message broker (rabbitmq, kafka etc) async communication instead of http requests? Simply adapt for async communication over synced communication to prevent it from the begining.

    When the transaction is processed and send to the remote backend, the url will be different because they are different servers.

    There are service locators (envoy, consul etc) for that. It's only job is to find the related service.

    To complicate matters most, the remote backend requires Login -> Receive SesssionID -> Then send this in the header of every subsequent request. In non multi-tenant implementations where its only one backend the application is sending these requests to, i simply use an interceptor to modify the header on the outgoing request.

    No no no. You don't send any session id or something over the network for internal communication. If you want to use synched communication over http, it will be using Client Credential Flow grant type of OAuth2.0 without user credentials. Don't try to re-invent bicycle if it is about security and if your job is not creating bicycles for security.

    In multi-tenant I assume the best thing to do would be to login -> send to redis cache for the tenant, and check this each time in the future when a request needs to go out and its for a particular tenant ID.

    Multitenancy in ABP framework is very nicely abstracted and you can use with resolvers or a midware. You can check the source code.

    I'm looking for any suggestion on how to accomplish this reliably without collapsing the application, keeping in mind that thousands of transactions can be posted in to the abp app, from different web carts, from different tenants.

    I would suggest leaning towards async messaging (eventbus over message broker) over synced messaging (http requests). Aso watching Mastering Chaos - A Netflix Guide to Microservices can give you ideas about how they solve millions of requests.

    I know this is a loaded question. Just looking for direction to make the most of this framework using best practices.

    You can also follow eShopOnAbp repository where we are building eShop application using Abp.

  • 0
    hikalkan created
    Support Team

    @rcalv002 I want to inform you that background job queue is not guaranteed to be ordered. Because, if a job fails, the next job is executed. The failed job is rescheduled to be executed later (the documentation: https://docs.abp.io/en/abp/latest/Background-Jobs#default-background-job-manager). This is the default background job manager. If you want to use HangFire, then refer its own documentation.

    I read your post a few times, but it is very hard to give architectural advices like that. Every system has its own tradeoff and deciding such stuff requires a lot of meetings and discussions inside the team.

  • 0
    rcalv002 created

    Hi all, Thanks for the responses! Im subscribed to the thread but did not receive update over email so I missed your responses until now. I will clarify some parts here i noticed were not clear.

  • 0
    albert created
    Support Team

    thanks for the feedback

  • 0
    rcalv002 created

    When new data comes in ( new orders for example ) the module will kick off a distributed event (these will be local initially but the code should work for when we move to microservice, per the docs). The main application then subscribes to these events and should record the transaction locally on abp database, and then schedule and process a background job (using the hangfire implementation) that posts the transactions into the appropriate remote backend.

    Okay, thinking that you have a microservice application now since you want to manage transactions with database and background jobs. There is also a pattern for microservice transactions, which is called inbox-outbox pattern. And it happens to be that ABP will be implementing this pattern in v5. Check the annoucements about it.

    Thanks, I did see the announcement earlier and am looking forward to it, but don't want to wait 2 months to start working on this, I can refactor later. Right now my app will not be a ms, but a mono with modules.

    Does this make sense to do? Also since the background jobs seems to be picked up from the queue sequentially and there could be many jobs and tenants, would we run into a problem where there could be a ton of transactions queued and they'd only be processed sequentially so a particular tenant could see huge delays getting their transactions in?

    I suggest checking transactional outbox pattern which we already implement. I don't think there will be a delay problem for tenants.

    Okay, I'll search the forums and docs, if you have a direct link great.

    A bigger concern is the fact that creating a bunch of httpclients to make the outgoing requests to the remote backends could cause resource exhaustion. In the past I've used an httpclient in DI to make the requests, however there's a problem here, and that is that each tenant will configure via settings management their remote backend url, these are different servers (but all the same software so contracts are the same).

    I fail to understand the usage of http requests in here. Since you are in distributed system, why not using message broker (rabbitmq, kafka etc) async communication instead of http requests? Simply adapt for async communication over synced communication to prevent it from the begining.

    I'm not currently on microservices but regardless, I'm sending requests to an external, remote, non-managed backend. For more clarity, we implement backend ERP systems, these have web api. These systems are administered by our clients. We will send data from our abp app to these remote systems, it must be through http :).

    When the transaction is processed and send to the remote backend, the url will be different because they are different servers.

    There are service locators (envoy, consul etc) for that. It's only job is to find the related service.

    Each tenant will have different url to their remote backend server that we don't manage. We simply send the appropriate transactions via api. This abpp app will mostly be a multitenant integration platform.

    To complicate matters most, the remote backend requires Login -> Receive SesssionID -> Then send this in the header of every subsequent request. In non multi-tenant implementations where its only one backend the application is sending these requests to, i simply use an interceptor to modify the header on the outgoing request.

    No no no. You don't send any session id or something over the network for internal communication. If you want to use synched communication over http, it will be using Client Credential Flow grant type of OAuth2.0 without user credentials. Don't try to re-invent bicycle if it is about security and if your job is not creating bicycles for security.

    Right, its not internal communication, and the remote systems only have one authentication mechanism, which is to send user and pass, receive a 30 min session id, and send this with subsequent requests.

    In multi-tenant I assume the best thing to do would be to login -> send to redis cache for the tenant, and check this each time in the future when a request needs to go out and its for a particular tenant ID.

    Multitenancy in ABP framework is very nicely abstracted and you can use with resolvers or a midware. You can check the source code.

    I'm looking for any suggestion on how to accomplish this reliably without collapsing the application, keeping in mind that thousands of transactions can be posted in to the abp app, from different web carts, from different tenants.

    The use of redis I mentioned here was intended to store the 30 min session id, and picking it up for requests that should go to the appropriate backend remote system, when it expires or is removed from cache (same right?) I'd have to login again to get a new session id and continue.

    I would suggest leaning towards async messaging (eventbus over message broker) over synced messaging (http requests). Aso watching Mastering Chaos - A Netflix Guide to Microservices can give you ideas about how they solve millions of requests.

    I know this is a loaded question. Just looking for direction to make the most of this framework using best practices.

    You can also follow eShopOnAbp repository where we are building eShop application using Abp.

    Thanks for the suggestions, I'll look up the netflix document. I started watching the eshoponabp repo since it was announced. I see a lot of action on it this last week.

  • 0
    albert created
    Support Team

    closing the question. you can reopen it if you'd like to add anything.

  • 0
    rcalv002 created

    Hi Albert, Yes actually I was clarifying the remote call issue and would like some feedback on this point of my original quest, please?

  • 0
    albert created
    Support Team

    can you pls write your specific question? thanks

  • 0
    rcalv002 created

    Albert,

    My original question was around the part regarding sending requests to remote systems that require require login sessions, these systems would all be on separate servers that I would not control. It was regarding the best way to do this, pulling the connection information from configuration on the tenant. Could you please reread the thread with the original question and my clarifications after initial response?

  • 0
    hikalkan created
    Support Team

    My original question was around the part regarding sending requests to remote systems that require require login sessions, these systems would all be on separate servers that I would not control.

    Hi. Shouldn't you ask this to that system's maintainers? Because we can't know how they are authenticated. If every tenant has different connection information, you can define a tenant based setting and store that information in the setting. Settings can be encrypted too.

  • 0
    rcalv002 created

    Hi Hikalkan,

    I explained exactly how they are authenticated, my scenario, and that i would use setting on the tenant to store connection info and asked for recommendation on a specific point, how best to make calls to remote systems. Is it possible to have a zoom with your team to explain scenario? Paid if necessary.

    If not please let me know as well. this 15 question limit discourages reaching out for your assistance so I've been holding on to them for this kind of scenario.

  • 0
    albert created
    Support Team

    hi,

    sorry but the live support is not available to the Team license plan. and please create a new ticket for the new question. you can also purchase 50 question pack. contact to [email protected] to purchase extra questions.

  • 0
    rcalv002 created

    Thanks Albert,

    But the question remains the same, could I get a response on it? Or could you clarify whats not clear from what I'm asking?