0%

SpringCloud服务优雅启停的打开方式

“宠辱若惊,贵大患若身。
何谓宠辱若惊?
宠为下。
得之若惊,失之若惊,是谓宠辱若惊。
何谓贵大患若身?
吾所以有大患者,为吾有身。
及吾无身,吾有何患?
故贵以身为天下,若可以寄于天下,爱以身为天下者,若可托天下。”1

SpringCloud服务优雅启停的打开方式

The marvel’s service UP and DOWN in elegant model

问题:

1.服务已经发布,在eureka上已经看到注册成功了,但是服务调用方在调用服务时,依然调不到。
2.发布服务时,不能粗暴的kill或者重新部署,由于服务提供方并不支持幂等请求,所以粗暴的方式无可避免导致请求的异常,因此平台要支持服务优雅的上下线。

解决:

对于问题1:

EurekaServer有两个缓存机制:

eurekaserver-cache

  • ReadWriteMap: 当服务注册或者维持心跳时,更新。
  • ReadOnlyMap: 当有服务调用者查询服务列表时,访问。
解决方案:

EurekaServer: marvel-eureka-dev[test].yml

1
#eureka server刷新readCacheMap的时间,注意,client读取的是readCacheMap,这个时间决定了多久会把readWriteCacheMap的缓存更新到readCacheMap上
2
#默认30s
3
eureka.server.responseCacheUpdateIntervalMs=3000
4
#eureka server缓存readWriteCacheMap失效时间,这个只有在这个时间过去后缓存才会失效,失效前不会更新,过期后从registry重新读取注册服务信息,registry是一个ConcurrentHashMap。
5
#由于启用了evict其实就用不太上改这个配置了
6
#默认180s
7
eureka.server.responseCacheAutoExpirationInSeconds=180
8
9
#启用主动失效,并且每次主动失效检测间隔为3s
10
eureka.server.eviction-interval-timer-in-ms=3000

Client:marvel-eureka-client-dev[test].yml

1
#服务过期时间配置,超过这个时间没有接收到心跳EurekaServer就会将这个实例剔除
2
#注意,EurekaServer一定要设置eureka.server.eviction-interval-timer-in-ms否则这个配置无效,这个配置一般为服务刷新时间配置的三倍
3
#默认90s
4
eureka.instance.lease-expiration-duration-in-seconds=15
5
#服务刷新时间配置,每隔这个时间会主动心跳一次
6
#默认30s
7
eureka.instance.lease-renewal-interval-in-seconds=5
8
9
10
#eureka client刷新本地缓存时间
11
#默认30s
12
eureka.client.registryFetchIntervalSeconds=5
13
#eureka客户端ribbon刷新时间
14
#默认30s
15
ribbon.ServerListRefreshInterval=5000

对于问题2:

需要整合actuator,在marvel-client-eureka-dev[test].yml已经整合:

1
management:
2
  endpoint:
3
    health:
4
      show-details: always
5
  endpoints:
6
    web:
7
      exposure:
8
        include: '*'

各个项目在启动的时候,可以看到控制台有如下输出:

1
2019-06-24 14:18:36.810 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/archaius],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2
2019-06-24 14:18:36.811 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/auditevents],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
3
2019-06-24 14:18:36.811 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/beans],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
4
2019-06-24 14:18:36.812 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/health],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
5
2019-06-24 14:18:36.812 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/conditions],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
6
2019-06-24 14:18:36.812 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/configprops],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
7
2019-06-24 14:18:36.812 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/env],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
8
2019-06-24 14:18:36.813 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/env/{toMatch}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
9
2019-06-24 14:18:36.813 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/env],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v2+json || application/json],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
10
2019-06-24 14:18:36.814 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/env],methods=[DELETE],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
11
2019-06-24 14:18:36.814 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/info],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
12
2019-06-24 14:18:36.814 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/logfile],methods=[GET],produces=[application/octet-stream]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
13
2019-06-24 14:18:36.814 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/loggers],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
14
2019-06-24 14:18:36.815 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/loggers/{name}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
15
2019-06-24 14:18:36.815 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/loggers/{name}],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
16
2019-06-24 14:18:36.815 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/heapdump],methods=[GET],produces=[application/octet-stream]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
17
2019-06-24 14:18:36.815 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/threaddump],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
18
2019-06-24 14:18:36.816 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/metrics/{requiredMetricName}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
19
2019-06-24 14:18:36.816 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/metrics],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
20
2019-06-24 14:18:36.816 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/scheduledtasks],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
21
2019-06-24 14:18:36.817 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/httptrace],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
22
2019-06-24 14:18:36.817 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/mappings],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
23
2019-06-24 14:18:36.817 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/refresh],methods=[POST],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
24
2019-06-24 14:18:36.817 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/features],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
25
2019-06-24 14:18:36.818 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/service-registry],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
26
2019-06-24 14:18:36.818 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator/service-registry],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v2+json || application/json],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
27
2019-06-24 14:18:36.819 [main] INFO  o.s.b.a.e.w.s.WebMvcEndpointHandlerMapping - 547 : Mapped "{[/actuator],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto protected java.util.Map<java.lang.String, java.util.Map<java.lang.String, org.springframework.boot.actuate.endpoint.web.Link>> org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping.links(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)

其中:/actuator/service-registry 通过GET请求可以查看服务的状态,通过POST可以设置服务的状态 UP or Down
当设置服务的状态为DOWN时即优雅的关闭(下线)了该服务,查看eureka控制台时,此服务即已下线,通过观察服务的log,当没有任何请求log时可以对服务进行重新发布。

注意:如采用这种方式,请做好api的权限控制,否则:(。

关于Actuator的详细知识,可以点击查看这篇博客,讲的很详细了。

1:老子《道德经》第九章,老子故里,中国鹿邑。