最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Eureka源碼解析服務(wù)離線狀態(tài)變更

 更新時(shí)間:2022年10月15日 12:34:42   作者:hsfxuebao  
這篇文章主要為大家介紹了Eureka源碼解析服務(wù)離線的狀態(tài)變更示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

環(huán)境

1. 服務(wù)離線的方式

服務(wù)離線,即某服務(wù)不能對(duì)外提供服務(wù)了。服務(wù)離線的原因有兩種:服務(wù)下架與服務(wù)下線。

  • 服務(wù)下架:表示這個(gè)已經(jīng)被kill掉了,不能對(duì)外提供服務(wù),自己也不能訪問(wèn)
  • 服務(wù)下線:只是該服務(wù)不能被 eureka server端發(fā)現(xiàn)(不能注冊(cè)),不能被遠(yuǎn)程訪問(wèn),但是可以自己訪問(wèn)自己的服務(wù)

1.1 基于Actuator監(jiān)控器實(shí)現(xiàn)

提交如下POST請(qǐng)求,可實(shí)現(xiàn)相應(yīng)的服務(wù)離線操作:

  • 服務(wù)下架:http://localhost:端口號(hào)/actuator/shutdown 無(wú)需請(qǐng)求體
  • 服務(wù)下線:http://localhost:端口號(hào)/actuator/serviceregistry 請(qǐng)求體為(該方法稱為服務(wù)平滑上下 線)
{
    "status":"OUT_OF_SERVICE"  或 "UP"
}

注意,從Spring Cloud 2020.0.0版本開始,服務(wù)平滑上下線的監(jiān)控終端由service-registry變更為 了serviceregistry

1.2 直接向Eureka Server提交請(qǐng)求

可以通過(guò)直接向Eureka Server提交不同的請(qǐng)求的方式來(lái)實(shí)現(xiàn)指定服務(wù)離線操作:

服務(wù)下架:通過(guò)向eureka server發(fā)送DELETE請(qǐng)求來(lái)刪除指定client的服務(wù)

http://${server}:${port}/eureka/apps/${serviceName}/${instanceId}

服務(wù)下線:通過(guò)向eureka server發(fā)送PUT請(qǐng)求來(lái)修改指定client的status,其中${value}的取值 為:OUT_OF_SERVICE或UP

http://${server}:${port}/eureka/apps/${serviceName}/${instanceId}/stat us?value=${value}

1.3 特殊狀態(tài)CANCEL_OVERRIDE

用戶提交的狀態(tài)修改請(qǐng)求中指定的狀態(tài),除了InstanceInfo的內(nèi)置枚舉類InstanceStatus中定義的狀態(tài) 外,還可以是CANCEL_OVERRIDE狀態(tài)。

若用戶提交的狀態(tài)為CANCEL_OVERRIDE,則Client會(huì)通過(guò)Jersey向Server提交一個(gè)DELETE請(qǐng)求,用于 在Server端將對(duì)應(yīng)InstanceInfooverridenStatus修改為UNKNWON,即刪除了原來(lái)的overridenStatus 的狀態(tài)值。此時(shí),該Client發(fā)送的心跳Server是不接收的。Server會(huì)向該Client返回404。

2. 服務(wù)下架源碼

public class EurekaClientAutoConfiguration {
   @Configuration(proxyBeanMethods = false)
   @ConditionalOnRefreshScope
   protected static class RefreshableEurekaClientConfiguration {
      @Bean(destroyMethod = "shutdown")
      @ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
      @org.springframework.cloud.context.config.annotation.RefreshScope
      @Lazy
      public EurekaClient eurekaClient(ApplicationInfoManager manager, EurekaClientConfig config,
            EurekaInstanceConfig instance, @Autowired(required = false) HealthCheckHandler healthCheckHandler) {
      }
  }
}

當(dāng)Actuator監(jiān)聽到服務(wù)下架時(shí),會(huì)調(diào)用DiscoveryClient.shutdown()方法:

// 服務(wù)下架
@PreDestroy
@Override
public synchronized void shutdown() {
    if (isShutdown.compareAndSet(false, true)) {
        logger.info("Shutting down DiscoveryClient ...");
        // 注銷狀態(tài)改變監(jiān)聽器
        if (statusChangeListener != null && applicationInfoManager != null) {
            applicationInfoManager.unregisterStatusChangeListener(statusChangeListener.getId());
        }
        // todo 取消定時(shí)任務(wù)
        cancelScheduledTasks();
        // If APPINFO was registered
        if (applicationInfoManager != null
                && clientConfig.shouldRegisterWithEureka()
                && clientConfig.shouldUnregisterOnShutdown()) {
            applicationInfoManager.setInstanceStatus(InstanceStatus.DOWN);
            // todo 服務(wù)下架
            unregister();
        }
        if (eurekaTransport != null) {
            eurekaTransport.shutdown();
        }
        heartbeatStalenessMonitor.shutdown();
        registryStalenessMonitor.shutdown();
        Monitors.unregisterObject(this);
        logger.info("Completed shut down of DiscoveryClient");
    }
}

有兩個(gè)核心方法,我們分別看一下。

2.1 cancelScheduledTasks()

取消定時(shí)任務(wù)。

private void cancelScheduledTasks() {
    if (instanceInfoReplicator != null) {
        instanceInfoReplicator.stop();
    }
    if (heartbeatExecutor != null) {
        heartbeatExecutor.shutdownNow();
    }
    if (cacheRefreshExecutor != null) {
        cacheRefreshExecutor.shutdownNow();
    }
    if (scheduler != null) {
        scheduler.shutdownNow();
    }
    if (cacheRefreshTask != null) {
        cacheRefreshTask.cancel();
    }
    if (heartbeatTask != null) {
        heartbeatTask.cancel();
    }
}

2.2 unregister()

發(fā)送服務(wù)下架請(qǐng)求。

void unregister() {
    // It can be null if shouldRegisterWithEureka == false
    if(eurekaTransport != null && eurekaTransport.registrationClient != null) {
        try {
            logger.info("Unregistering ...");
            EurekaHttpResponse<Void> httpResponse = eurekaTransport.registrationClient.cancel(instanceInfo.getAppName(), instanceInfo.getId());
            logger.info(PREFIX + "{} - deregister  status: {}", appPathIdentifier, httpResponse.getStatusCode());
        } catch (Exception e) {
            logger.error(PREFIX + "{} - de-registration failed{}", appPathIdentifier, e.getMessage(), e);
        }
    }
}
@Override
public EurekaHttpResponse<Void> cancel(String appName, String id) {
    String urlPath = "apps/" + appName + '/' + id;
    ClientResponse response = null;
    try {
        Builder resourceBuilder = jerseyClient.resource(serviceUrl).path(urlPath).getRequestBuilder();
        addExtraHeaders(resourceBuilder);
        // delete 請(qǐng)求
        response = resourceBuilder.delete(ClientResponse.class);
        return anEurekaHttpResponse(response.getStatus()).headers(headersOf(response)).build();
    } finally {
        if (logger.isDebugEnabled()) {
            logger.debug("Jersey HTTP DELETE {}/{}; statusCode={}", serviceUrl, urlPath, response == null ? "N/A" : response.getStatus());
        }
        if (response != null) {
            response.close();
        }
    }
}

服務(wù)下架請(qǐng)求:DELETE請(qǐng)求,path:"apps/" + appName + '/' + id;

3. 服務(wù)下線源碼分析(狀態(tài)變更)

Eureka 整合了 Actuator ,可以通過(guò) Actuator 變更實(shí)例在服務(wù)端的狀態(tài)。spring cloud整合eureka,入口在 spring-cloud-common下的spring.factories:

@Configuration(proxyBeanMethods = false)
public class ServiceRegistryAutoConfiguration {
   @ConditionalOnBean(ServiceRegistry.class)
   @ConditionalOnClass(Endpoint.class)
   protected class ServiceRegistryEndpointConfiguration {
      @Autowired(required = false)
      private Registration registration;
      @Bean
      @ConditionalOnAvailableEndpoint
      public ServiceRegistryEndpoint serviceRegistryEndpoint(ServiceRegistry serviceRegistry) {
         ServiceRegistryEndpoint endpoint = new ServiceRegistryEndpoint(serviceRegistry);
         endpoint.setRegistration(this.registration);
         return endpoint;
      }
   }
}

ServiceRegistryAutoConfiguration是一個(gè)配置類,往容器中注入ServiceRegistryEndpoint

@Endpoint(id = "serviceregistry")
public class ServiceRegistryEndpoint {
    ...
   @WriteOperation
   public ResponseEntity<?> setStatus(String status) {
      Assert.notNull(status, "status may not by null");
      if (this.registration == null) {
         return ResponseEntity.status(HttpStatus.NOT_FOUND).body("no registration found");
      }
      // 變更狀態(tài)
      this.serviceRegistry.setStatus(this.registration, status);
      return ResponseEntity.ok().build();
   }
   @ReadOperation
   public ResponseEntity getStatus() {
      if (this.registration == null) {
         return ResponseEntity.status(HttpStatus.NOT_FOUND).body("no registration found");
      }
       // 獲取狀態(tài)
      return ResponseEntity.ok().body(this.serviceRegistry.getStatus(this.registration));
   }
}

