Eureka集群部署以及踩坑记录(实例始终unavailable)

一、Eureka集群部署 建议先严格按照步骤来部署,不然容易出问题,可能出现的问题会在下边说明
1、新建一个maven工程,pom示例如下

4.0.0 com.iceberg.eurekatest eureka-test 1.0-SNAPSHOTorg.springframework.boot spring-boot-starter-parent 2.1.6.RELEASE org.springframework.cloud spring-cloud-dependencies Greenwich.SR2 pom import org.springframework.cloud spring-cloud-starter-netflix-eureka-server org.springframework.boot spring-boot-maven-plugin

2、在Application类上加上注解,开启eureka
@EnableEurekaServer @SpringBootApplication public class EurekaApplication {public static void main(String[] args) { SpringApplication.run(EurekaApplication.class, args); } }

3、添加两个配置文件 application-peer1.yaml
spring: application: name: eureka-serverserver: port: 8001eureka: client: #是否将自己注册到Eureka Server register-with-eureka: true #是否从Eureka Server获取注册信息 fetch-registry: true serviceUrl: defaultZone: "http://peer2:8002/eureka/" instance: prefer-ip-address: false hostname: "peer1"

application-peer2.yaml
spring: application: name: eureka-serverserver: port: 8002eureka: client: #是否将自己注册到Eureka Server register-with-eureka: true #是否从Eureka Server获取注册信息 fetch-registry: true serviceUrl: defaultZone: "http://peer1:8001/eureka/" instance: prefer-ip-address: false hostname: "peer2"

【Eureka集群部署以及踩坑记录(实例始终unavailable)】4、在host中添加两条映射
127.0.0.1 peer1
127.0.0.1 peer2
5、在SpringBoot的启动参数上加上-Dspring.profiles.active=peer1,然后启动项目。
Eureka集群部署以及踩坑记录(实例始终unavailable)
文章图片

然后改成peer2,启动项目(共启动两个)
6、注意事项
(1)在启动第一个eureka的时候,会报下列异常
2019-07-29 15:49:57.335WARN 15416 --- [nfoReplicator-0] c.n.discovery.InstanceInfoReplicator: There was a problem with the instance info replicatorcom.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server at com.netflix.discovery.shared.transport.decorator.RetryableEurekaHttpClient.execute(RetryableEurekaHttpClient.java:112) ~[eureka-client-1.9.12.jar:1.9.12] at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.register(EurekaHttpClientDecorator.java:56) ~[eureka-client-1.9.12.jar:1.9.12] at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$1.execute(EurekaHttpClientDecorator.java:59) ~[eureka-client-1.9.12.jar:1.9.12] at com.netflix.discovery.shared.transport.decorator.SessionedEurekaHttpClient.execute(SessionedEurekaHttpClient.java:77) ~[eureka-client-1.9.12.jar:1.9.12] at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.register(EurekaHttpClientDecorator.java:56) ~[eureka-client-1.9.12.jar:1.9.12] at com.netflix.discovery.DiscoveryClient.register(DiscoveryClient.java:847) ~[eureka-client-1.9.12.jar:1.9.12] at com.netflix.discovery.InstanceInfoReplicator.run(InstanceInfoReplicator.java:121) ~[eureka-client-1.9.12.jar:1.9.12] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_212] at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266) [na:1.8.0_212] at java.util.concurrent.FutureTask.run(FutureTask.java) [na:1.8.0_212] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_212] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_212] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_212] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_212] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_212]

这个异常的意思是配置的eureka-server未找到(因为你还没启动),当第二个eureka-server启动好之后就正常了
(2)在eureka单机版配置中,register-with-eureka和fetch-registry 这两个选项是false,但是集群版的eureka是利用服务发现来实现的,所以需要改成true来向服务端注册自己并获取客户端信息
7、启动完成后,浏览器访问localhost:8001和localhost:8002
看到下图表示成功
Eureka集群部署以及踩坑记录(实例始终unavailable)
文章图片
Eureka集群部署以及踩坑记录(实例始终unavailable)
文章图片

二、集群部署时可能遇到的坑 1、不想加host,直接使用localhost
有些朋友可能不知道怎么改host或者干脆就是懒,直接用localhost取代之前的peer1和peer2,配置文件如下
application-peer1.yaml
spring: application: name: eureka-serverserver: port: 8001eureka: client: #是否将自己注册到Eureka Server register-with-eureka: true #是否从Eureka Server获取注册信息 fetch-registry: true serviceUrl: defaultZone: "http://localhost:8002/eureka/" instance: prefer-ip-address: false hostname: "localhost"

application-peer2.yaml
spring: application: name: eureka-serverserver: port: 8002eureka: client: #是否将自己注册到Eureka Server register-with-eureka: true #是否从Eureka Server获取注册信息 fetch-registry: true serviceUrl: defaultZone: "http://localhost:8001/eureka/" instance: prefer-ip-address: false hostname: "localhost"

这里分成两种情况:
(1)单机部署两个eureka,然后访问http://localhost:8001/ Eureka集群部署以及踩坑记录(实例始终unavailable)
文章图片

