Please state the source of the article. Welcome to add Echo wechat (wechat id: T2421499075) for exchange and learning.


First of all, let’s consider a question: to realize dynamic configuration of NACOS, which one should be pushed by the server or continuously pulled by the client? Which way is more appropriate? This section focuses on these two questions. You can go straight to the conclusion at the end

Dynamic Configuration Description

Spring Cloud Alibaba- Using NACOS as a configuration hub We know that when we change the configuration of the registry, we can get the modified configuration locally almost immediately. That’s the dynamic configuration we’re going to talk about today.

Whether to pull or push

After the configuration center changes the configuration, the client can get the latest configuration. Is it the configuration center pushing the information to the client or the client pulling the configuration information? To figure this out we need to look at the source code

  • Prepare a source code
The source code download address https://github.com/alibaba/nacos/Copy the code

Find NacosConfigService

We see that the implementation of the configuration class maintains a long rotation and a proxy connection. We continue to trace the long rotation code as follows:

There are three things that are done

  • Create a thread pool for scheduled tasks
  • Create a thread pool that holds long connections
  • Create a delayed task, each 10ms checking the configuration information

Among these three things, we can directly look at the implementation of checking configuration information

/** * Check config info. */
public void checkConfigInfo(a) {
    // Dispatch taskes.
    int listenerSize = cacheMap.get().size();
    // Round up the longingTaskCount.
    int longingTaskCount = (int) Math.ceil(listenerSize / ParamUtil.getPerTaskConfigSize());
    if (longingTaskCount > currentLongingTaskCount) {
        for (int i = (int) currentLongingTaskCount; i < longingTaskCount; i++) {
            // The task list is no order.So it maybe has issues when changing.
            executorService.execute(newLongPollingRunnable(i)); } currentLongingTaskCount = longingTaskCount; }}Copy the code

In the code we can see that he executed a LongPollingRunnable event, so what does he do? Let’s look at the corresponding run method.

@Override
public void run(a) {
    
    List<CacheData> cacheDatas = new ArrayList<CacheData>();
    List<String> inInitializingCacheList = new ArrayList<String>();
    try {
        // Check fault-tolerant configuration
        for (CacheData cacheData : cacheMap.get().values()) {
            if (cacheData.getTaskId() == taskId) {
                cacheDatas.add(cacheData);
                try {
                    checkLocalConfig(cacheData);
                    if(cacheData.isUseLocalConfigInfo()) { cacheData.checkListenerMd5(); }}catch (Exception e) {
                    LOGGER.error("get local config info error", e); }}}// Check the configuration center configuration
        List<String> changedGroupKeys = checkUpdateDataIds(cacheDatas, inInitializingCacheList);
        if(! CollectionUtils.isEmpty(changedGroupKeys)) { LOGGER.info("get changedGroupKeys:" + changedGroupKeys);
        }
        
        for (String groupKey : changedGroupKeys) {
            String[] key = GroupKey.parseKey(groupKey);
            String dataId = key[0];
            String group = key[1];
            String tenant = null;
            if (key.length == 3) {
                tenant = key[2];
            }
            try {
                String[] ct = getServerConfig(dataId, group, tenant, 3000L);
                CacheData cache = cacheMap.get().get(GroupKey.getKeyTenant(dataId, group, tenant));
                cache.setContent(ct[0]);
                if (null! = ct[1]) {
                    cache.setType(ct[1]);
                }
                LOGGER.info("[{}] [data-received] dataId={}, group={}, tenant={}, md5={}, content={}, type={}",
                        agent.getName(), dataId, group, tenant, cache.getMd5(),
                        ContentUtils.truncateContent(ct[0]), ct[1]);
            } catch (NacosException ioe) {
                String message = String
                        .format("[%s] [get-update] get changed config exception. dataId=%s, group=%s, tenant=%s", agent.getName(), dataId, group, tenant); LOGGER.error(message, ioe); }}// If there is any change, notify the listener for processing
        for (CacheData cacheData : cacheDatas) {
            if(! cacheData.isInitializing() || inInitializingCacheList .contains(GroupKey.getKeyTenant(cacheData.dataId, cacheData.group, cacheData.tenant))) { cacheData.checkListenerMd5(); cacheData.setInitializing(false);
            }
        }
        inInitializingCacheList.clear();
        
        executorService.execute(this);
        
    } catch (Throwable e) {
        
        // If the rotation training task is abnormal, the next execution time of the task will be punished
        LOGGER.error("longPolling error : ", e);
        executorService.schedule(this, taskPenaltyTime, TimeUnit.MILLISECONDS); }}Copy the code

See here we for dynamic configuration implementation is slowly clear? Throughout the process, we saw that the client maintained a long rotation, and then the configuration center changed, and then the local comparison was updated.

Is it better to pull or push

We have determined that the implementation of dynamic configuration is client-side pull, so why do we choose client-side pull? Instead of server push?

Think about it for a moment. What would be the disadvantages if our remote configuration center solved this problem by pushing?

Pros and cons of push solutions

Advantages: Simple and does not require the client to perform any operations. Disadvantages: Multiple clients need to be pushed, causing heavy pressure on the service segment

Advantages and disadvantages of pull solutions

Advantages: The client scatters services on the server. Disadvantages: Long rotation training

conclusion

  • Dynamic configuration is achieved by client pulling
  • The pull method is more reliable than the push method