微架构 springcloud-10. Eureka 心跳管理
常见配置
心跳检测
客户端(Client):
- 注册服务收起发送:>> 每隔n(n=30,默认)秒向Eureka服务端发送信息,刷新注册服务,
- 客户端告知服务端:若在n秒内没有向服务器发送信息,则服务端将其从服务列表中删除
客户端添加如下配置:
#客户端每隔n秒向服务端发送数据包
eureka.instance.leaseRenewalIntervalInSeconds=5
#客户端告知服务端:若在n秒内没有向服务器发送信息,则服务端将其从服务列表中删除
eureka.instance.leaseExpirationDurationInSeconds=10
#配置日志级别
logging.level.com.netflix:DEBUG
服务端(Server):
- 关闭自我保护
- 注册服务周期检测:>> 每隔n(n=90,默认)秒检测服务端是否重新注册服务,否则将服务从服务列表中清除
相关配置如下:
#关闭Eureka服务自我保护
eureka.server.enable-self-preservation=false
#服务端每隔n秒刷新依次服务列表,将无效服务剔除
eureka.server.eviction-interval-timer-in-ms=5000
接下来做的都是单节点测试,故关闭Eureka作为客户端相关的配置,否则启动会报错:
#eureka.client.service-url.defaultZone=http://localhost:8762/eureka/
# 关闭默认注册到eureka服务中心(该项目本身就是服务中心,无需自己注册自己)
eureka.client.register-with-eureka=false
# 关闭自动抓取服务端,该工程本身就是服务端
eureka.client.fetch-registry=false
重启Eureka服务 8761:
2018-03-16 11:47:38.507 DEBUG 70716 --- [tbeatExecutor-0] c.n.d.shared.MonitoredConnectionManager : Get connection: {}->http://localhost:8761, timeout = 5000
2018-03-16 11:47:38.507 DEBUG 70716 --- [tbeatExecutor-0] c.n.d.shared.NamedConnectionPool : [{}->http://localhost:8761] total kept alive: 1, total issued: 0, total allocated: 1 out of 200
2018-03-16 11:47:38.507 DEBUG 70716 --- [tbeatExecutor-0] c.n.d.shared.NamedConnectionPool : Getting free connection [{}->http://localhost:8761][null]
2018-03-16 11:47:38.515 DEBUG 70716 --- [tbeatExecutor-0] c.n.d.shared.MonitoredConnectionManager : Released connection is reusable.
2018-03-16 11:47:38.515 DEBUG 70716 --- [tbeatExecutor-0] c.n.d.shared.NamedConnectionPool : Releasing connection [{}->http://localhost:8761][null]
2018-03-16 11:47:38.515 DEBUG 70716 --- [tbeatExecutor-0] c.n.d.shared.NamedConnectionPool : Pooling connection [{}->http://localhost:8761][null]; keep alive indefinitely
2018-03-16 11:47:38.515 DEBUG 70716 --- [tbeatExecutor-0] c.n.d.shared.NamedConnectionPool : Notifying no-one, there are no waiting threads
2018-03-16 11:47:38.515 DEBUG 70716 --- [tbeatExecutor-0] n.d.s.t.j.AbstractJerseyEurekaHttpClient : Jersey HTTP PUT http://localhost:8761/eureka//apps/APPTWO/192.168.198.2:AppTwo:8083; statusCode=200
2018-03-16 11:47:38.516 DEBUG 70716 --- [tbeatExecutor-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_APPTWO/192.168.198.2:AppTwo:8083 - Heartbeat status: 200
2018-03-16 11:47:43.519 DEBUG 70716 --- [tbeatExecutor-0] c.n.d.shared.MonitoredConnectionManager : Get connection: {}->http://localhost:8761, timeout = 5000
2018-03-16 11:47:43.519 DEBUG 70716 --- [tbeatExecutor-0] c.n.d.shared.NamedConnectionPool : [{}->http://localhost:8761] total kept alive: 1, total issued: 0, total allocated: 1 out of 200
2018-03-16 11:47:43.519 DEBUG 70716 --- [tbeatExecutor-0] c.n.d.shared.NamedConnectionPool : Getting free connection [{}->http://localhost:8761][null]
2018-03-16 11:47:43.528 DEBUG 70716 --- [tbeatExecutor-0] c.n.d.shared.MonitoredConnectionManager : Released connection is reusable.
2018-03-16 11:47:43.529 DEBUG 70716 --- [tbeatExecutor-0] c.n.d.shared.NamedConnectionPool : Releasing connection [{}->http://localhost:8761][null]
2018-03-16 11:47:43.529 DEBUG 70716 --- [tbeatExecutor-0] c.n.d.shared.NamedConnectionPool : Pooling connection [{}->http://localhost:8761][null]; keep alive indefinitely
2018-03-16 11:47:43.529 DEBUG 70716 --- [tbeatExecutor-0] c.n.d.shared.NamedConnectionPool : Notifying no-one, there are no waiting threads
2018-03-16 11:47:43.529 DEBUG 70716 --- [tbeatExecutor-0] n.d.s.t.j.AbstractJerseyEurekaHttpClient : Jersey HTTP PUT http://localhost:8761/eureka//apps/APPTWO/192.168.198.2:AppTwo:8083; statusCode=200
2018-03-16 11:47:43.529 DEBUG 70716 --- [tbeatExecutor-0] com.netflix.discovery.DiscoveryClient
## 服务端每隔5秒刷新服务列表
2018-03-19 15:44:05.760 INFO 17660 --- [a-EvictionTimer] c.n.e.registry.AbstractInstanceRegistry : Running the evict task with compensationTime 0ms
2018-03-19 15:44:10.761 INFO 17660 --- [a-EvictionTimer] c.n.e.registry.AbstractInstanceRegistry : Running the evict task with compensationTime 0ms
重启客户端服务 8081:
2018-03-20 15:51:15.353 DEBUG 15556 --- [tbeatExecutor-0] c.n.d.shared.MonitoredConnectionManager : Get connection: {}->http://localhost:8761, timeout = 5000
2018-03-20 15:51:15.353 DEBUG 15556 --- [tbeatExecutor-0] c.n.d.shared.NamedConnectionPool : [{}->http://localhost:8761] total kept alive: 1, total issued: 0, total allocated: 1 out of 200
2018-03-20 15:51:15.353 DEBUG 15556 --- [tbeatExecutor-0] c.n.d.shared.NamedConnectionPool : Getting free connection [{}->http://localhost:8761][null]
2018-03-20 15:51:15.356 DEBUG 15556 --- [tbeatExecutor-0] c.n.d.shared.MonitoredConnectionManager : Released connection is reusable.
2018-03-20 15:51:15.356 DEBUG 15556 --- [tbeatExecutor-0] c.n.d.shared.NamedConnectionPool : Releasing connection [{}->http://localhost:8761][null]
2018-03-20 15:51:15.357 DEBUG 15556 --- [tbeatExecutor-0] c.n.d.shared.NamedConnectionPool : Pooling connection [{}->http://localhost:8761][null]; keep alive indefinitely
2018-03-20 15:51:15.357 DEBUG 15556 --- [tbeatExecutor-0] c.n.d.shared.NamedConnectionPool : Notifying no-one, there are no waiting threads
2018-03-20 15:51:15.357 DEBUG 15556 --- [tbeatExecutor-0] n.d.s.t.j.AbstractJerseyEurekaHttpClient : Jersey HTTP PUT http://localhost:8761/eureka//apps/APPONE/192.168.198.2:AppOne:8081; statusCode=200
2018-03-20 15:51:15.357 DEBUG 15556 --- [tbeatExecutor-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_APPONE/192.168.198.2:AppOne:8081 - Heartbeat status: 200
2018-03-20 15:51:20.358 DEBUG 15556 --- [tbeatExecutor-0] c.n.d.shared.MonitoredConnectionManager : Get connection: {}->http://localhost:8761, timeout = 5000
2018-03-20 15:51:20.358 DEBUG 15556 --- [tbeatExecutor-0] c.n.d.shared.NamedConnectionPool : [{}->http://localhost:8761] total kept alive: 1, total issued: 0, total allocated: 1 out of 200
2018-03-20 15:51:20.358 DEBUG 15556 --- [tbeatExecutor-0] c.n.d.shared.NamedConnectionPool : Getting free connection [{}->http://localhost:8761][null]
2018-03-20 15:51:20.361 DEBUG 15556 --- [tbeatExecutor-0] c.n.d.shared.MonitoredConnectionManager : Released connection is reusable.
2018-03-20 15:51:20.361 DEBUG 15556 --- [tbeatExecutor-0] c.n.d.shared.NamedConnectionPool : Releasing connection [{}->http://localhost:8761][null]
2018-03-20 15:51:20.361 DEBUG 15556 --- [tbeatExecutor-0] c.n.d.shared.NamedConnectionPool : Pooling connection [{}->http://localhost:8761][null]; keep alive indefinitely
2018-03-20 15:51:20.361 DEBUG 15556 --- [tbeatExecutor-0] c.n.d.shared.NamedConnectionPool : Notifying no-one, there are no waiting threads
2018-03-20 15:51:20.361 DEBUG 15556 --- [tbeatExecutor-0] n.d.s.t.j.AbstractJerseyEurekaHttpClient : Jersey HTTP PUT http://localhost:8761/eureka//apps/APPONE/192.168.198.2:AppOne:8081; statusCode=200
2018-03-20 15:51:20.361 DEBUG 15556 --- [tbeatExecutor-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_APPONE/192.168.198.2:AppOne:8081 - Heartbeat status: 200
客户端每隔5秒向服务端发送信息!
强制停止客户端,查看服务端信息,打印:
2018-03-20 15:51:43.523 INFO 13276 --- [a-EvictionTimer] c.n.e.registry.AbstractInstanceRegistry : Evicting 1 items (expired=1, evictionLimit=1)
2018-03-20 15:51:43.523 WARN 13276 --- [a-EvictionTimer] c.n.e.registry.AbstractInstanceRegistry : DS: Registry: expired lease for APPONE/192.168.198.2:AppOne:8081
2018-03-20 15:51:43.524 INFO 13276 --- [a-EvictionTimer] c.n.e.registry.AbstractInstanceRegistry : Cancelled instance APPONE/192.168.198.2:AppOne:8081 (replication=false)
服务端已将无效服务 AppOne:8081 剔除出服务列表
一个客户端(App2)要访问另一个客户端(App1)的服务,App2在启动过程中就会首先读取服务列表,将App1服务存储到自己(App2)上,App2 访问时则根据此路由访问App1的服务,那么App2如何确保App1服务一直是有效的呢?比如App1异常中断服务;所以,各App本身也会定时的向Eureka确认,刷新自己的可用的服务列表,默认是每隔 30s 向Eureka服务中心确认,此配置更改如下:
# 定时的向Eureka确认,刷新自己的可用的服务列表,修改为5s
eureka.client.registry-fetch-interval-seconds=5
#将原有注册相关配置时间间隔增大:
# 客户端每隔n秒向服务端发送数据包
eureka.instance.leaseRenewalIntervalInSeconds=60
# 客户端告知服务端:若在n秒内没有向服务器发送信息,则服务端将其从服务列表中删除
eureka.instance.leaseExpirationDurationInSeconds=600
重启App2,后台会没间隔5秒打印打印如下信息:
2018-03-21 09:42:59.080 DEBUG 19496 --- [freshExecutor-0] c.n.d.shared.MonitoredConnectionManager : Get connection: {}->http://localhost:8761, timeout = 5000
2018-03-21 09:42:59.080 DEBUG 19496 --- [freshExecutor-0] c.n.d.shared.NamedConnectionPool : [{}->http://localhost:8761] total kept alive: 1, total issued: 0, total allocated: 1 out of 200
2018-03-21 09:42:59.080 DEBUG 19496 --- [freshExecutor-0] c.n.d.shared.NamedConnectionPool : Getting free connection [{}->http://localhost:8761][null]
2018-03-21 09:42:59.085 DEBUG 19496 --- [freshExecutor-0] c.n.d.shared.MonitoredConnectionManager : Released connection is reusable.
2018-03-21 09:42:59.085 DEBUG 19496 --- [freshExecutor-0] c.n.d.shared.NamedConnectionPool : Releasing connection [{}->http://localhost:8761][null]
2018-03-21 09:42:59.085 DEBUG 19496 --- [freshExecutor-0] c.n.d.shared.NamedConnectionPool : Pooling connection [{}->http://localhost:8761][null]; keep alive indefinitely
2018-03-21 09:42:59.085 DEBUG 19496 --- [freshExecutor-0] c.n.d.shared.NamedConnectionPool : Notifying no-one, there are no waiting threads
2018-03-21 09:42:59.085 DEBUG 19496 --- [freshExecutor-0] n.d.s.t.j.AbstractJerseyEurekaHttpClient : Jersey HTTP GET http://localhost:8761/eureka//apps/delta?; statusCode=200
2018-03-21 09:42:59.085 DEBUG 19496 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : Got delta update with apps hashcode UP_1_
2018-03-21 09:42:59.085 DEBUG 19496 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : Added instance 192.168.198.2:AppTwo:8083 to the existing apps in region null
2018-03-21 09:42:59.085 DEBUG 19496 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : Deleted instance 192.168.198.2:AppOne:8081 to the existing apps
2018-03-21 09:42:59.085 DEBUG 19496 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : The total number of instances fetched by the delta processor : 2
2018-03-21 09:42:59.085 DEBUG 19496 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : The total number of all instances in the client now is 1
2018-03-21 09:42:59.086 DEBUG 19496 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : Completed cache refresh task for discovery. All Apps hash code is Local region apps hashcode: UP_1_, is fetching remote regions? false
2018-03-21 09:43:04.087 DEBUG 19496 --- [freshExecutor-0] c.n.d.shared.MonitoredConnectionManager : Get connection: {}->http://localhost:8761, timeout = 5000
2018-03-21 09:43:04.087 DEBUG 19496 --- [freshExecutor-0] c.n.d.shared.NamedConnectionPool : [{}->http://localhost:8761] total kept alive: 1, total issued: 0, total allocated: 1 out of 200
2018-03-21 09:43:04.087 DEBUG 19496 --- [freshExecutor-0] c.n.d.shared.NamedConnectionPool : Getting free connection [{}->http://localhost:8761][null]
2018-03-21 09:43:04.091 DEBUG 19496 --- [freshExecutor-0] c.n.d.shared.MonitoredConnectionManager : Released connection is reusable.
2018-03-21 09:43:04.091 DEBUG 19496 --- [freshExecutor-0] c.n.d.shared.NamedConnectionPool : Releasing connection [{}->http://localhost:8761][null]
2018-03-21 09:43:04.091 DEBUG 19496 --- [freshExecutor-0] c.n.d.shared.NamedConnectionPool : Pooling connection [{}->http://localhost:8761][null]; keep alive indefinitely
2018-03-21 09:43:04.091 DEBUG 19496 --- [freshExecutor-0] c.n.d.shared.NamedConnectionPool : Notifying no-one, there are no waiting threads
2018-03-21 09:43:04.091 DEBUG 19496 --- [freshExecutor-0] n.d.s.t.j.AbstractJerseyEurekaHttpClient : Jersey HTTP GET http://localhost:8761/eureka//apps/delta?; statusCode=200
2018-03-21 09:43:04.091 DEBUG 19496 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : Got delta update with apps hashcode UP_1_
2018-03-21 09:43:04.091 DEBUG 19496 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : Deleted instance 192.168.198.2:AppOne:8081 to the existing apps
2018-03-21 09:43:04.091 DEBUG 19496 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : The total number of instances fetched by the delta processor : 1
2018-03-21 09:43:04.091 DEBUG 19496 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : The total number of all instances in the client now is 1
2018-03-21 09:43:04.091 DEBUG 19496 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : Completed cache refresh task for discovery. All Apps hash code is Local region apps hashcode: UP_1_, is fetching remote regions? false
将App1 /sayMesg/{word} 业务逻辑代码更改如下:
@RequestMapping(value = "/sayMesg/{word}")
public @ResponseBody String sayMesg(@PathVariable String word){
if(word==null){
return "未接收到参数!";
}
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < word.length(); i++) {
int acii = word.charAt(i);
buffer.append(acii + ",");
}
return active + buffer.toString() ;
}
# 即返回参数world 的Ascii码
回顾App2 /getAppOneMesg/{mesg} 代码:
@RequestMapping("/getAppOneMesg/{mesg}")
public @ResponseBody String getAppOneMesg(@PathVariable String mesg){
String strMesg=restTemplate.getForObject("http://APPONE/sayMesg/" + mesg, String.class);
return "访问App2,从App1 收到信息:“"+strMesg+"”";
}
重新梳理逻辑:重启Eureka、App1、App2,待启动完成,访问 http://192.168.198.2:8083/getAppOneMesg/123456,页面打印:
访问App2,从App1 收到信息:“808149,50,51,52,53,54,“
强制停止App1服务,观察App2 控制台:
##其中打印:
2018-03-21 10:33:24.061 DEBUG 6636 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : Deleted instance 192.168.198.2:AppOne:8081 to the existing apps
App1 服务停止,那么Eureka服务端在扫描规则下会将App1从服务列表中剔除,App2 刷新本地服务列表,将不存在于服务端的App1从本地剔除
再访问:http://192.168.198.2:8083/getAppOneMesg/123456,页面打印:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Wed Mar 21 10:36:43 CST 2018
There was an unexpected error (type=Internal Server Error, status=500).
No instances available for APPONE
# App1 已经停止服务,且本地(App2)已剔除该服务信息,故无法访问
重启App1,观察App2 客户端:
# 其中打印
2018-03-21 10:39:07.162 DEBUG 21960 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : Added instance 192.168.198.2:AppOne:8081 to the existing apps in region null
# 说明App2已经将App1服务添加到本地
再访问:http://192.168.198.2:8083/getAppOneMesg/123456,页面打印:
访问App2,从App1 收到信息:“808149,50,51,52,53,54,“
# 应用恢复正常
客户端获取本地服务信息,以下示例以App2为列
- 注入DiscoveryClient
@Autowired
private DiscoveryClient discoveryClient;
- 获取服务名称,即:App1、App2
@GetMapping("/discoveryClientList")
public List discoveryClientList(){
/*获取Eureka 中的服务名称列表*/
List<String> services = discoveryClient.getServices();
return services;
}
- 获取服务具体实例
@GetMapping("/discoveryClientInstanceList")
public List<Map> discoveryClientInstanceList(){
/*获取客户端实例列表*/
List<Map> list = new ArrayList<Map>();
Map<String, Object> map = new HashMap<String, Object>();
List<String> servicesNames = discoveryClient.getServices(); //获取名称
for (String name : servicesNames) {
map = new HashMap<String, Object>();
List<ServiceInstance> instanceList = discoveryClient.getInstances(name);
Map objs = new HashMap();
for (ServiceInstance instance : instanceList) {
objs.put("host", instance.getHost());
objs.put("port", instance.getPort());
objs.put("serviceId",instance.getServiceId());
objs.put("uri", instance.getUri());
}
map.put(name, objs);
list.add(map);
}
return list;
}
访问:http://192.168.198.2:8083/discoveryClientList 页面响应:
["appone","apptwo"]
# 只是服务名
访问:http://192.168.198.2:8083/discoveryClientInstanceList 页面响应:
[
{"appone":{"port":8081,"host":"192.168.198.2","serviceId":"APPONE","uri":"http://192.168.198.2:8081"}},
{"apptwo":{"port":8083,"host":"192.168.198.2","serviceId":"APPTWO","uri":"http://192.168.198.2:8083"}}
]
# 各服务名实例包括:端口、地址、ID、URI 等
配置元数据,App2 配置文件添加如下配置:
# 配置元数据:metadata
eureka.instance.metadata-map.companename:PersonJack
eureka.instance.metadata-map.address:chongqing
从DiscoveryClient 获取元数据,其实也是从ServiceInstance 中获取的,配置文件中spring.application.name即为实例名,故相关Controller 书写如下:
@GetMapping("/metaMap")
public @ResponseBody List metaMap(){
List<ServiceInstance> instanceList = discoveryClient.getInstances("AppTwo");
List list = new ArrayList();
for (ServiceInstance instance : instanceList) {
Map map=instance.getMetadata();
list.add(map);
}
return list;
}
访问:http://192.168.198.2:8083/metaMap 页面响应如下:
[{"companename":"PersonJack","address":"chongqing"}]
# 元数据成功获取