Published on July 9, 2019
“…back to the future”.
Industry counts many different applications where components have to make automated decisions about something. Typical representatives of such applications are Workflows, Business Process Automation and alike. The values of gathered experience are significant and it would irrational to lose them only because developers use new technologies now, particularly, Microservices.
Limitations imposed by principles of Microservice design may be convenient for development teams, but not necessary suitable for an implementation of certain business tasks. If some verified designs contradict a few principles of Microservice, the IT management and DevOps (delivery teams) face a choice – either to relax those principles or put-off Microservices per se and use a different technology for realisation of such tasks. In practice, it is much easier to alter the principles than to give up the Microservices. It is the right approach: service-orientation is an omni-solution for business tasks while principles oriented on today development convenience are likely to be changed in the future.
An implementation of certain business tasks assumes that some Microservices should provide a decision-making functionality. There may be decisions about given information, or about the state of the system, or about which action to perform next, where, when, whom to, and so forth. In other words, a functionality to be provided by a Microservice is making a decision.
While there are several methods of realizing decision-making functionality, it is desirable that the solution would meet all following requirements
1) Accuracy of decision
2) Flexibility in adopting changes in the decision logic (minimization of Microservice re-design and re-development)
3) Consistency of the decision logic (concurrent updates)
4) Manageability and maintenance of the decision logic
5) Scalable accessibility of the decision making unit.
The problem is in which method to choose.
We review four methods of realisation of the decision-making functionality:
1. Inside the Microservice’s code
2. Outside of the Microservice’s code
3. As a static content
4. As a dynamic content.
One of the most popular methods of decision logic implementation is known from a business process management automation (BPMN-based). It is realised as a static code/script running usually inside the decision-making unit of work, which can be implemented as a Microservice.
An alternative option externalises the logic rules into a configuration source, so that the unit of work can upload the rules, as needed, in run-time. The configuration source can be updated as needed without stopping the unit of work. This constitutes a dynamic rule realisation though still within the Microservice body.
The options described above have been combined in the model known as a Rule Engine. This model has successfully worked for years. In essence, the Rule Engine is a sophisticated structure of modules that allow: 1) specifying different types of rules, and 2) executing them. Both take place outside of the Microservice boundaries.
A Microservice responsible for making decision simply outsource the rules to the Rule Engine and communicates with it via APIs. The communication may be synchronous, e.g. with HTML/JSON URL, or asynchronous, via messaging or events.
The APIs help to decouple the realm of consumers from the realm of the Rule Engine. Because of this separation, the Rule Engine can be highly responsive and scalable itself. We can find several Rule Engine products in the market.
The Table below illustrates how each rule implementation mechanism meets the requirements.
Accuracy Flexibility Consistency Manageability Scalable access
BPMN/script high low high medium low
Configurable rules high medium high medium medium
Rule Engine high high medium high high
The core of the Rule Pattern is in the clear separation of the decision logic from the rest of the code in the unit of work. The Table above shows that an externalised Rule Engines represent the best solutions against the specified requirements. There may many mechanisms of creating and updating decision rules in the Rule Pattern including dynamic ones.
A common problem known for the units of work, which operate with multiple rules, is that some rules may be bypassed by using some other rules. Since the rules may be specified or owned by different people or systems, the logic of providing an overall consistency is quite difficult. At the same time, when the number and types of rules is relatively small, they are easier observable and can be corrected earlier.
The second and the final part of the Rules Pattern is about access the Rule Engine. There are two options:
1) Direct access via Rules Engine API(s)
2) Access via RulesAdapter entity (Microservice).
If a Microservices accesses the Rules Engine directly via its API, all of them should be aware of the API. This means that if a Rules Engine changes the API, all its current consumers (Microservices) should be updated. Also, all consumers (Microservices) with a direct access are locked-in by particular Rules Engine. If a Rules Engine’s API is down, the consuming Microservice should wait for restoring the API. On the other hand, a direct access is the fastest one.
A RulesAdapter Microservice situates between the consuming Microservice and the Rules Engine’s API. It uses an Adapter Microservice Pattern while can be implements using Sib or Tandem patterns depending on the communication model with consuming Microservices. Though an access to the Rules Engine takes a bit longer time, you are getting a freedom of replacing one Rules Engine by another with no impact on consuming Microservices. Also, the RulesAdapter Microservice can shield the consuming Microservices from all failures in the accessibility or unavailability of the Rules Engine. Altogether, this increases the robustness in obtaining the decisions from the professional built tool.
A design of distributed transaction across multiple Microservices can segregate the code responsible for interactions with the supplemental Microservices and the code responsible for acquiring the decision. If the former includes event listening and event firing, the latter interacts with the Rule Engine via its API(s).
The Rule Engine API(s) usually receive data according a preliminary defined schema and returns a selection of agreed options – what to do next. Since Rule Engine API(s) are stateless, these API interactions scale well and, usually, concurrently (the Rule Engine vendors can offer many different additional features).
The orchestrating Microservice of the transaction engages the Rule Engine API(s) for each of its steps. Depending on the complexity of rules and the volume of data to be transmitted for analysis and decision, the Rule Engine API(s) may be engaged several times per the transaction’s step.
Another example: modern customers, when applying for loans online, expect almost instantaneous decisions. Such financial service is regulated by the Financial Authority and the rules change frequently. The most efficient way of adopting rule updates is in the Rule Engine outside of the decision-providing Microservices. Otherwise, each rule change would require a re-design, re-testing and re-deployment of each Microservice implementing one or another part of the rule.