可以看到registered-replicas那一栏为空了,为什么会这样子?
我们来看下eureka的源码中PeerEurekaNodes的resolvePeerUrls()方法,这个方法的作用是从配置的serviceUrl中获取可用的地址
protected List resolvePeerUrls() { InstanceInfo myInfo = applicationInfoManager.getInfo(); String zone = InstanceInfo.getZone(clientConfig.getAvailabilityZones(clientConfig.getRegion()), myInfo); List replicaUrls = EndpointUtils .getDiscoveryServiceUrls(clientConfig, zone, new EndpointUtils.InstanceInfoBasedUrlRandomizer(myInfo)); int idx = 0; while (idx < replicaUrls.size()) { //这个地方就是罪魁祸首 if (isThisMyUrl(replicaUrls.get(idx))) { replicaUrls.remove(idx); } else { idx++; } } return replicaUrls; }public boolean isThisMyUrl(String url) { final String myUrlConfigured = serverConfig.getMyUrl(); if (myUrlConfigured != null) { return myUrlConfigured.equals(url); } return isInstanceURL(url, applicationInfoManager.getInfo()); }//判断url的hostnam和当前的hostname是否一致,如果一致则直接忽略 public boolean isInstanceURL(String url, InstanceInfo instance) { String hostName = hostFromUrl(url); String myInfoComparator = instance.getHostName(); if (clientConfig.getTransportConfig().applicationsResolverUseIp()) { myInfoComparator = instance.getIPAddr(); } return hostName != null && hostName.equals(myInfoComparator); }

通过isInstanceURL()方法,eureka会把hostname相同的url移除掉,而恰好我们配置的都是localhost,所以虽然你启动了两个eureka,但是它们不会把自己当成集群
(2)多机(或者多个虚拟机)部署
如果你把两个eureka启动在了不同的主机上,并配置了localhost,那你会一直看到com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server这个错误,因为它无法通过localhost找到另一个eureka
2、不使用域名,而是使用IP注册
eureka提供了一个选项,可以使eureka注册的地址不使用域名而是IP,配置项是eureka.instance.prefer-ip-address=true
(1)单机多网卡部署
这里解释一下什么是多网卡,我们安装vmware之后,它会给我们创建一些虚拟网卡,比如我这边它就给我创建了两个虚拟地址
Eureka集群部署以及踩坑记录(实例始终unavailable)
文章图片

多网卡的意思是你使用ipconfig命令,能看到多个IP地址(只是我自己的定义,不代表学术定义)
这种情况下eureka注册的IP跟你实际的IP可能是不同的,比如我刚才启动的eureka它的instance info显示的IP就是 192.168.157.1,这种情况下他注册的IP也是192.168.157.1,为了让他注册实际的IP,我们需要通过 eureka.instance.ip-address=10.60.44.136指定一下 Eureka集群部署以及踩坑记录(实例始终unavailable)
文章图片

然后问题就来了,假如你的peer1填的ip-address是10.60.44.136,peer2中的serviceUrl.defaultZone中的url也得是10.60.44.136,那peer2的ip-address用啥呢?也用10.60.44.136的话就会出现之前的问题,被eureka自己排除掉,所以你需要换一个IP且仍然表示本地的,比如127.0.0.1,配置文件如下所示: application-peer1.yaml
spring: application: name: eureka-serverserver: port: 8001eureka: client: #是否将自己注册到Eureka Server register-with-eureka: true #是否从Eureka Server获取注册信息 fetch-registry: true serviceUrl: defaultZone: "http://127.0.0.1:8002/eureka/" instance: prefer-ip-address: true hostname: "localhost" ip-address: "10.60.44.136"

application-peer2.yaml
spring: application: name: eureka-serverserver: port: 8002eureka: client: #是否将自己注册到Eureka Server register-with-eureka: true #是否从Eureka Server获取注册信息 fetch-registry: true serviceUrl: defaultZone: "http://10.60.44.136:8001/eureka/" instance: prefer-ip-address: true hostname: "localhost" ip-address: "127.0.0.1"

运行后的结果如下图
Eureka集群部署以及踩坑记录(实例始终unavailable)
文章图片
Eureka集群部署以及踩坑记录(实例始终unavailable)
文章图片

(2)单机单网卡部署
刚才是多网卡表示ipconfig有多个IP,单网卡就是只有一个IP啦,根据之前的描述,只有一个IP的情况下,你单机是无法部署集群成功的(会被忽略掉),所以就略过啦~
(3)多机部署
这个也没啥好说的了,ip指定为能互相访问的ip,只要正确配置就OK啦
三、总结 1、单机伪集群部署
方法一:每个eureka实例使用不同的域名映射到同一个IP
方法二:每个eureka实例使用不同的IP,但是这些IP要都表示本地
2、多机部署 同样可以使用域名或者IP,但是不要使用localhost,要保证实例之间可以通过域名或IP找到对方
以上就是我在部署eureka集群的一些总结,希望对你有帮助~
转载于:https://my.oschina.net/icebergxty/blog/3080748

    推荐阅读