高可用的Eureka Server集群
在分布式应用开发中需要部署高可用的Eureka集群来保证微服务的正常调用,Eureka Server通过运行多个实例且彼此相互注册的方式实现高可用部署。Eureka Server实例彼此增量地同步信息,确保所有节点的数据一致。
双节点的Eureka Server集群
上一篇文章介绍了单节点的Eureka集群,在此基础上创建一个双节点的Eureka Server集群工程micro-service-discovery-eureka-ha。
Eureka微服务注册与发现
在父pom中增加如下的module:
<module>micro-service-discovery-eureka-ha</module>
micro-service-discovery-eureka-ha的工程可以通过复制micro-service-discovery-eureka工程来创建,接下来修改一些配置即可。
配置系统的host
127.0.0.1 peer1 peer2
micro-service-discovery-eureka-ha的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.test.cloud</groupId>
<artifactId>micro-service-discovery-eureka-ha</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>com.fanfan.cloud</groupId>
<artifactId>micro-service-spring-cloud-study</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
</dependencies>
<!-- 引入spring cloud的依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Edgware.SR6</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>discovery-eureka-ha</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
micro-service-discovery-eureka-ha的application.yml文件:
spring:
application:
name: eureka-ha
# 使用---连接符
---
spring:
profiles: peer1
server:
port: 8762
# 指定该Eureka实例的端口
eureka:
instance:
# 主机名
hostname: peer1
prefer-ip-address: true
instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
client:
serviceUrl:
defaultZone: http://peer2:8763/eureka/
---
spring:
profiles: peer2
server:
port: 8763
eureka:
instance:
hostname: peer2
prefer-ip-address: true
instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
client:
serviceUrl:
defaultZone: http://peer1:8762/eureka/
micro-service-discovery-eureka-ha的启动类:
/**
* EurekaServer
*/
@SpringBootApplication
@EnableEurekaServer
public class EurekaHAApplication{
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
高可用的Eureka Server集群配置好了。
集群启动成功后可以看到如下的画面:
接下来就是将应用注册到Eureka Server上了。
服务生产者
服务生产者还是使用micro-service-provider-user,只需要修改application.yml即可,将原来的单个服务注册中心的配置注释掉,改成多个服务注册中心配置。
eureka:
client:
serviceUrl:
# 单个服务注册中心
#defaultZone: http://localhost:8761/eureka/
# 多个服务注册中心
defaultZone: http://peer1:8762/eureka/,http://peer2:8763/eureka/
instance:
prefer-ip-address: true
# 自定义Eureka的Instance ID
instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
# 配置虚拟主机名
virtual-host-name: micro-service-provider
appname: USER-HAHA
服务的消费者
服务的消费者也是同样的修改application.yml为多服务注册中心即可。
eureka:
client:
serviceUrl:
#defaultZone: http://localhost:8761/eureka/
defaultZone: http://peer1:8762/eureka/,http://peer2:8763/eureka/
instance:
prefer-ip-address: true
instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
appname: MOVIE-HAHA
完成配置后,启动生产者和消费者,完成接口调用测试即可。
以上生产者和消费者的application.yml文件中如果配置了appname的话,则如下图所示,可以看到展示的名字为配置的名字,注意这个配置是大写。
Eureka Server添加用户认证
以上配置的eureka server是允许匿名访问的,下面构建一个需要登录才能访问的micro-service-discovery-eureka-authenticating工程。
在父pom中添加如下module:
<module>micro-service-discovery-eureka-authenticating</module>
创建service-discovery-eureka-authenticating工程
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.test.cloud</groupId>
<artifactId>micro-service-discovery-eureka-authenticating</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>com.fanfan.cloud</groupId>
<artifactId>micro-service-spring-cloud-study</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
<!-- 引入spring cloud的依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Edgware.SR6</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>authenticating-eureka</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.yml文件
server:
port: 8764 # 指定该Eureka实例的端口
eureka:
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://localhost:8764/eureka/
security:
basic:
enabled: true # 开启基于HTTP basic的认证
user:
name: root # 配置登录账户
password: 123456 # 配置登录密码
启动类:
/**
* EurekaServer
*/
@SpringBootApplication
@EnableEurekaServer
public class EurekaAuthApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaAuthApplication.class, args);
}
}
接下来将微服务注册到需要认证的Eureka Server上。
服务生产者
application.yml文件
使用用户名和密码的方式注册到eureka server。
eureka:
client:
serviceUrl:
# 单个服务注册中心
#defaultZone: http://localhost:8761/eureka/
# 多个服务注册中心
# defaultZone: http://peer1:8762/eureka/,http://peer2:8763/eureka/
# 认证
defaultZone: http://root:123456@localhost:8764/eureka/
instance:
prefer-ip-address: true
# 自定义Eureka的Instance ID
instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
# 配置虚拟主机名
virtual-host-name: micro-service-provider
appname: USER-HAHA
服务消费者
application.yml文件
eureka:
client:
serviceUrl:
#defaultZone: http://localhost:8761/eureka/
#defaultZone: http://peer1:8762/eureka/,http://peer2:8763/eureka/
defaultZone: http://root:123456@localhost:8764/eureka/
instance:
prefer-ip-address: true
instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
appname: MOVIE-HAHA
启动service-discovery-eureka-authenticating、生产者以及消费者,访问http://localhost:8764/需要输入用户名和密码,然后点击登录可以看到服务注册情况了。
Eureka元数据
Eureka的元数据有两种,标准元数据和自定义元数据。自定义元数据使用eureka.instance.metadata-map配置。
服务生产者
复制micro-service-provider-user,将名字修改为micro-service-provider-user-my-metadata,在application.yml文件中配置metadata-map信息如下:
server:
port: 8011
spring:
jpa:
generate-ddl: false
show-sql: true
hibernate:
ddl-auto: none
datasource: # 指定数据源
platform: h2 # 指定数据源类型
schema: classpath:schema.sql # 指定h2数据库的建表脚本
data: classpath:data.sql # 指定h2数据库的数据脚本
application:
name: provider #名称要小写
logging:
level:
root: INFO # 配置日志级别,让hibernate打印执行的SQL
org.hibernate: INFO
org.hibernate.type.descriptor.sql.BasicBinder: TRACE
org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
com.spring.cloud.test: DEBUG
eureka:
client:
serviceUrl:
# 单个服务注册中心
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
# 自定义Eureka的Instance ID
instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
virtual-host-name: micro-service-provider # 可不配置
metadata-map:
# 自定义元数据 key/value格式
year: 2018
服务消费者
复制micro-service-consumer-movie并命名为:micro-service-consumer-movie-understanding-metadata,注入DiscoveryClient来获取服务生产者的实例,注意这里的实例用的依旧是虚拟主机名,若生产者不配置虚拟主机名virtual-host-name: microservice-provider,则使用应用名provider 。
@RestController
public class MovieController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/movie/{id}")
public User findById(@PathVariable Long id) {
return restTemplate.getForObject("http://localhost:8010/user/simple/" + id, User.class);
}
@GetMapping("/user-instance")
public List<ServiceInstance> showInfo() {
return this.discoveryClient.getInstances("micro-service-provider");
}
}
关闭上文其他的服务,启动单点的Eureka Server,以及metadata的生产者和消费者,调用/user-instance接口如下: