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