是这样的, 最近使用 rancher 搭建 spring-cloud 环境的时候 出现了一个这样的问题
访问 zuul 给定的接口的时候 需要路由到 app0 模块, 但是 却报出了一个
Caused by: java.net.UnknownHostException: docker-cloud-app0-0.docker-cloud-eureka.docker-cloud.svc.cluster.local: Name does not resolve
环境信息 : jdk8 + spring-cloud-x 2.2.3-RELEASE + spring-cloud-zuul-starter 1.3.1.RELEASE
访问给定的服务错误页面如下
zuul 日志错误信息如下
可以看到是在像 app0 发送网络请求的时候, 出现了异常, 大致的原因是 从 app0 上面拿到的 主机名是 "docker-cloud-app0-0.docker-cloud-eureka.docker-cloud.svc.cluster.local", 然后 通过这个域名 解析不到目标服务器
Caused by: java.net.UnknownHostException: docker-cloud-app0-0.docker-cloud-eureka.docker-cloud.svc.cluster.local: Name does not resolve
at java.net.Inet4AddressImpl.lookupAllHostAddr(Native Method) ~[na:1.8.0_201]
at java.net.InetAddress$2.lookupAllHostAddr(InetAddress.java:929) ~[na:1.8.0_201]
at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1324) ~[na:1.8.0_201]
at java.net.InetAddress.getAllByName0(InetAddress.java:1277) ~[na:1.8.0_201]
at java.net.InetAddress.getAllByName(InetAddress.java:1193) ~[na:1.8.0_201]
at java.net.InetAddress.getAllByName(InetAddress.java:1127) ~[na:1.8.0_201]
at org.apache.http.impl.conn.SystemDefaultDnsResolver.resolve(SystemDefaultDnsResolver.java:44) ~[httpclient-4.3.4.jar!/:4.3.4]
at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:101) ~[httpclient-4.3.4.jar!/:4.3.4]
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:318) ~[httpclient-4.3.4.jar!/:4.3.4]
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:363) ~[httpclient-4.3.4.jar!/:4.3.4]
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:219) ~[httpclient-4.3.4.jar!/:4.3.4]
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195) ~[httpclient-4.3.4.jar!/:4.3.4]
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:86) ~[httpclient-4.3.4.jar!/:4.3.4]
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108) ~[httpclient-4.3.4.jar!/:4.3.4]
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184) ~[httpclient-4.3.4.jar!/:4.3.4]
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) ~[httpclient-4.3.4.jar!/:4.3.4]
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106) ~[httpclient-4.3.4.jar!/:4.3.4]
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57) ~[httpclient-4.3.4.jar!/:4.3.4]
at org.springframework.cloud.netflix.ribbon.apache.RibbonLoadBalancingHttpClient.execute(RibbonLoadBalancingHttpClient.java:94) ~[spring-cloud-netflix-core-1.3.1.RELEASE.jar!/:1.3.1.RELEASE]
at org.springframework.cloud.netflix.ribbon.apache.RibbonLoadBalancingHttpClient.execute(RibbonLoadBalancingHttpClient.java:43) ~[spring-cloud-netflix-core-1.3.1.RELEASE.jar!/:1.3.1.RELEASE]
at com.netflix.client.AbstractLoadBalancerAwareClient$1.call(AbstractLoadBalancerAwareClient.java:109) ~[ribbon-loadbalancer-2.2.2.jar!/:2.2.2]
at com.netflix.loadbalancer.reactive.LoadBalancerCommand$3$1.call(LoadBalancerCommand.java:303) ~[ribbon-loadbalancer-2.2.2.jar!/:2.2.2]
at com.netflix.loadbalancer.reactive.LoadBalancerCommand$3$1.call(LoadBalancerCommand.java:287) ~[ribbon-loadbalancer-2.2.2.jar!/:2.2.2]
at rx.internal.util.ScalarSynchronousObservable$3.call(ScalarSynchronousObservable.java:231) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.internal.util.ScalarSynchronousObservable$3.call(ScalarSynchronousObservable.java:228) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.Observable.unsafeSubscribe(Observable.java:10151) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.drain(OnSubscribeConcatMap.java:286) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.onNext(OnSubscribeConcatMap.java:144) ~[rxjava-1.2.0.jar!/:1.2.0]
at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:185) ~[ribbon-loadbalancer-2.2.2.jar!/:2.2.2]
at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:180) ~[ribbon-loadbalancer-2.2.2.jar!/:2.2.2]
at rx.Observable.unsafeSubscribe(Observable.java:10151) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:94) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:42) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.Observable.unsafeSubscribe(Observable.java:10151) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber$1.call(OperatorRetryWithPredicate.java:127) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.internal.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.enqueue(TrampolineScheduler.java:73) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.internal.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.schedule(TrampolineScheduler.java:52) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber.onNext(OperatorRetryWithPredicate.java:79) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber.onNext(OperatorRetryWithPredicate.java:45) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.internal.util.ScalarSynchronousObservable$WeakSingleProducer.request(ScalarSynchronousObservable.java:276) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.Subscriber.setProducer(Subscriber.java:209) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.internal.util.ScalarSynchronousObservable$JustOnSubscribe.call(ScalarSynchronousObservable.java:138) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.internal.util.ScalarSynchronousObservable$JustOnSubscribe.call(ScalarSynchronousObservable.java:129) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.Observable.subscribe(Observable.java:10247) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.Observable.subscribe(Observable.java:10214) ~[rxjava-1.2.0.jar!/:1.2.0]
at rx.observables.BlockingObservable.blockForSingle(BlockingObservable.java:444) ~[rxjava-1.2.0.jar!/:1.2.0]
... 131 common frames omitted
然后期望的正常效果如下
先说一下 解决方式吧, 增加配置 eureka.instance.prefer-ip-address = true
当然 还有其他的多种解决方式, 也许你看了本文, 再去跟一下代码 也能发现一些
在 zuul 启动的时候 会向注册中心请求, 全量获取一次应用的信息(还提供了增量, 指定引用获取应用信息等等 服务)
response 信息如下
可以看到 目前只有一个 app0 注册到了 eureka 上面
{
"applications": {
"versions__delta": "1",
"apps__hashcode": "UP_1_",
"application": [
{
"name": "APP0",
"instance": [
{
"instanceId": "192.168.1.113:app0:7901",
"hostName": "192.168.1.113",
"app": "APP0",
"ipAddr": "192.168.1.113",
"status": "UP",
"overriddenStatus": "UNKNOWN",
"port": {
"$": 7901,
"@enabled": "true"
},
"securePort": {
"$": 443,
"@enabled": "false"
},
"countryId": 1,
"dataCenterInfo": {
"@class": "com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo",
"name": "MyOwn"
},
"leaseInfo": {
"renewalIntervalInSecs": 30,
"durationInSecs": 90,
"registrationTimestamp": 1594519419369,
"lastRenewalTimestamp": 1594520049830,
"evictionTimestamp": 0,
"serviceUpTimestamp": 1594519418829
},
"metadata": {
"management.port": "7901"
},
"homePageUrl": "http://192.168.1.113:7901/",
"statusPageUrl": "http://192.168.1.113:7901/actuator/info",
"healthCheckUrl": "http://192.168.1.113:7901/actuator/health",
"vipAddress": "app0",
"secureVipAddress": "app0",
"isCoordinatingDiscoveryServer": "false",
"lastUpdatedTimestamp": "1594519419369",
"lastDirtyTimestamp": "1594519418766",
"actionType": "ADDED"
}
]
}
]
}
}
看一下控制台, 只有一个 app0 应用
再来看一下 zuul 向 app0 发送请求的地方, uri 是一个相对路径的 url, 因此发送请求是取 请求头里面的 Host 作为对方服务器(5.1.2 Request-URI)
这里的 Host 的数据来自于 route 的 targetHost
route 的 targetHost 来自于 上层请求的 requestUri
再往上看, requestUri 来自于 目标服务器(app0), 拼接上 请求的相对路径
目标服务器(app0) 来自于 loadBalanceContext 的计算
使用 eurekaClient 通过 key 获取 服务列表
这里就是 获取所有的 应用信息的地方, 呵呵 看上面这个 getApplicationsInternal 熟悉吗?
对 就是本节 上面第一张图, 获取所有的 applications
再来看一下 InstanceInfo 适配成 Server 的地方, 这传入了一个 shouldUseIpAddr, 默认是 false, 也会影响 server 的 host 是 ip 还是 hostname (但是和我们这里的场景没有关系)
因此到这里 可以得出的结论是 zuul 向 app0 发送请求的时候 使用的是 从 eureka 获取的 InstanceInfo 的 hostname
通过上面可以发现, zuul 是通过来访问eureka, 来获取应用的信息
http://eureka-host:8761/eureka/apps(全量获取所有应用)
http://eureka-host:8761/eureka/apps/APP0 (获取APP0的应用信息)
我们再来看一下 eureka 这边的实现, 从简单的开始看吧, 看获取某一个应用的信息
藏得也是非常的深了, 不是普通的 springmvc 开放出来的服务(jesery服务)
获取 APP0 对应的 Application, 然后把它 xml 编码, zuul 拿到的就是这个数据
当然 我们也可以直接在 浏览器中访问 : http://localhost:8761/eureka/apps/APP0
那么 InstanceInfo 有何什么有关系呢?
eureka 使用的 instanceInfo, 来自于 app0 模块向注册中心注册的时候, 使用的 instanceInfo
DiscoveryClient 里面的 instanceInfo 从哪里来的呢? 从一个 applicationInfoManager 里面取得的 instanceInfo
那么 ApplicationManager 有何 InstanceInfo 有什么关系呢?
原来 instanceInfo 是由 eurekaInstanceConfigBean 创建出来的
根据 eurekaInstanceConfigBean 创建 instanceInfo
我们这里 需要着重关注 hostName
EurekaInstanceConfigBean.getHostName 方法如下, 这里的 preferIpAddress 对应于我们上面显示配置的 "eureka.instance.prefer-ip-address"
EurekaInstanceConfigBean 里面初始化 ipAddress, hostname 的地方
理论上面的东西 上面都说的差不多了, 那么我们来看一下 我们这个问题 在 rancher 里面的一些实际情况吧
我再 APP0 项目后面 嵌套了这样的一段代码, 用于调试
EurekaInstanceConfigBean instance = (SpringContext.getContext().getBean(EurekaInstanceConfigBean.class));
String cloudClientHostName = instance.getEnvironment().getProperty("spring.cloud.client.hostname");
System.out.println("instance -- " + instance);
System.out.println("cloudClientHostName -- " + cloudClientHostName);
System.out.println("instanceHostName -- " + instance.getHostname());
InetUtils inetUtils = SpringContext.getContext().getBean(InetUtils.class);
InetUtils.HostInfo hostInfo = inetUtils.findFirstNonLoopbackHostInfo();
System.out.println("hostInfo -- " + hostInfo.getHostname());
System.out.println("hostInfo -- " + hostInfo.getIpAddress());
instance 就是 APP0 创建的 EurekaInstanceConfigBean
cloudClientHostName 是用于创建默认的 instanceId 的时候需要使用, 默认也是使用的 inetUtils 获取的数据(和上面的内容没太大的关系)
hostInfo 是用于调试的, 查看 inetUtils 获取到的数据 究竟是什么
在 preferIdAddress 为 false 的时候, rancher 上面 APP0 输出数据如下
instance -- EurekaInstanceConfigBean{hostInfo=org.springframework.cloud.commons.util.InetUtils$HostInfo@59328218, inetUtils=org.springframework.cloud.commons.util.InetUtils@5345dfe8, appname='app0', appGroupName='null', instanceEnabledOnit=false, nonSecurePort=7901, securePort=443, nonSecurePortEnabled=true, securePortEnabled=false, leaseRenewalIntervalInSeconds=30, leaseExpirationDurationInSeconds=90, virtualHostName='app0', instanceId='docker-cloud-app0-0.docker-cloud-eureka.docker-cloud.svc.cluster.local:app0:7901', secureVirtualHostName='app0', aSGName='null', metadataMap={management.port=7901}, dataCenterInfo=com.netflix.appinfo.MyDataCenterInfo@478967eb, ipAddress='10.1.0.212', statusPageUrlPath='/actuator/info', statusPageUrl='http://docker-cloud-app0-0.docker-cloud-eureka.docker-cloud.svc.cluster.local:7901/actuator/info', homePageUrlPath='/', homePageUrl='null', healthCheckUrlPath='/actuator/health', healthCheckUrl='http://docker-cloud-app0-0.docker-cloud-eureka.docker-cloud.svc.cluster.local:7901/actuator/health', secureHealthCheckUrl='null', namespace='eureka', hostname='docker-cloud-app0-0.docker-cloud-eureka.docker-cloud.svc.cluster.local', preferIpAddress=false, initialStatus=UP, defaultAddressResolutionOrder=[], environment=StandardServletEnvironment {activeProfiles=[], defaultProfiles=[default], propertySources=[MapPropertySource {name='server.ports'}, BootstrapPropertySource {name='bootstrapProperties-classpath:/config/application-rancher-dev.yml'}, ConfigurationPropertySourcesPropertySource {name='configurationProperties'}, StubPropertySource {name='servletConfigInitParams'}, ServletContextPropertySource {name='servletContextInitParams'}, PropertiesPropertySource {name='systemProperties'}, OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}, RandomValuePropertySource {name='random'}, MapPropertySource {name='springCloudClientHostInfo'}, OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.yml]'}, OriginTrackedMapPropertySource {nam
e='applicationConfig: [classpath:/bootstrap.properties]'}, MapPropertySource {name='springCloudDefaultProperties'}, CachedRandomPropertySource {name='cachedrandom'}]}, }
cloudClientHostName -- docker-cloud-app0-0.docker-cloud-eureka.docker-cloud.svc.cluster.local
instanceHostName -- docker-cloud-app0-0.docker-cloud-eureka.docker-cloud.svc.cluster.local
hostInfo -- docker-cloud-app0-0.docker-cloud-eureka.docker-cloud.svc.cluster.local
hostInfo -- 10.1.0.212
在 preferIdAddress 为 true 的时候, rancher 上面 APP0 输出数据如下
instance -- EurekaInstanceConfigBean{hostInfo=org.springframework.cloud.commons.util.InetUtils$HostInfo@734ce281, inetUtils=org.springframework.cloud.commons.util.InetUtils@49b89425, appname='app0', appGroupName='null', instanceEnabledOnit=false, nonSecurePort=7901, securePort=443, nonSecurePortEnabled=true, securePortEnabled=false, leaseRenewalIntervalInSeconds=30, leaseExpirationDurationInSeconds=90, virtualHostName='app0', instanceId='docker-cloud-app0-0.docker-cloud-eureka.docker-cloud.svc.cluster.local:app0:7901', secureVirtualHostName='app0', aSGName='null', metadataMap={management.port=7901}, dataCenterInfo=com.netflix.appinfo.MyDataCenterInfo@59328218, ipAddress='10.1.0.212', statusPageUrlPath='/actuator/info', statusPageUrl='http://10.1.0.212:7901/actuator/info', homePageUrlPath='/', homePageUrl='null', healthCheckUrlPath='/actuator/health', healthCheckUrl='http://10.1.0.212:7901/actuator/health', secureHealthCheckUrl='null', namespace='eureka', hostname='docker-cloud-app0-0.docker-cloud-eureka.docker-cloud.svc.cluster.local', preferIpAddress=true, initialStatus=UP, defaultAddressResolutionOrder=[], environment=StandardServletEnvironment {activeProfiles=[], defaultProfiles=[default], propertySources=[MapPropertySource {name='server.ports'}, BootstrapPropertySource {name='bootstrapProperties-classpath:/config/application-rancher-dev.yml'}, ConfigurationPropertySourcesPropertySource {name='configurationProperties'}, StubPropertySource {name='servletConfigInitParams'}, ServletContextPropertySource {name='servletContextInitParams'}, PropertiesPropertySource {name='systemProperties'}, OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}, RandomValuePropertySource {name='random'}, MapPropertySource {name='springCloudClientHostInfo'}, OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.yml]'}, OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/bootstrap.properties]'}, MapPropertySource {name='springCloudDefaultProperties'},
CachedRandomPropertySource {name='cachedrandom'}]}, }
cloudClientHostName -- docker-cloud-app0-0.docker-cloud-eureka.docker-cloud.svc.cluster.local
instanceHostName -- 10.1.0.212
hostInfo -- docker-cloud-app0-0.docker-cloud-eureka.docker-cloud.svc.cluster.local
hostInfo -- 10.1.0.212
然后 我们再来 看一下容器上面的网络情况
可以看到 ping 服务的名称 是能够 ping 通的, ping 服务域名(服务名称 + 名称空间 + ".svc.cluster.local"(默认)) 也是能够 ping 通
但是 ping "docker-cloud-app0-0.docker-cloud-eureka.docker-cloud.svc.cluster.local" 就不行了, 这个名称 也有些奇怪?, APP0 上面获取的 hostname 怎么会和 eureka 有关系呢 ??
master:docker jerry$ docker exec -it k8s_docker-cloud-zuul_docker-cloud-zuul-0_docker-cloud_4d72d86c-1775-46c4-b657-465e127384a3_0 /bin/sh
/ # ping docker-cloud-app0
PING docker-cloud-app0 (10.1.0.216): 56 data bytes
64 bytes from 10.1.0.216: seq=0 ttl=64 time=0.090 ms
64 bytes from 10.1.0.216: seq=1 ttl=64 time=9.974 ms
^C
--- docker-cloud-app0 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.090/5.032/9.974 ms
/ # ping docker-cloud-app0.docker-cloud.svc.cluster.local
PING docker-cloud-app0.docker-cloud.svc.cluster.local (10.1.0.216): 56 data bytes
64 bytes from 10.1.0.216: seq=0 ttl=64 time=0.115 ms
64 bytes from 10.1.0.216: seq=1 ttl=64 time=0.958 ms
^C
--- docker-cloud-app0.docker-cloud.svc.cluster.local ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.115/0.536/0.958 ms
/ # ping docker-cloud-app0-0.docker-cloud-eureka.docker-cloud.svc.cluster.local
ping: bad address 'docker-cloud-app0-0.docker-cloud-eureka.docker-cloud.svc.cluster.local'
/ # ping docker-cloud-app0-0.docker-cloud-app0.docker-cloud.svc.cluster.local
ping: bad address 'docker-cloud-app0-0.docker-cloud-app0.docker-cloud.svc.cluster.local'
/ #
因为通过 inetUtils 获取到的 hostname 是一个很 messsy 的域名, zuul所在的服务器 解析不了这个域名
所以 回到最上面, 我们使用了一个 "eureka.instance.prefer-ip-address" 的配置
1. 从而 EurekaInstanceConfigBean.getHostName 返回的是 EurekaInstanceConfigBean 的 ipAddress
2. InstanceInfo 从 EurekaInstanceConfigBean 拿到的 hostName 是 ipAddress
3. app0 向 rureka 注册的 InstanceInfo 的 hostName 是 ipAddress
4. zuul 向 rureka 查询到的 app0 的 InstanceInfo 的 hostName 是 ipAddress
5. zuul 向 app0 发送请求是通过 ipAddress + 端口 进行发送
至此 本文的核心问题就解决了
1. InstanceInfo 的 instanceId 默认是怎么组成的 ?
取决于如下的几个配置, 这是默认的生成 instanceId 的方式, 也可以指定 eureka.instance.instance_id 覆盖默认的配置
2. eureka 管理界面的 instance 部分展示的什么
3. admin 管理界面的 url 展示的什么
这部分的页面数据绑定是在 js 中处理的, 这个 js 被混淆了, 但是 从结果上来看, 这里展示的应该是 serviceUrl
[
{
"name": "APP0",
"buildVersion": null,
"status": "DOWN",
"statusTimestamp": "2020-07-12T12:11:04.200Z",
"instances": [
{
"id": "dd4cc37f3958",
"version": 1,
"registration": {
"name": "APP0",
"managementUrl": "http://192.168.1.113:7901/actuator",
"healthUrl": "http://192.168.1.113:7901/actuator/health",
"serviceUrl": "http://192.168.1.113:7901",
"source": "discovery",
"metadata": {
"management.port": "7901"
}
},
"registered": true,
"statusInfo": {
"status": "DOWN",
"details": {
"path": "/actuator/health",
"error": "Not Found",
"message": "",
"status": 404,
"timestamp": "2020-07-12T12:11:04.133+0000"
}
},
"statusTimestamp": "2020-07-12T12:11:04.200Z",
"info": {},
"endpoints": [
{
"id": "health",
"url": "http://192.168.1.113:7901/actuator/health"
}
],
"buildVersion": null,
"tags": {}
}
]
},
{
"name": "ADMIN",
"buildVersion": null,
"status": "UP",
"statusTimestamp": "2020-07-12T12:11:33.723Z",
"instances": [
{
"id": "8b2f8d85ac7e",
"version": 2,
"registration": {
"name": "ADMIN",
"managementUrl": "http://192.168.1.113:8781/actuator",
"healthUrl": "http://192.168.1.113:8781/actuator/health",
"serviceUrl": "http://192.168.1.113:8781",
"source": "discovery",
"metadata": {
"management.port": "8781"
}
},
"registered": true,
"statusInfo": {
"status": "UP",
"details": {}
},
"statusTimestamp": "2020-07-12T12:11:33.723Z",
"info": {},
"endpoints": [
{
"id": "health",
"url": "http://192.168.1.113:8781/actuator/health"
},
{
"id": "info",
"url": "http://192.168.1.113:8781/actuator/info"
}
],
"buildVersion": null,
"tags": {}
}
]
}
]
serivceUri 的处理方式