Eureka注册中心
1. 认识Eureka
首先我们来解决第一问题,服务的管理。
问题分析
在刚才的案例中,user-service对外提供服务,需要对外暴露自己的地址。而consumer(调用者)需要记录服务提供者的地址。将来地址出现变更,还需要及时更新。这在服务较少的时候并不觉得有什么,但是在现在日益复杂的互联网环境,一个项目肯定会拆分出十几,甚至数十个微服务。此时如果还人为管理地址,不仅开发困难,将来测试、发布上线都会非常麻烦。
Eureka做什么?
Eureka负责管理、记录服务提供者的信息。服务调用者无需自己寻找服务,而是把自己的需求告诉Eureka,然后Eureka会把符合你需求的服务告诉你。
同时,服务提供方与Eureka之间通过“心跳”
机制进行监控,当某个服务提供方出现问题,Eureka自然会把它从服务列表中剔除。
这就实现了服务的自动注册、发现、状态监控。
2.原理图
负载均衡 Ribbon
但是实际环境中,我们往往会开启很多个user-service的集群。此时我们获取的服务列表中就会有多个,到底该访问哪一个呢?
一般这种情况下我们就需要编写负载均衡算法,在多个实例列表中进行选择。
Eureka已经帮我们集成了负载均衡组件 Ribbon,简单修改代码即可使用。
什么是Ribbon:
代码编写
-
服务注册中心
Eureka的服务端应用,提供服务注册和发现功能(Eureka Server 集群)
-
服务提供者
提供服务的应用,可以是SpringBoot应用,也可以是其它任意技术实现,只要对外提供的是Rest风格服务即可。(多个提高相同服务的集群)
-
服务消费者
消费应用从注册中心获取服务列表,从而得知每个服务方的信息,知道去哪里调用服务方。
1.编写EurekaServer
POM.XML:
<?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">
<parent>
<artifactId>spring-cloud-demo</artifactId>
<groupId>spring-cloud-demo</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka-server</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
启动类:
@SpringBootApplication
@EnableEurekaServer // 告知spring使用EurekaServer
public class EurekaServerApp {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApp.class);
}
}
配置yml:同一台机器的话实现即可多占用几个端口,多启几个服务实现集群
注意:idea中一个应用不能启动两次。先在edit configuration勾选Allow parallel run。
使用时我们需要启动一个, 再修改端口, 启动另一个
server:
port: 10000 # 端口
spring:
application:
name: eureka-server # 应用名称,会在Eureka中显示
eureka:
client:
service-url: # 配置其他Eureka服务的地址;
defaultZone: http://127.0.0.1:10001/eureka,http://127.0.0.1:10002/eureka
2.将user-service注册到Eureka
POM.XML
<?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">
<parent>
<artifactId>spring-cloud-parent</artifactId>
<groupId>spring-cloud-parent</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../spring-cloud-parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>user-service</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Eureka客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
</project>
application.yml配置。只有一台机器的话,多开几个端口就开启多个provider服务器,就可以实现某个功能集群(同服务器名称,下方应用名称)。
server:
port: 9000
spring:
# 应用名称
application:
name: user-service
eureka:
client:
service-url:
# EurekaServer地址:有几台注册几台
defaultZone: http://127.0.0.1:10000/eureka,http://127.0.0.1:10001/eureka,http://127.0.0.1:10002/eureka
instance:
prefer-ip-address: true # 当调用getHostname获取实例的hostname时,返回ip而不是host名称
ip-address: 127.0.0.1 # 指定自己的ip信息,不指定的话会自己寻找
启动类
@SpringBootApplication
@EnableDiscoveryClient // spring自动查找可用的注册中心(Eureka、zookeeper。。。)
public class UserServiceApp {
public static void main(String[] args) {
SpringApplication.run(UserServiceApp.class);
}
}
Controller层:自定义提供的服务
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("user/{id}")
public User queryById(@PathVariable("id") Integer id) {
return userService.findById(id);
}
}
3.消费者从Eureka获取服务
POM.XML
<?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">
<parent>
<artifactId>spring-cloud-parent</artifactId>
<groupId>spring-cloud-parent</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../spring-cloud-parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>user-consumer</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
//http客户端工具
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.14.2</version>
</dependency>
//Eureka客户端
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
</project>
启动类
@SpringBootApplication
@EnableDiscoveryClient //开启注册中心客户端
public class CustomerMain {
public static void main(String[] args) {
SpringApplication.run(CustomerMain.class);
}
//也可以在一个Configure类配置该bean
@Bean
@LoadBalanced //开启负载均衡
public RestTemplate restTemplate() {
// 使用okHttp客户端
return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
}
}
application.xml 配置
server:
port: 8080
spring:
application:
# 应用名称
name: user-consumer
eureka:
client:
service-url:
# EurekaServer地址:有几台注册几台
defaultZone: http://127.0.0.1:10000/eureka,http://127.0.0.1:10001/eureka
instance:
prefer-ip-address: true # 当其它服务获取地址时提供ip而不是hostname
ip-address: 127.0.0.1 # 指定自己的ip信息,不指定的话会自己寻找
user-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
Service层调用服务的方式:直接通过服务名称调用
@Service
public class UserCustomerService {
@Resource
private RestTemplate restTemplate;
//这里user-service是服务提供者的注册名称
//后面的/user/id 是调用服务提供方的provider调用数据的真正uri
//类似于 String url = "http://localhost:8081/user/" + id;
public User findById(Integer id) {
String url = "http://user-service/user/" + id;
return restTemplate.getForObject(url, User.class);
}
}
配置完毕,直接开启所有Eureka server和service provider ,使用客户端的路径url调用即可。
最后说下,这里server,provider,consumer的pom.xml都继承自一个父pom:通过建空项目,然后建一个maven module而来。该空项目只有一个用于继承的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>spring-cloud-parent</groupId>
<artifactId>spring-cloud-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>../user-service</module>
<module>../user-consumer</module>
<module>../eureka-server</module>
</modules>
<packaging>pom</packaging>
<!-- 继承 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.9.RELEASE</version>
</parent>
<properties>
</properties>
<dependencyManagement>
<dependencies>
<!-- 组合 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
未完待续。。。。。。。。。。。。。。。。。。先睡觉了