3.1 變更狀態(tài)

核心方法ServiceRegistry#setStatus:

@Override
public void setStatus(EurekaRegistration registration, String status) {
   // 獲取實(shí)例信息
   InstanceInfo info = registration.getApplicationInfoManager().getInfo();
   // TODO: howto deal with delete properly?
   if ("CANCEL_OVERRIDE".equalsIgnoreCase(status)) {
      // 如果變更狀態(tài)請(qǐng)求傳過(guò)來(lái) status = "CANCEL_OVERRIDE",向服務(wù)端發(fā)起 Jersey 刪除狀態(tài)請(qǐng)求
      registration.getEurekaClient().cancelOverrideStatus(info);
      return;
   }
   // TODO: howto deal with status types across discovery systems?
   InstanceInfo.InstanceStatus newStatus = InstanceInfo.InstanceStatus.toEnum(status);
   // 如果不是刪除狀態(tài),則向服務(wù)端發(fā)起 Jersey 變更狀態(tài)請(qǐng)求
   registration.getEurekaClient().setStatus(newStatus, info);
}

核心流程有2個(gè),分別為

statusCANCEL_OVERRIDE:

public void cancelOverrideStatus(InstanceInfo info) {
   getEurekaHttpClient().deleteStatusOverride(info.getAppName(), info.getId(), info);
}
@Override
public EurekaHttpResponse<Void> deleteStatusOverride(String appName, String id, InstanceInfo info) {
    String urlPath = "apps/" + appName + '/' + id + "/status";
    ClientResponse response = null;
    try {
        Builder requestBuilder = jerseyClient.resource(serviceUrl)
                .path(urlPath)
                .queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().toString())
                .getRequestBuilder();
        addExtraHeaders(requestBuilder);
        // DELETE 請(qǐng)求
        response = requestBuilder.delete(ClientResponse.class);
        return anEurekaHttpResponse(response.getStatus()).headers(headersOf(response)).build();
    } finally {
        if (logger.isDebugEnabled()) {
            logger.debug("Jersey HTTP DELETE {}/{}; statusCode={}", serviceUrl, urlPath, response == null ? "N/A" : response.getStatus());
        }
        if (response != null) {
            response.close();
        }
    }
}

刪除deleteStatusOverride請(qǐng)求: DELETE請(qǐng)求 path:"apps/" + appName + '/' + id + "/status"

直接調(diào)用setStatus()方法:

@Override
public EurekaHttpResponse<Void> statusUpdate(String appName, String id, InstanceStatus newStatus, InstanceInfo info) {
    String urlPath = "apps/" + appName + '/' + id + "/status";
    ClientResponse response = null;
    try {
        Builder requestBuilder = jerseyClient.resource(serviceUrl)
                .path(urlPath)
                .queryParam("value", newStatus.name())
                .queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().toString())
                .getRequestBuilder();
        addExtraHeaders(requestBuilder);
        // PUT 請(qǐng)求
        response = requestBuilder.put(ClientResponse.class);
        return anEurekaHttpResponse(response.getStatus()).headers(headersOf(response)).build();
    } finally {
        if (logger.isDebugEnabled()) {
            logger.debug("Jersey HTTP PUT {}/{}; statusCode={}", serviceUrl, urlPath, response == null ? "N/A" : response.getStatus());
        }
        if (response != null) {
            response.close();
        }
    }
}

變更狀態(tài)請(qǐng)求:PUT請(qǐng)求,path為 :"apps/" + appName + '/' + id + "/status"

3.2 獲取狀態(tài)

// EurekaServiceRegistry.class
public Object getStatus(EurekaRegistration registration) {
    String appname = registration.getApplicationInfoManager().getInfo().getAppName();
    String instanceId = registration.getApplicationInfoManager().getInfo().getId();
    // 獲取本地實(shí)例信息
    InstanceInfo info = registration.getEurekaClient().getInstanceInfo(appname,
	    instanceId);
    HashMap<String, Object> status = new HashMap<>();
    if (info != null) {
        // 從實(shí)例信息取出相應(yīng)狀態(tài)返回
	status.put("status", info.getStatus().toString());
	status.put("overriddenStatus", info.getOverriddenStatus().toString());
    }
    else {
        // 如果實(shí)例信息不存在,則返回 UNKNOWN 狀態(tài)
	status.put("status", UNKNOWN.toString());
    }
    return status;
}

參考文章

eureka-0.10.11源碼(注釋)

springcloud-source-study學(xué)習(xí)github地址

