Quotes

Wednesday, October 31, 2018

Why we need to split monolith app into microservices


Why?

1) Scale independently.


2) Different tech stacks, versions
   

3)  When two are more clients wants to use the same service.


4) Conflicting dependencies.









Distributed cloud apps architecture



Feature                 Past                                  Present

Clients             Enterprise/Intranet              Public/Internet
Demand           Stable(Small)                      Dynamic (Small -> Massive)
Datacenter       Single tenant                       Multi - tenant(noisy neighbor)
Operations       People(expensive)              Automation (cheap)
Scale                Up via few reliable             Out via lots of (Cheap) commodity PCs
                         (expensive) PCs             
Failure             Unlikely but possible          Very likely
Machine loss    Catastrophic                       Normal (no big deal)


Exceptions            Catch, swallow & keep running      Crash & restart
Communication    In order exactly once                       Out of order Clients must retry &
                                                                                       servers must be idempotent.


Failure Model Analysis (FMA)

How will the application detect this type of failure?
How will the application response to his type of failure?
How will you log and monitor this type of failure?

Design self healing apps:

Detect failures, response to failures gracefully and log and monitor failures to give operational insight


Recommendations:

1) Retry failed operations. Transient failures might occur due to momentary loss of network connectivity, a dropped database connection, or a timeout when a service is busy. Build retry logic into your application to handle transient failures.


2) Protect failing remote services (circuit breaker design pattern). It's advisable to retry after a transient failure, but if the failure persists, you can end up with too many callers hitting a failing service. This can lead to cascading failures as requests back up. Use the circuit breaker design pattern to fail fast (without making the remote call) when an operation is likely to fail.

3) Isolate critical resources (bulkhead pattern). Failures in one subsystem can sometimes cascade. This can happen if a failure causes some resources, such as threads or sockets, from being freed in a timely manner, leading to resource exhaustion. To avoid this, partition a system into isolated groups, so that a failure in one partition does not bring down the entire system.

4) Perform load leveling. Applications may experience sudden spikes in traffic that can overwhelm services on the backend. To avoid this, use the queue-based load leveling pattern to queue work items to run asynchronously. The queue acts as a buffer that evens out peaks in the load.

5) Fail over. If an instance can't be reached, fail over to another instance. For things that are stateless, like a web server, put several instances behind a load balancer or traffic manager. For things that store state, like a database, use replicas and fail over. Depending on the data store and how it replicates, this might require the application to deal with eventual consistency.

6) Compensate for failed transactions. In general, avoid distributed transactions because they require coordination across services and resources. Instead, use compensating transactions to undo any step that already completed.
7)Use checkpoints on long-running transactions. Checkpoints can provide resiliency if a long-running operation fails. When the operation restarts (for example, it is picked up by another virtual machine), it can be resumed from the last checkpoint.

8) Degrade gracefully. Sometimes you can't work around a problem, but you can provide reduced functionality that is still useful. Consider an application that shows a catalog of books. If the application can't retrieve the thumbnail image for the cover, it might show a placeholder image. Entire subsystems might be noncritical for the application. For example, in an e-commerce site, showing product recommendations is probably less critical than processing orders.

9)Throttle clients. Sometimes a small number of users create excessive load, which can reduce your application's availability for other users. In this situation, throttle the client for a certain period of time. See the throttling pattern for more information.

10) Block bad actors. Just because you throttle a client, it doesn't mean the client was acting maliciously. It just means that the client exceeded its service quota. But if a client consistently exceeds their quota or otherwise behaves badly, you might block them. Define an out-of-band process for the user to request getting unblocked.

11) Use leader election. When you need to coordinate a task, use leader election to select a coordinator. That way, the coordinator is not a single point of failure. If the coordinator fails, a new one is selected. Rather than implement a leader election algorithm from scratch, consider an off-the-shelf solution such as Apache ZooKeeper.

12) Test with fault injection. All too often, the success path is well tested but not the failure path. A system could run in production for a long time before a failure path is exercised. Use fault injection to test the resiliency of the system to failures, either by triggering actual failures or by simulating them.

13) Embrace chaos engineering. Chaos engineering extends the notion of fault injection by randomly injecting failures or abnormal conditions into production instances.

UML and Architecture Patterns.

UML - Unified Modeling Language.

1) Kruchen's 4 + 1 Model.

2) LucidChart's

3) Component Diagrams

4) Class Diagrams

5) Activity Diagrams

6) Deployment Diagrams

7) Use Case Diagrams.


Architecture Patterns.

