上一篇博客中,直接通过Http进行调用服务存在着许多的问题。user-service需要暴露自己的地址,而user-consume需要记录服务提供者的地址,未来地址一旦发生变更,就需要及时更新。但是如果在服务非常多的情况下,会使得开发和维护变得非常困难。
Eureka的存在就能很好的解决这个问题。服务将自己的服务统一注册到Eureka上,相当于一个注册中心。消费者直接往Eureka订阅服务,并调用。
下面开始改进上篇博客的直接调用的情况
(一) Eureka Server
首先,用Spring boot初始化工具选择依赖

完整依赖如下图
<?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.leyou.demo</groupId>
<artifactId>eureka-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>eureka-demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.M1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
主类添加@EnableEurekaServer注解
@SpringBootApplication
@EnableEurekaServer
public class EurekaDemoApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaDemoApplication.class, args);
}
}
yml配置文件添加如下
server:
port: 10086 //当前应用端口号
spring:
application:
name: eureka-server //应用名称
eureka:
client:
register-with-eureka: false //表示不向注册中心注册自己
fetch-registry: false //表示不需要检索服务
service-url:
defaultZone: http://127.0.0.1:${server.port}/eureka/ //注册中心的url
启动服务,并访问http://localhost:10086/ 可以看到下图所示的Eureka信息面板。
下图中Instances currently registered with Eureka表示当前注册到Eureka的实例

(二)user-service-demo
同样的引入依赖
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
启动类加入注解@EnableDiscoveryClient
@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceDemoApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceDemoApplication.class, args);
}
}
yml配置文件 配置注册中心地址
eureka:
client:
service-url: # EurekaServer地址
defaultZone: http://127.0.0.1:10086/eureka/
启动user-service服务,查看eureka的信息面板

(三)user-consume-demo
同user-service-demo一样引入相同的依赖,加入注解,配置也相同
service层的方法中拿到DiscoveryClient类
@Service
public class UserService {
// @Autowired
// private UserDao userDao;
//
// public List<User> queryUserByIds(List<Long> ids){
// List<User> users = new ArrayList<>();
// for (Long id : ids) {
// User user = this.userDao.queryUserById(id);
// users.add(user);
// }
// return users;
// }
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
public List<User> queryUserByIds(List<Long> ids){
List<User> users = new ArrayList<>();
//根据服务的名称,获取服务的实例
List<ServiceInstance> instances = discoveryClient.getInstances("user-service");
ServiceInstance instance = instances.get(0);//由于只有一个服务治取一个,此处可以做负载均衡
//获取ip和端口信息
String baseUrl = "http://"+instance.getHost()+":"+instance.getPort()+"/user/";
ids.forEach(id->{
// 测试多次查询,
System.out.print(baseUrl);
users.add(this.restTemplate.getForObject(baseUrl + id, User.class));
// 每次间隔500毫秒
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
return users;
}
}
启动服务并访问,实例成功创建,并调用成功


(三)集群配置
假设另一台eureka-server的端口号是10087,则修改eureka-server的yml配置
server:
port: 10086
spring:
application:
name: eureka-server
eureka:
client:
service-url: #配置其他eureka服务的地址,而不是自己
#defaultZone: http://127.0.0.1:${server.port}/eureka/
defaultZone: http://127.0.0.1:10087/eureka/
其中删掉了原来的register-with-eureka=false和fetch-registry=false两个配置。其默认值为true,就会把自己给注册到注册中心
将eureka-server复制一份 有如下配置
server:
port: 10087
spring:
application:
name: eureka-server
eureka:
client:
service-url: #配置其他eureka服务的地址,而不是自己
#defaultZone: http://127.0.0.1:${server.port}/eureka/
defaultZone: http://127.0.0.1:10086/eureka/
此外,需要在user-service 和user-consumer配置两个注册中心的地址
eureka:
client:
service-url: # EurekaServer地址
defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eureka/
启动并访问localhost:10086

(四)负载均衡Ribbon
eureka中已经存在Ribbon,所以在eureka-consume加上@LoadBalanced注解
@SpringBootApplication
@EnableDiscoveryClient
public class UserConsumerDemoApplication {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
// 这次我们使用了OkHttp客户端,只需要注入工厂即可
return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
}
public static void main(String[] args) {
SpringApplication.run(UserConsumerDemoApplication.class, args);
}
}
user-consume的service方法直接写实例名称
public List<User> queryUserBiIds(List<Long> ids){
List<User> users = new ArrayList<>();
//根据服务的名称,获取服务的实例
//List<ServiceInstance> instances = discoveryClient.getInstances("user-service");
//ServiceInstance instance = instances.get(0);
//获取ip和端口信息
//String baseUrl = "http://"+instance.getHost()+":"+instance.getPort()+"/user/";
//地址直接写服务名称
String baseUrl = "http://user-service/user/";
ids.forEach(id->{
// 我们测试多次查询,
System.out.print(baseUrl);
users.add(this.restTemplate.getForObject(baseUrl + id, User.class));
// 每次间隔500毫秒
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
return users;
}
结果如下:

网友评论