Building web and middleware to be more cloud native, with Service Mesh in between

In Cuba, the Web client tier can be separated from the middle-tier and each can be scaled separately. However, the linkage between these 2 layers is via Spring remoting.

In Jmix, based on spring boot, there is no separation anymore and both Web and middle tier is in deployment WAR.

We would like to architect our large Jmix solution so that we can make it more “cloud native” whilst still have the productivity gain of building both FE and BE together.

Can we architect the solution so that we can deploy the web client and service beans as separate WARs and have a service mesh to call the service beans from the web client and also from each service bean ?

The recommended way of separating backend and frontend tiers while working with the same data model and services is using REST API and REST DataStore add-ons. You can find an example of this architecture in the Separating Application Tiers :: Jmix Documentation guide.

With REST DataStore you can work with the data model of a remote application almost the same as with local database. And Jmix 2.6 will include the REST DataStore improvement that simplifies invocation of REST services: Annotated interfaces for calling REST services by knstvk · Pull Request #4384 · jmix-framework/jmix

The main limitation of this approach is that full-stack add-ons like Reports cannot be used as is on the frontend. Also, you need to synchronize the model and service interfaces between the applications.

Theoretically, it is possible to implement your own variant of Spring Remoting, and use Spring container magic to substitute all services on frontend with proxies that communicate with backend through this Custom Remoting. This would let you develop the distributed application in CUBA style, with a single source for data model and service interfaces. Potentially it could also support full-stack add-ons. However, this is a very complicated task and we cannot provide an out-of-the-box solution.

Regards,
Konstantin

How would we be able to scale (out or up) our Jmix application if there 500, 2000 or more concurrent users ? What is the best practice and what are limitations ? With Cuba I remember there was a POC done with 20,000 active users with many Web tier and a different set of middle-tier servers.

And can we do a blue-green deployment i.e. patching / update / rollback of the components without downtime for all users ?

And one more thing. The example you shared has the data model “shared” from the backend-app to the frontend-app using the REST DataStore, right ? Is there an example of building a service (bean) in the backend-app that can be called from the frontend-app easily using the current Jmix framework ? Do we need to write our own service bean proxies and rest calls and corresponding rest controllers in the backend-app ?

In a standard full-stack approach you just create a cluster of applications servers, and a load balancer with sticky sessions for incoming requests. There is an example of setting up the application for working in a Kubernetes cluster in the docs: Kubernetes Cluster :: Jmix Documentation.

Limitations (of a single node) are the same as in CUBA: each user session requires a certain amount of memory on the server, and if the server goes down the users working with this server lose the UI state and have to re-login. Regarding possible load capacity of a single node, see performance test results in the Bookstore sample application. This test shows the application behavior with 1000 concurrent users.

In case of separate backend and frontend applications, both can be scaled using separate clusters. Limitations mentioned above apply only to the frontend application. The backend can be completely stateless and require less resources.

Yes you can. Create two clusters connected to the same database, and use draining on the load balancer to move users gradually from one cluster to another. Obviously, you should update your database schema very carefully, keeping compatibility with the previous application version running on the different cluster.

Yes, but you have to copy entities from backend project to the frontend one manually and remove JPA annotations. In the future, we’ll try to automate or eliminate this task.

On the backend you expose a service using @RestService/@RestMethod annotations:

@RestService("InventoryService")
public class InventoryService {

    @RestMethod
    public Double getAvailableInStock(Product product) {
        return (double) Math.round(Math.random() * 100);
    }
}

On the frontend, in the current Jmix 2.5 you have to write “service proxies” manually, using Spring’s RestClient calls as shown in this guide. In Jmix 2.6 (will be released this month) all you have to do on the frontend side is to declare an interface with @RemoteService annotation, and a proxy implementation will be created automatically:

@RemoteService(store = "products")
public interface InventoryService {

    Double getAvailableInStock(Product product);
}

Regards,
Konstantin