1) Multi Tiered architecture.

2) Client Server Architecture

3) Model- View- Controller Architecture

4) Service Oriented Architecture

5) Microservices Architecture

6) Domain Driven Architecture

7) Event Driven Architecture

Tuesday, October 30, 2018

Asynchronous, Synchronous, Multi threading, Concurrency

Synchronous Programming model – In this programming model, A thread is assigned to one task and starts working on it. Once the task completes then it is available for the next task. In this model, it cannot leave the executing task in mid to take up another task. Let’s discuss how this model works in single and multi-threaded environments.
Single Threaded – If we have couple of tasks to be worked on and the current system provides just a single thread, then tasks are assigned to the thread one by one. It can be pictorially depicted as
singlethreadedHere we can see that we have a thread (Thread 1 ) and four tasks to be completed. Thread starts workingon the tasks one by one and completes all. (The order in which tasks will be taken up, does not affect the execution, we can have different algorithm which can define the priorities of tasks)
Multi-Threaded – In this environment, we used to have multiple threads which can take up these tasks and start working on that. It means we have a pool of threads (new threads can also be created based on the requirement and available resources) and bunch of tasks. So these thread can work on these as
multithreadedHere we can see that we have four threads and same number of tasks to complete. So each thread takes up one task and completes that. This is an ideal scenario but in normal cases, we used to have more number of tasks than the number of available threads. So, whichever thread gets free, takes up another task. As already mentioned that spawning new thread is not an option each time because it requires system resources like CPU, memory.
Now, Let’s talk about Asynchronous model and how does it behave in single and multi-threaded environment.
Asynchronous Programming Model – In contrary to Synchronous programming model, here a thread once start executing a task it can hold it in mid, save the current state and start executing another task.
async-singleHere we can see that a single thread is responsible to complete all the tasks and tasks are interleaved to each other.
If our system is capable of having multiple threads then all the threads can work in asynchronous model as well
Async-mutlithreadedHere we can see that same task say T4, T5, T6.. are handled by multiple thread. This is the beauty of this scenario. As you can see that T4 was started first in Thread 1 and completed by Thread 2. Similarly, T6 is completed by Thread 2, Thread 3 and Thread 4. It shows the maximum utilization of the threads.
So till now we have discussed four scenarios –
  1. Synchronous Single Threaded
  2. Synchronous Multi-Threaded
  3. Asynchronous Single Threaded
  4. Asynchronous Multi-Threaded
Let’s discuss one more term – Concurrency.
Concurrency
In simple terms, concurrency means processing multiple requests at a time. As we have discussed two scenarios where multiple requests were getting processed, Multi-threaded programming and asynchronous model (single and multi-threaded both). In case of asynchronous model whether single or multi-threaded, multiple tasks are in progress at a time, some are in hold state and some are getting executed. There are many flavors of it but that is beyond the scope of this post.
As discussed earlier, the new age is of asynchronous programming. Why is it so important?
Benefits of Asynchronous Programming
There are two things which are very important for any application – Usability and Performance. Usability because say a user clicks on a button to save some data. This requires multiple smaller tasks like reading and populating data in internal object, establishing connection with SQL and saving it there etc. As SQL runs on another machine in network and runs under different process, it could be time consuming and may take bit longer. So, if the application runs on a single thread then the screen will be in hanged state till all the tasks completes which is a very bad user experience. That’s why nowadays many applications and new frameworks completely rely on asynchronous model.
Performance of an application is also very important. It has been seen that while executing a request, around 70-80% of the time gets wasted while waiting for the dependent tasks. So, it can be maximum utilized by asynchronous programming where once the task is passed to another process (say SQL), current thread saves the state and available to take another task. When the SQL task completes any thread which is free, can take it up further.
Asynchrony in ASP.NET
Async in ASP.NET can be a major boost in the throughput of your application. Let’s see, how IIS processes a request.
CLRWhen a request is received by IIS, it takes a thread from CLR thread pool (IIS does not own any thread-pool itself instead uses CLR thread pool) and assigns to it which further processes the request. As number of threads are limited and new ones can be created at a certain limit then if the thread wastes most of the time in waiting then it’s going to hit hard to your application’s overall performance. But if you write asynchronous code (which now become very easy and can be written almost similar to synchronous using the new keywords async/await in C#) then it will be way faster and throughput of your server will increase significantly because instead of waiting something to complete, it will be available to thread pool to take the new requests. If the application has a lot of dependency and long running process then for those application, async programming will be not less than a boon.