以上就是Eureka源碼解析服務(wù)離線狀態(tài)變更的詳細(xì)內(nèi)容,更多關(guān)于Eureka 服務(wù)離線狀態(tài)變更的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Springboot整合ActiveMQ實(shí)現(xiàn)消息隊(duì)列的過(guò)程淺析

    Springboot整合ActiveMQ實(shí)現(xiàn)消息隊(duì)列的過(guò)程淺析

    昨天仔細(xì)研究了activeMQ消息隊(duì)列,也遇到了些坑,下面這篇文章主要給大家介紹了關(guān)于SpringBoot整合ActiveMQ的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • Java 你知道什么是耦合、如何解(降低)耦合

    Java 你知道什么是耦合、如何解(降低)耦合

    這篇文章主要介紹了Java 你知道什么是耦合、如何解(降低)耦合的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • java設(shè)計(jì)模式之單例模式的詳解及優(yōu)點(diǎn)

    java設(shè)計(jì)模式之單例模式的詳解及優(yōu)點(diǎn)

    這篇文章主要介紹了java設(shè)計(jì)模式之單例模式的詳解及優(yōu)點(diǎn)的相關(guān)資料,如果一個(gè)類始終只能創(chuàng)建一個(gè)實(shí)例,那么這個(gè)類被稱為單例類,這種設(shè)計(jì)模式被稱為單例模式,需要的朋友可以參考下
    2017-08-08
  • 解決IDEA項(xiàng)目external libraries依賴包消失的問(wèn)題

    解決IDEA項(xiàng)目external libraries依賴包消失的問(wèn)題

    有時(shí)候電腦重啟后,再打開IDEA上的項(xiàng)目時(shí)會(huì)出現(xiàn)external libraries目錄下的依賴包都消失了的情況,只剩下了一個(gè)JDK的包,本文給大家介紹了解決IDEA項(xiàng)目external libraries依賴包消失的辦法,需要的朋友可以參考下
    2024-02-02
  • Springboot配置Swagger的實(shí)現(xiàn)示例

    Springboot配置Swagger的實(shí)現(xiàn)示例

    Swagger 是一種提高 API 開發(fā)和維護(hù)效率的工具,它使開發(fā)者能夠更輕松地構(gòu)建、測(cè)試和文檔化 API,本文主要介紹了Springboot配置Swagger的實(shí)現(xiàn)示例,感興趣的可以了解一下
    2023-10-10
  • Jenkins自動(dòng)化打包為war包

    Jenkins自動(dòng)化打包為war包

    這篇文章主要介紹了Jenkins自動(dòng)化打包為war包,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Java中操作Word修訂功能的示例詳解

    Java中操作Word修訂功能的示例詳解

    Word的修訂功能是一種在文檔中進(jìn)行編輯和審閱的功能,它允許多個(gè)用戶對(duì)同一文檔進(jìn)行修改并跟蹤這些修改,以便進(jìn)行審查和接受或拒絕修改,下面我們就來(lái)學(xué)習(xí)一下Java中操作Word修訂功能的方法,需要的可以參考下
    2023-12-12
  • Java冒泡排序的定義與實(shí)例代碼

    Java冒泡排序的定義與實(shí)例代碼

    這篇文章主要給大家介紹了關(guān)于Java冒泡排序的定義與實(shí)例的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • RocketMQ的四種常用消息隊(duì)列及代碼演示

    RocketMQ的四種常用消息隊(duì)列及代碼演示

    這篇文章主要介紹了RocketMQ的四種常用消息隊(duì)列及代碼演示,普通消息隊(duì)列是最基本的一種消息隊(duì)列,可以按照先進(jìn)先出(FIFO)的順序存儲(chǔ)消息,并且可以被多個(gè)消費(fèi)者同時(shí)消費(fèi),可以通過(guò)在生產(chǎn)者端指定主題名稱和標(biāo)簽來(lái)創(chuàng)建普通消息隊(duì)列,需要的朋友可以參考下
    2024-01-01
  • Spring-Boot框架初步搭建

    Spring-Boot框架初步搭建

    本篇文章主要介紹了Spring-Boot框架初步搭建,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-03-03

最新評(píng)論

紫云| 阿城市| 渝北区| 奈曼旗| 绿春县| 溧水县| 十堰市| 东港市| 革吉县| 绵竹市| 陇南市| 望江县| 钟祥市| 珠海市| 鲁山县| 万全县| 宣化县| 浮山县| 内丘县| 湘潭市| 高雄县| 呼伦贝尔市| 乌审旗| 乌什县| 清水河县| 镇坪县| 昌图县| 方正县| 富民县| 台东县| 蕲春县| 扶绥县| 桃江县| 林州市| 北川| 漳平市| 武隆县| 双江| 湄潭县| 彩票| 普格县|