Distributed Task Synchronization: Leveraging ShedLock in Spring

In today's distributed computing landscape, coordinating tasks across multiple nodes while ensuring they execute without conflicts or duplication presents significant challenges. Whether managing periodic jobs, batch processes, or critical system tasks, maintaining synchronization and consistency is crucial for seamless operations.

The Problem

Let's say we need to run some tasks on a schedule, whether it's a database cleanup task or some data generation task. If you approach the problem directly, you can solve this problem using the @Schedules annotation included in Spring Framework. This annotation allows you to run code at fixed intervals or on a cron schedule. But what if the number of instances of our service is more than one? In this case, the task will be executed on every instance of our service.

Data Consistency in Distributed Systems: Transactional Outbox

In today's world of distributed systems and microservices, it is crucial to maintain consistency. Microservice architecture is considered almost a standard for building modern, flexible, and reliable high-loaded systems. But at the same time introduces additional complexities.

Monolith vs Microservices

In monolithic applications, consistency can be achieved using transactions. Within a transaction, we can modify data in multiple tables. If an error occurred during the modification process, the transaction would roll back and the data would remain consistent. Thus consistency was achieved by the database tools. In a microservice architecture, things get much more complicated. At some point, we will have to change data not only in the current microservice but also in other microservices.

JWT Token Revocation: Centralized Control vs. Distributed Kafka Handling

Tokens are essential for secure digital access, but what if you need to revoke them? Despite our best efforts, there are times when tokens can be compromised. This may occur due to coding errors, accidental logging, zero-day vulnerabilities, and other factors. Token revocation is a critical aspect of modern security, ensuring that access remains in the right hands and unauthorized users are kept out. In this article, we'll explore how different methods, such as centralized control and distributed Kafka handling, play a vital role in keeping your systems and data safe.

Access/Refresh Tokens

I described more about using JWTs in this article. JWTs allow you to eliminate the use of centralized token storage and verify tokens in the middleware layer of each microservice.

Preventing Data Loss With Kafka Listeners in Spring Boot

Data loss is one of the biggest problems developers face when building distributed systems. Whether due to network issues or code bugs, data loss can have serious consequences for enterprises. In this article, we'll look at how to build Kafka listeners with Spring Boot and how to use Kafka's acknowledgment mechanisms to prevent data loss and ensure the reliability of our systems.

Apache Kafka

Apache Kafka is a distributed message platform used to store and deliver messages. Once a message is written to Kafka, it will be kept there according to a retention policy. The consumer groups mechanism is used to read out messages. The offset for each consumer group is used to understand the stage of message processing and to keep track of the progress of each consumer group in reading messages from a partition. It allows each consumer group to independently read messages from a topic and resume reading from where it left off in case of failures or restarts. In a simplified way, this can be represented as follows:
Apache Kafka process

Enhancing Security with Two-Factor Authentication: An Introduction to TOTP and HOTP

One of the most popular method of authentication remains the password. In a previous article, we discussed the proper implementation of password authentication. However, relying solely on a password as the means of authentication is no longer sufficient, especially for critical accounts, such as bank accounts or personal email accounts, that serve as the point of access to other services.

Two-factor authentication (2FA) significantly enhances account security by adding an extra step in the login process. In this article, we will discuss 2FA options and take a closer look at implementations of the commonly used time-based one-time password (TOTP) and a password and HMAC-based one-time password (HOTP) protocols.

Using JSON Web Encryption (JWE)

In the previous article, we looked at signed JSON Web Tokens and how to use them for cross-service authorization. But sometimes, there are situations when you need to add sensitive information to a token that you would not want to share with other systems. Or such a token can be given to the user's device (browser, phone). In this case, the user can decode the token and get all the information from the payload.

One solution to such a problem could be the use of JSON Web Encryption (JWE), the full specification of which can be found in RFC7516.

Password Authentication. How to Correctly Do It.

The problem of cybersecurity is quite severe nowadays. Even large and well-known companies face the problem of sensitive user data leakage. It can be unauthorized access to databases, leaked logs, etc. Quite often, we encounter day 0 vulnerabilities that attackers can exploit. All this negatively affects the security of users themselves and the business's reputation. In this article, I would like to explain how to implement storing user authentication data with password authentication.

Authentication

Authentication is the process of confirming by the user that he is the owner of the presented identifier. The most apparent and most familiar authentication process is password authentication. The user goes to the login page, enters his username/password, and logs on. In this article, I will show how you can implement authentication on the server.

Distributed Tracing System (Spring Cloud Sleuth + OpenZipkin)

When we build a microservice architecture and the number of services keeps growing, we face the problem of debugging and tracing requests through our entire system. What happened when a user got a 500 error on his request? What service incorrectly processed his request? All these questions can be solved by the Distributed Tracing System. Let's take Spring Cloud Sleuth as an example.

How Spring Cloud Sleuth Works

To trace a request through a distributed system, the concepts TraceID and SpanID are introduced. TraceID is generated when a request enters our system and remains unchanged throughout its path. SpanID changes as the request passes from one service to another. If necessary, it is possible to generate new spans within one service to distinguish business processes.