This is the 7th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.

Hello everyone, I am Wukong.

First of all, it took a lot of time to draw the schematic diagram of this article.

This is the seventh article in the Eureka Registry series.

Leadership let me study had source | the boot process

Lead “yi” let me study Eureka source code: registration process

Details of the Eureka console worth collecting

It turns out that a Map can handle the registry

6 picture | analyze the client for the first time synchronization of the registry

11 picture | rectified principle, the smallest increment pull

This article has been included in my personal website: www.passjava.cn

One, foreword

Last time, we saw that the Server side of the Eureka registry has a three-level cache to store registration information, which can be used to improve system performance. Let’s take a closer look:

Level 1 cache: read-only cache readOnlyCacheMap, ConcurrentHashMap. Equivalent to a database.

Level-2 Cache: readOnlyCacheMap and Guava Cache. Equivalent to the master node in the Redis master-slave architecture, it can be read or written.

Level 3 cache: local registry, data structure ConcurentHashMap. Equivalent to the slave node of the Redis master-slave architecture, only responsible for reading.

The picture is clearer, as shown below:

Three kinds of cache

ConcurrenthashMap is also a map structure, which is stored in key-value pairs, as shown in the following figure:

Structure of the Map

In this article, Brother Wukong will take you to see how Eureka’s cache architecture is. By learning this, we can also learn from Eureka’s cache design ideas and apply them to the project.

Two, triggered a few thoughts

Let’s take a look at the Eureka source code, in fact, not difficult to understand, the following will be explained.

  • The default is to followread-onlyLook in the cache.
  • If not, start againRead and writeLook in the cache.
  • If found, the read-only cache is updated and the cache found is returned.
  • If not, load it from the local cache Registry.

Three problems arise:

(1) How does the three-level cache data come from?

(2) How is the cache data updated?

(3) How does the cache expire?

Local cache

Let’s take a look at the local cache Registry, a data structure defined as ConcurrentHashMap, which was explained in detail earlier.

When a client initiates a registration request, the registration information is placed in Registry. The following code looks like this:

registry.putIfAbsent(app)
Copy the code

PutIfAbsent: If a duplicate key exists, the value will not be added. If the value corresponding to the key already exists, the value will be returned without replacement.

After the putIfAbsent operation, the client’s registration information is put into Registry.

Let’s take a look at one of these cache constructs: the read/write cache.

4. Read and write cache

A read/write cache, as its name suggests, is a cache that can be both read and write. Reads are primarily for read-only caches to read. Write is basically updating the cache into your own Map.

The following are from the principle of write cache, the source code of write cache, the principle of expiration time, expiration time of the source code of several aspects to answer respectively.

3.1 Write cache principle and source code

I was beginning to think that when we couldn’t read from cache, we would look it up in the database. I looked around, but I couldn’t find a place to read the database.

I then used the IDEA tool to find out where readOnlyCacheMap was used and found it.

Read and write caches use the Guava Cache utility class, which will not be covered in this article. If the key does not exist in the cache when accessing the read/write cache, it is checked locally and then put back into the cache.

It then implements the abstract method load(key), which is used to fetch from the local Registry cache when the read/write cache is not present.

There are two types of read/write cache expiration: timed expiration and real-time expiration. Since the source code above has defined timed expiration intervals, let’s look at timed expiration first.

3.2 Timing and Expiration

When you build the read/write cache, you define how often the entire read/write cache expires. As shown in the following code, the read and write cache expires periodically for 180 seconds.

expireAfterWrite(180s)
Copy the code

3.3 Real-time Expiration

When a new service instance is registered, offline, or fails, the cache of the corresponding service instance will expire.

As shown in the figure below, the registry is at the top and the service instances are at the bottom. The registry is aware that service instances are registered, taken offline, and fail, and will actively expire the read and write cache corresponding service instances.

3.4 Real-time expired source code

From the source level we look at the read and write cache expired source code. The invalidateCache method was called to expire.

File path: com/netflix/had been/registry/AbstractInstanceRegistry Java

Read-only cache

5.1 Scheduled Update

ReadOnlyCacheMap, a read-only cache, has a periodic update mechanism that updates certain keys in the read-only cache every 30 seconds.

It actually iterates through all of its registration information and compares it with the read/write cache. If the registration information is inconsistent, it replaces it with the read/write cache data.

The source code is as follows, there is a scheduled scheduling task, scheduled once every 30 seconds.

The 5.2 update

In addition, when obtaining the registration information, the client first reads the read-only cache. If the read-only cache does not contain the registration information, the client searches for the registration information from the read/write cache and puts it into the read-only cache. If not in the read/write cache, it is loaded from the local registry into the read/write cache, and the registry information is returned.

If this cache is called read-only cache, how can it be updated? Shouldn’t it be immutable?

In fact, the change here is relative to the client, when the client obtains the registry information, the initial access is read-only cache, similar to the database or Redis master-slave architecture, the master is responsible for reading and writing, the slave is responsible for reading. The system then synchronizes information from the master node to the slave node. Does that make sense?

6. Cache configuration

What is the cache configuration of Eureka Server?

6.1 Whether to Enable Read-only Cache

eureka.server.useReadOnlyResponseCache

Whether the client obtains registration information from the read-only cache first. If false, it is fetched directly from the read/write cache. The default is true.

6.2 Interval for periodically updating the read-only cache

eureka.server.responseCacheUpdateIntervalMs

By default, caches updated by read/write caches are synchronized to read-only caches every 30 seconds.

7. Problems with caching

Level 3 caching seems to provide a performance boost. But it also introduces other issues, such as cache inconsistencies.

The read-only cache is refreshed every 30 seconds, which results in data inconsistency with the read/write cache. The registry information obtained by the client is delayed in 30 seconds.

When using Eureka cluster, the problem of cache inconsistency will be more obvious. There will also be inconsistent data of read-only cache between different nodes. Therefore, Eureka can only guarantee high availability, but not strong consistency, that is, AP is guaranteed, but CP is not guaranteed. Such as Zookeeper and Nacos, which will be covered later.

How can inconsistencies be mitigated?

(1) On the server side, we can set the interval for updating the read-only cache. The default interval is 30 seconds. Shorten the interval, such as 15 seconds, because the frequency is too high, which may cause performance problems for Eureka.

(2) On the server side, we can also consider turning off reading registry information from the read-only cache, and Eureka Client directly reads from the read/write cache.

Eight, summary

Eureka Server registry level 3 cache architecture

This article studied the three-tier cache architecture on the Server side of Eureka registry, including Registry, readOnlyCacheMap, and readWriteCacheMap, which are used to store service registration information.

  • By default, registration information is updated from the read/write cache to the read-only cache every 30 seconds.
  • By default, the client reads the registry from the read-only cache first, if not, from the read/write cache, and if not, from the local registry.
  • By default, the read and write cache expires every 180 seconds.
  • When a service instance is registered, offline, or faulty, the read and write cache expires in real time.
  • The introduction of multi-level caching also brings the problem of cache inconsistency. \

References:

www.passjava.cn 

In-depth Analysis of Microservices Architecture

Eureka source