一、Eureka集群部署
建议先严格按照步骤来部署,不然容易出问题,可能出现的问题会在下边说明
1、新建一个maven工程,pom示例如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.iceberg.eurekatest</groupId>
<artifactId>eureka-test</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- spring -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
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,然后启动项目。
然后改成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
看到下图表示成功
二、集群部署时可能遇到的坑
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/
可以看到registered-replicas那一栏为空了,为什么会这样子?
我们来看下eureka的源码中PeerEurekaNodes的resolvePeerUrls()方法,这个方法的作用是从配置的serviceUrl中获取可用的地址
protected List<String> resolvePeerUrls() {
InstanceInfo myInfo = applicationInfoManager.getInfo();
String zone = InstanceInfo.getZone(clientConfig.getAvailabilityZones(clientConfig.getRegion()), myInfo);
List<String> 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之后,它会给我们创建一些虚拟网卡,比如我这边它就给我创建了两个虚拟地址
多网卡的意思是你使用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指定一下
然后问题就来了,假如你的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"
运行后的结果如下图
(2)单机单网卡部署
刚才是多网卡表示ipconfig有多个IP,单网卡就是只有一个IP啦,根据之前的描述,只有一个IP的情况下,你单机是无法部署集群成功的(会被忽略掉),所以就略过啦~
(3)多机部署
这个也没啥好说的了,ip指定为能互相访问的ip,只要正确配置就OK啦
三、总结
1、单机伪集群部署
方法一:每个eureka实例使用不同的域名映射到同一个IP
方法二:每个eureka实例使用不同的IP,但是这些IP要都表示本地
2、多机部署 同样可以使用域名或者IP,但是不要使用localhost,要保证实例之间可以通过域名或IP找到对方
以上就是我在部署eureka集群的一些总结,希望对你有帮助~