Currently, SAP BTP enables the creation and consumption of microservices in two ways: SAP BTP, Cloud Foundry environment, and SAP BTP, Kyma runtime.
SAP BTP, Cloud Foundry environment, enables the creation and deployment of microservices. SAP HANA extended application services, advanced model (SAP HANA XSA) for on-premise applications and Cloud Foundry for cloud-based applications provide the platforms for microservices-based, polyglot web applications.
The Kyma environment is also now available with SAP BTP, which enables the development and deployment of microservices (and functions).
For Cloud Foundry, application containers provide an isolation layer between microservices, which can be written in separate languages, since a core part of the app server for that particular language is deployed in the corresponding app container.
A particular function for use as a microservice can be developed using any of the available buildpacks. For Java, the Spring framework is useful and quite powerful with its dependency injection framework.
For web-based applications, a web server is required, and Tomcat is the default web server supported by Cloud Foundry as well as for the Neo platform ever since SAP Cloud Platform (now SAP BTP) became available. One of its many advantages is that Tomcat requires little memory to run and is also part of the SAP Java buildpack.
Thus, to design an application and its microservices, you need SAP Business Application Studio (or SAP Web IDE), and you need access to the services you want to create your application around. Your application will be created as an .mta file, which is a multitarget application (MTA) file that can include a user interface (UI), business logic, and one or more workflows or an Internet of Things (IoT) service. Depending on which application is the core feature of your application, you can use the corresponding development tabs in SAP Business Application Studio spaces.
As shown in the figure below, the different components work together to deploy applications, including their microservices, in Cloud Foundry. These details will be quite transparent to your developers as well.
Let’s explore how the different components work together.
User account and authentication (UAA) is a service for regular authentication and for federated authentication, which is useful for authenticating technical or platform user access to an SAP Business Technology Platform instance. UAA is provided by an OAuth2 server and logon servers working together.
Extended services for user account and authentication (XSUAA), however, conducts authentication from a business perspective, checking whether a user has the authorization to access a specific application and perform a specific task. The platform application router (which is not the same as the AppRouter) routes incoming traffic to the appropriate component, either a Cloud Controller component or a hosted application running on a Diego Cell.
The router queries the Diego Bulletin Board System (BBS) to determine which cells and containers each application currently runs on. This query is performed periodically, and this information helps the platform application router recalculate new routing tables.
The request goes through the Cloud Controller, and buildpacks (including some buildpacks of applications deployed to the application code) and droplets are persisted in the binary large object (blob) store, which stores large binary files.
Diego is the Cloud Foundry runtime and container management system, which consists of a house manager, which is a bulletin board system. This manager checks which applications are still running.
An application can provide a custom health endpoint to be called to check this information, but this check is optional. If an application is unhealthy, Diego will stop the application, delete the application from the container, and then re-create and restart the application, using the information found in the blob store. If an application is healthy, then a route is assigned to the application instance.
Diego basically distinguishes between tasks (like database schema migrations) and long-running processes (LRPs) and, depending on this distinction, decides which cell container the application should be deployed to. Overall, an application is deployed to one individual container. This isolation helps you scale horizontally because an application, when running in isolation, can have other instances running next to it.
Then, the load balancer can distribute the load between several application instances. The figure above also shows an application bound to an external service via the concept of user-provided services, or the application can be bound to a managed service instance.
The service broker is responsible for providing the service instance to an application, which has the service provisioned and bound to it. This service can be any service provided within the organization or the platform or via third-party software as a service (SaaS) providers. The service broker is responsible for creating a Docker container and for deploying the service instance into that container. Furthermore, the service broker is responsible for binding this managed service instance, like MongoDB, to all instances of the application. Thus, the service broker is basically a microservice implementing just a few endpoints that are then executed by Cloud Foundry. The log aggregator streams the application log for the operators, while the metrics collector gathers metrics and statistics from the components, thereby helping users monitor a Cloud Foundry deployment. All components must provide an endpoint that offers this kind of information.
From the point of view of leveraging SAP BTP, Kyma runtime, for consuming or creating microservices, the architecture is quite transparent to developers. In this case, Kyma runs on a Kubernetes cluster and is available as a managed service on top of SAP BTP. You can create microservice in any language in Kyma.
SAP BTP, Kyma runtime, supports a microservice-based architecture, event handling or consumption, authentication, logging, tracing (which in turn helps in monitoring and alerting in case of failures or issues), consumption of services provided by hyperscalers, and also API management services. All these features are enabled through the managed service option in SAP BTP.
Microservice Design Considerations
While microservices provide many advantages in terms of reuse, independent scalability, and more, some costs are associated with these benefits. These costs are incurred through interacting with each other (communication overhead) or through having a separate persistence that require synching, which will increase overall latency. Thus, you should consider a few points when designing an application and the microservices to be used within it, such as the following.
You can apply domain-driven design, a concept invented by Eric Evans, by using a particular business context bounded to a model for that domain. An example of a domain could be insurance, finance, or manufacturing. In other words, in a particular domain, a data model cannot support all the subdomains in that domain, especially if the domain is quite large. A data model can have perspectives based on particular uses, and if all these perspectives are merged together, you may end up with a huge messy model that may not work at all. Thus, you should have domains and subdomains that are independently modeled. As shown in the figure below, three types of domains can be considered: The core domain is the main area of innovation and intellectual property, and this domain will receive the business impact and answer the question of why the system is being built. Then, a generic domain is required to run any application and is non-differentiating for your business, like user management or security; you should simply buy this domain. Finally, supporting domains act as the glue code between specific parts of your system but do not really serve as the core.
One major consideration is granularity. Not every functionality should be broken down into a minute microservice. Thus, a monolithic application should be broken down into a limited number of microservices but not randomly into hundreds of microservices.
If a particular function must be made more scalable or resilient, then creating the function as a separate microservice makes sense. If you want to scale horizontally, design the function to have more app instances to take on the load.
API-First Microservice Design
Depending on your business requirements, an API can be designed first and then the other components of the microservice can be built, for instance, the UI for either a mobile app or a web app. If the API is designed well, then reusing the API will be easy, and thus, many applications can be built using this API. Sometimes, if a public API is available and suitable for a particular business need, this API can serve as the starting point for designing a microservice.
Type of Service Calls
If all the service calls within an application use REST APIs and/or a design decision leads to a lot of interservice calls, a high degree of latency in response time may arise, especially if all the service calls are synchronous. Also, the decoupling of services is an essential design parameter. You should avoid any transactions between microservices because calls between microservices can be thousands of times slower than calls within a microservice. For messages, performance should not be a problem, but with synchronous REST calls, you may notice performance issues. Remember that response times often add up.
Outside-In Modeling Approach
This approach means that the focus of the design is on business events, which are modeled with help of domain experts. The relation between events—between inputs/prerequisites and outcomes—is also mapped out. This model can then be translated into a technical solution.
Built-in resiliency in a microservice means that the application can have multiple functions as independently deployed units. If any unit fails to deploy or has a bug, you should be able to isolate the unit without shutting down the entire application.
The twelve-factor app is a modern methodology to help design SaaS solutions. This methodology can be made applicable to the SAP domain as well.
The twelve-factor app principles state the following:
- Codebase: One codebase tracked in revision control, many deploys.
- Dependency: Explicitly declare and isolate dependencies.
- Config: Store configuration in the environment.
- Backing services: Treat backing services as attached resources.
- Build, release, run: Strictly separate build and run stages.
- Processes: Execute the app as one or more stateless processes.
- Port binding: Export services via port binding, which is handled by the SAP platform and does not need any extra action.
- Concurrency: Scale out via the process model.
- Disposability: Maximize robustness with fast startups and graceful shutdowns.
- Development/production parity: Keep development, staging, and production as similar as possible.
- Logs: Keep logs as event streams.
- Admin process: Run admin/management tasks as one-off processes.
More information about twelve-factor app design principles is available here.
Editor’s note: This post has been adapted from a section of the book Application Development with SAP Business Technology Platform by Gairik Acharya, Govind Bajaj, Avijit Dhar, Anup Ghosh, and Asidhara Lahiri.