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

一、Eureka集群部署

建议先严格按照步骤来部署,不然容易出问题,可能出现的问题会在下边说明

1、新建一个maven工程,pom示例如下



    4.0.0
    com.iceberg.eurekatest
    eureka-test
    1.0-SNAPSHOT

    
        org.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-server

server:
  port: 8001

eureka:
  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-server

server:
  port: 8002

eureka:
  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"

4、在host中添加两条映射
127.0.0.1 peer1
127.0.0.1 peer2

5、在SpringBoot的启动参数上加上-Dspring.profiles.active=peer1,然后启动项目。
Eureka集群部署以及踩坑记录(实例始终unavailable)_第1张图片
然后改成peer2,启动项目(共启动两个)

6、注意事项
(1)在启动第一个eureka的时候,会报下列异常

2019-07-29 15:49:57.335  WARN 15416 --- [nfoReplicator-0] c.n.discovery.InstanceInfoReplicator     : There was a problem with the instance info replicator

com.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)_第2张图片Eureka集群部署以及踩坑记录(实例始终unavailable)_第3张图片

二、集群部署时可能遇到的坑

1、不想加host,直接使用localhost
有些朋友可能不知道怎么改host或者干脆就是懒,直接用localhost取代之前的peer1和peer2,配置文件如下
application-peer1.yaml

spring:
  application:
    name: eureka-server

server:
  port: 8001

eureka:
  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-server

server:
  port: 8002

eureka:
  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)_第4张图片
可以看到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)_第5张图片
多网卡的意思是你使用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)_第6张图片
然后问题就来了,假如你的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-server

server:
  port: 8001

eureka:
  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-server

server:
  port: 8002

eureka:
  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)_第7张图片Eureka集群部署以及踩坑记录(实例始终unavailable)_第8张图片

(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

你可能感兴趣的:(Eureka集群部署以及踩坑记录(实例始终unavailable))