Monday, 19 September 2022

Managing High Usage Accounts

Big accounts, such as Big Bazaar, Domino's & Pantaloons, often cause hotspot issues for the payment system.

A hotspot payment account is an account that has a large number of concurrent operations on it. 

For example, when merchant A starts a promotion on Amazon Prime day, it receives many concurrent purchasing orders. In this case, the merchant’s account in the database becomes a hotspot account due to frequent updates.

In normal operations, we put a row lock on the merchant’s balance when it gets updated. However, this locking mechanism leads to low throughput and becomes a system bottleneck. 

The diagram below shows several optimizations. 




  • Rate limit
    We can limit the number of requests within a certain period. The remaining requests will be rejected or retried at a later time. It is a simple way to increase the system’s responsiveness for some users, but this can lead to a bad user experience. 

  • Split the balance account into sub-accounts
    We can set up sub-accounts for the merchant’s account. In this way, one update request only locks one sub-account, and the rest sub-accounts are still available.

  • Use cache to update balance first
    We can set up a caching layer to update the merchant’s balance. The detailed statements and balances are updated in the database later asynchronously. The in-memory cache can deal with much higher throughput than the database.




Unleashing the Power of API Gateway: Exploring Its Functionality

  


Step 1 - The client sends an HTTP request to the API gateway.

Step 2 - The API gateway parses and validates the attributes in the HTTP request.

Step 3 - The API gateway performs allow-list/deny-list checks.

Step 4 - The API gateway talks to an identity provider for authentication and authorization.

Step 5 - The rate limiting rules are applied to the request. If it is over the limit, the request is rejected.

Steps 6 and 7 - Now that the request has passed basic checks, the API gateway finds the relevant service to route to by path matching.

Step 8 - The API gateway transforms the request into the appropriate protocol and sends it to backend microservices.

Steps 9-12: The API gateway can handle errors properly, and deals with faults if the error takes a longer time to recover (circuit break). It can also leverage ELK (Elastic-Logstash-Kibana) stack for logging and monitoring. We sometimes cache data in the API gateway.


Source: bytebytego

Tuesday, 13 September 2022

Optimizing Pagination: Best Practices for Efficient Content Navigation

Introduction

In this article, we are going to discuss several data pagination best and worst practices.

Data pagination is omnipresent in enterprise applications. Yet, most solutions, not only they offer a bad user experience, but they are also inefficient.

The problem pagination solves

If you only had a dozen of entries in your database, then you can just simply fetch all data and display it to the user. However, this is almost never the case. Most often, database table entries range from tens of rows to billions of records.

Fetching a large amount of data takes a significant amount of time. That’s because a lot of work needs to be done to move large volumes of data from the database server to the user interface:

  • the data has to be scanned from the disk and loaded into the database server buffer pool
  • the loaded data is sent over the network
  • the application server will get the data in tabular fashion (e.g., the JDBC ResultSet)
  • the application transforms the tabular-based data into tree-based structures (e.g., entities, DTOs)
  • the tree-based structure is transformed to JSON and sent over the network to the browser
  • the browser needs to load the entire JSON and use it to build the UI

Not only that fetching large volumes of data is extremely inefficient, but it also hurts the user experience. Imagine having to load a list of tens of thousands of entries on your mobile phone over a metered connection. Loading this particular large list will be slow, expensive, and impossible to navigate on a mobile phone with a very limited viewport.

So, for all these reasons, pagination is used so that only a small subset of the entire dataset is fetched and displayed at once.

Classic pagination layout

Now, the most common way of sampling a result set is to split it into multiple pages or subsets of data. One such example can be seen on the old Hibernate forum:

Hibernate forum pagination

There are over 66k posts which are split into 2600 pages. While you can practically navigate to any of those pages, in reality, this is not very useful.

Why would I want to go to page number 1758? Or, how easily could I find the exact topic I’m interested in by jumping thousands of times from one page to the next?

Page number limit

When searching for a less-selective term on Google, you might end up getting a very large result set list of possible pages matching the searched keywords.

Searching Hibernate on Google - first page

So, when searching for “Hibernate”, Google says it has 22 million results. However, Google only provides the most relevant 16 or 17 pages:

The thing is, few users ever navigate to the second or third pages. Most users don’t even need to go from one page to another because there is a much better way to find exactly what you are interested in. You just need more selective search terms.

So, when refining the search terms, we get a much better chance of finding what we were interested in:

High-selective search terms

Better ways of filtering

Pagination is good, especially because it allows you to fetch only a small subset of data at a time. However, page navigation is only useful if the number of pages is small. If you have tens or hundreds of pages, then it’s going to be very difficult for the users to find what they are interested in.

Instead, what the user wants is a better filtering tool. Instead of manually scanning each page, it would be much better if the application could do that automatically as long as you provide highly-selective search terms.

For the application developers, it means they have to provide with a way of refining the result set, either by providing more filtering criteria or via a more detailed search term description.

This way, the application can fetch the exact subset of data the user is interested in, and the user will quickly find the right entry from the narrowed result set.

Sunday, 11 September 2022

Exploring NGINX's Threading Architecture: A Deep Dive into Efficient Request Handling


When NGINX reverse proxy starts it creates one thread per CPU core and these worker threads do the heavy lifting. The number of worker threads is configurable but NGINX recommends one thread per CPU core to avoid context switching and cache thrashing. In older versions of NGINX, all threads accept connections by competing on the shared listener socket (by default only one process can listen on IP/port pair). 





In recent versions of NGINX, this was changed to use socket sharding (through the SO_REUSEPORT socket option) which allows multiple threads to listen on the same port and the OS will load balance connections on each accept queue.




Exploring the Power of Generative AI Services: Unlocking Limitless Creativity

Introduction In recent years, we have witnessed remarkable advancements in the field of artificial intelligence (AI). One of the most intrig...