Showing posts with label DSA. Show all posts
Showing posts with label DSA. Show all posts

Tuesday, 9 May 2023

Distributed Logging and Tracing in Microservices

The microservice architecture pattern. Requests often span multiple services. Each service handles a request by performing one or more operations, e.g. database queries, publishes messages, etc.

How to understand the behavior of an application and troubleshoot problems?



The solution is Distributed Tracing and Log Aggregation

Distributed Tracing


Trace ID: A unique ID to trace the path of a request, If the request spans multiple services (Request ID).
Span ID: A unique ID to track requests related to a single service only (Service ID).

Log Aggregation
Storing of logs for visualization and analysis in an external/centralized place. Additional infra and setup costs. How to implement Log Aggregation.
1) Spring Cloud Sleuth + Zepkin
2) OpenTracing + Jaeger
3) ELK (ElasticSearch, Logstash, Kibana)

Note:
It is not mandatory to introduce Log Tracing in every Microservice architecture.
It is used for monitoring the behavior of applications and triggering specific alerts based on errors or exceptions. It totally depends on:
1) How you have designed your Architecture of application?
2) The microservices you created are independent in terms of resource processing or not?





Saga Pattern for Distributed Transaction Management in Microservices

One of the benefits of microservice architecture is that we can choose the technology stack per service. For instance, we can decide to use a relational database for service A and a NoSQL database for service B.
This model lets the service manage domain data independently on a data store that best suits its data types and schema. Further, it also lets the service scale its data stores on demand and insulates it from the failures of other services.
However, at times a transaction can span across multiple services, and ensuring data consistency across the service database is a challenge.

Implement each business transaction that spans multiple services as a saga. A saga is a sequence of local transactions. Each local transaction updates the database and publishes a message or event to trigger the next local transaction in the saga. If a local transaction fails because it violates a business rule then the saga executes a series of compensating transactions that undo the changes that were made by the preceding local transactions.


There are two ways of coordinating sagas:

  • Choreography - Event-Based (Message Broker)
  • Orchestration - Command-Based (Service Provider)

Choreography-based saga



  1. The Order Service receives the POST /orders request and creates an Order in a PENDING state
  2. Then Order Service publishes an event to the message broker that an ORDER_CREATED to Payment Service.
  3. The Payment Service got the ORDER_CREATED event and does the necessary updates and publishes the event to Order and Restaurant Service that an ORDER_PAID.
  4. The Order and Restaurant Service got the ORDER_PAID event and do the necessary updates.
  5. The Restaurant Service publishes the event to Order and Delivery Service that an ORDER_PREPARED.
  6. The Order and Delivery Service got the ORDER_PREPARED event and do the necessary updates.
  7. Finally, Delivery Service publishes the event to Order Service that ORDER_DELIVERED to the Order Service, and the Order state changed from PENDING to COMPLETE.

Orchestration-based saga


  1. The Order Service receives the POST /orders request and creates an Order in a PENDING state
  2. Then Order Service sends the command to Orchestrator Service that an ORDER_CREATED to Payment Service.
  3. The Payment Service got the ORDER_CREATED command and does the necessary updates and sends the command to Order and Restaurant Service that an ORDER_PAID.
  4. The Order and Restaurant Service got the ORDER_PAID command and do the necessary updates.
  5. The Restaurant Service sends the command to Order and Delivery Service that an ORDER_PREPARED.
  6. The Order and Delivery Service got the ORDER_PREPARED command and do the necessary updates.
  7. Finally, Delivery Service sends the command to Order Service that ORDER_DELIVERED to the Order Service, and the Order state changed from PENDING to COMPLETE.

Conclusion

CHOREOGRAPHY-Event-Based (Message Broker) could be a case where you can end in a deadlock because one service is dependent on the other and what if the other is dependent on the other, so if you have a very less number of events it will be very good but if let's say you have more number of events there could be a point where you might miss the sequence of the workflow and it might be tedious to test individual microservices and integration tests when you have too many events, in terms of ORCHESTRATION Command-Based (Service Provider) there is a single service which is going to interact with different microservices and now orchestration needs to have mapping on what each service does which again defeats the purpose of individual microservices concept where your orchestration service knows what is service does and if let's say there is a change is a payment service it might end up the changing the orchestration service as well. So this is one more pattern of implementing SAGAS however it's up to you to decide which one to go for based on your architectural use case.




Wednesday, 3 May 2023

Recursion

Recursion/Properties of Recursion

  • The same operation is performed multiple times with different inputs.

  • In every step, we try to make the problem smaller.

  • We mandatory need to have a base condition. Which tells the system to stop the recursion.


In case our sub-problem is similar in nature to a bigger problem, only in those kinds
of cases we can use recursion else recursion

will not be efficient.

Recursion is heavily used in Data structures like Trees, Graph, Divide, and Conquer, Greedy, Dynamic Programming, etc.

Recursive Case: Case where the function recurs.

Base Case: Case where the function does not recur (exit).


Code Snippet

public class ProblemStatement {

public static void main(String[] args) {
System.out.println("function1 -> " + function1(5));
System.out.println("function2 -> " + function2(5));
System.out.println("function3 -> " + function3(5));
}

public static int function1(int num) {
if(num == 0)
return 1;
return function1(num - 1);
}

public static int function2(int num) {
if(num == 0)
return 1;
return function2(num - 1) + num;
}

public static int function3(int num) {
if(num == 0)
return 1;
return function3(num -1) + function3(num -1);
}

} 

The output will be:

function1 -> 1

function2 -> 16

function3 -> 32


Explanation:

function1(0)

Return – 1

function1(1)

Return – 1

function1(2)

Return – 1

function1(3)

Return – 1

function1(4)

Return – 1

function1(5)

Return – 1


function2(0) + 1

Return – 1 + 1 = 2

function2(1) + 2

Return – 2 + 2 = 4

function2(2) + 3

Return – 4 + 3 = 7

function2(3) + 4

Return – 7 + 4 = 11

function2(4) + 5

Return – 11 + 5 = 16

function2(5)

Return – 16


function3(0) + function3(0)

Return – 1 + 1 = 2

function3(1) + function3(1)

Return – 2 + 2 = 4

function3(2) + function3(2)

Return – 4 + 4 = 8

function3(3) + function3(3)

Return – 8 + 8 = 16

function3(4) + function3(4)

Return – 16 + 16 = 32

function3(5)

Return – 32