springCloud+consul優雅停機


之前的方案:先調用待更新的模塊的shutdown的Endpoint,這是springboot的功能實現,consul上可見服務確實下線了,再kill掉進程。但是還會有一些請求被轉發到該節點上,導致少量的錯誤。

總結的幾種:

1、直接kill方式關閉服務進程

2、向注冊中心發送取消注冊命令

3、發指令給注冊中心,改變指定微服務的服務狀態

4、客戶端主動通知注冊中心下線

5、設置指定模塊的服務的狀態,可通過狀態變更來實現再eureka的上下線

 

1、直接kill方式關閉服務進程

kill -9 沒有善后

kill -15  有善后 會發送down狀態到eureka server

kill java進程【不建議】

這種方式簡單粗暴,直接造成的影響就是部分模塊調用時出錯,如果有多台服務器的話,一台一台地重啟還是可以的,前提是調用端得有自己的重試策略,比如使用Feign作為客戶端調用接口的話可以配置ribbon的重試策略,而且被調用方得做好冪等策略,防止重試調用時出現重復數據的問題。

 

2、向注冊中心發送取消注冊命令

2.1、eureka

向eureka 注冊中心發送delete 請求,只是取消注冊服務, 當發送心跳時還是會注冊到eureka

格式為   eureka地址/eureka/apps/服務名稱/實例名稱

請求方式為delete

下面是取消注冊一個服務的例子。

 

  下圖是用postman 發送delete請求

 

2.2、consul

PUT 請求

http://10.200.110.100:8500/v1/agent/service/deregister/tag-10-200-110-100-8778

參考《consul之:常用API接口

3、發指令給注冊中心,改變指定微服務的服務狀態

3.1、eureka

通過eureka變更服務狀態的方式實現服務上下線,不會再發送心跳注冊到eureka server

 

 3.2、consul

PUT方式: http://10.200.110.100:8500/v1/agent/service/maintenance/tag-10-200-110-100-8778?enable=true&reason=sprint40

參考《consul之:常用API接口

執行完成后,consul的控制台如下:

觀察/tag-10-200-110-100-8778的實時日志,看新請求進來后,再停機

 

4、客戶端主動通知注冊中心下線

4.1、eureka

客戶端主動通知注冊中心下線,下線后不會再注冊到eureka了

如果你的eureka客戶端是是一個spring boot應用,可以通過調用以下代碼通知注冊中心下線。

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.netflix.discovery.DiscoveryManager;
import com.shm.common.model.RespVO;
import com.shm.common.util.RespUtil;

@RestController
public class OfflineController {


    @RequestMapping(value = "/offline", method = RequestMethod.GET)
    public RespVO<Object> offLine(){
        DiscoveryManager.getInstance().shutdownComponent();
        return RespUtil.success();
    }
    
    
}

4.2、consul

 

5、設置指定模塊的服務的狀態,可通過狀態變更來實現再eureka的上下線

5.1、eureka

設置服務的狀態,可通過狀態變更來實現再eureka的上下線

pom中加入

actuator的包
       <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

以上的方式都能實現服務的下線,但是有的時候只想要下線某個服務,卻不需要發布,等待事情處理完成后上線此服務,則以上方式就做不到了。這時可以通過設置微服務的狀態來完成此功能。項目中整合了actuator的話就非常簡單了,在項目啟動的時候可以看到控制台的輸出:

/actuator/service-registry 可以已Get的方式獲取當前服務的狀態,以Post的方式修改當前服務狀態,如將服務設置為Down狀態,這樣其他微服務接收到此狀態后將不調用此服務。將order服務狀態設置為Down:

 

看下執行后的效果:

等到流量都沒有進來后,需要發布的話直接發布接口,不需要發布可以直接上線當前服務:

這樣一個服務的上線和下線就優雅的完成了,如果項目中沒有使用Actuator框架,可以模仿Actuator框架的實現方式,詳見類:ServiceRegistryEndpoint

如果要再上線:

5.2、consul

shutdown

springboot1.5版本

首先配置:

endpoints.shutdown.enabled: true
#endpoint.shutdown.enabled: true
endpoint.shutdown.sensitive: false
management.endpoints.web.exposure.include: "shutdown"

management.endpoint.shutdown.enabled=true
management.endpoints.web.exposure.include=shutdown

 

6、/pause端點

Spring Boot 應用提供了/pause端點,利用該端點可實現優雅下線。

使用方式:在想下線應用的application.yml中添加配置,從而啟用並暴露/pause端點:

management:
  endpoint:
    # 啟用pause端點
    pause:
      enabled: true
    # 啟用restart端點,之所以要啟用restart端點,是因為pause端點的啟用依賴restart端點的啟用
    restart:
      enabled: true
  endpoints:
    web:
      exposure:
        include: pause,restart

發送 POST 請求到/actuator/pause端點:

  • curl -X POST http://你想停止的服務實例地址/actuator/pause

執行后的效果類似下圖:

如圖所示,該應用在 Eureka Server 上的狀已被標記為DOWN,但是應用本身其實依然是可以正常對外服務的。在 Spring Cloud 中,Ribbon 做負載均衡時,只會負載到標記為UP的實例上。利用這兩點,你可以:先用/pause端點,將要下線的應用標記為DOWN,但不去真正停止應用;然后過一定的時間(例如 90 秒,或者自己做個監控,看當前實例的流量變成 0 后)再去停止應用,例如kill應用。

  • 缺點 & 局限
缺點 描述
不同的版本配置不大一樣 早期的 Spring Cloud 版本中,pause端點是不依賴restart端點的
無法和 Eureka 的健康檢查配合使用 如果你的服務發現組件用的是 Eureka,並且你的應用開啟了健康檢查eureka.client.healthcheck.enabled = true,那么/pause端點無效

 

總結
以上幾種方式都可以實現微服的下線,3和5的方式最為優雅,可以主動下線和上線,在沒有新流量進來后可以隨時發布,這樣在也不用等到半夜12點發布了。 

 

 

參考:

https://www.cnblogs.com/shihaiming/p/11408684.html

https://www.cnblogs.com/ql211lin/p/10854967.html

https://blog.csdn.net/linxingliang/article/details/106645443

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM