前言
对Eureka的基本介绍和使用
一、Eureka是什么?
微服务的其中一个特点是服务之间需要进行网络通信,服务器之间发起调用时调用服务得知道被调用服务的通信地址,试问当微服务数量成百上千之多,程序员该如何管理众多的服务通信地址,对于随时新增加的微服务和下线的微服务,又应该如何去动态添加和删除这些微服务的通信地址呢?所以手工管理服务的通信地址是一件遥不可及的事情,我们需要借助一个强大的工具帮我们实现这一功能 - Eureka,同类型的组件还有 zookeeper,consul等
二、Eureka的工作原理
1.服务注册
Eureka是一个服务注册与发现组件,简单说就是用来统一管理微服务的通信地址的组件,它包含了EurekaServer 服务端(也叫注册中心)和EurekaClient客户端两部分组成,EurekaServer是独立的服务,而EurekaClient需要集成到每个微服务中。
微服务(EurekaClient)在启动的时候会向EurekaServer提交自己的服务信息(通信地址如:服务名,ip,端口等),在 EurekaServer会形成一个微服务的通信地址列表存储起来。 — 这叫服务注册
2.服务发现
微服务(EurekaClient)会定期(RegistryFetchIntervalSeconds:默认30s)的从EurekaServer拉取一份微服务通信地址列表缓存到本地。当一个微服务在向另一个微服务发起调用的时候会根据目标服务的服务名找到其通信地址,然后基于HTTP协议向目标服务发起请求。—这叫服务发现
3.服务续约
另外,微服务(EurekaClient)采用定时(LeaseRenewalIntervalInSeconds:默认30s)发送“心跳”请求向EurekaServer发请求进行服务续约,其实就是定时向 EurekaServer发请求报告自己的健康状况,告诉EurekaServer自己还活着,不要把自己从服务地址清单中剔除掉,那么当微服务(EurekaClient)宕机未向EurekaServer续约,或者续约请求超时,注册中心机会从服务地址清单中剔除该续约失败的服务。
4.服务下线
微服务(EurekaClient)关闭服务前向注册中心发送下线请求,注册中心(EurekaServer)接受到下线请求负责将该服务实例从注册列表剔除
图解:
三、EurekaServer实战
文章采用“用户”,“订单”,“支付”等业务来演示整个SpringCloud的各个组件
1.项目结构搭建
项目结构如下,新建一个web项目springcloud,在项目中新建以下模块:
springcloud-parent //父项目
pom.xml //父项目的pom
springcloud-eureka-server-1010 //注册中心EurekaServer
springcloud-user-server-1020 //用户服务EurekaClient ,提供者
springcloud-order-server-1030 //订单服务EurekaClient ,消费者
2.父项目管理依赖
代码如下(示例):
<!--公共的一些配置-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<!--1.管理 SpringBoot的jar包-->
<!--SpringBoot-->
<parent>
<groupId> org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<!--2.管理 SpringCloud的jar包
-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!--3.这里是所有子项目都可以用的jar包-->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
3.搭建Eureka Server
3.1导入依赖
代码如下(示例):
<?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>springcloud-parent</artifactId>
<groupId>cn.itsource.springboot</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-eureka-server-1010</artifactId>
<name>springcloud-eureka-server-1010</name>
<dependencies>
<!--spring-cloud-starter-netflix-eureka-server -->
<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-web</artifactId>
</dependency>
</dependencies>
</project>
提示:spring-cloud-starter-netflix-eureka-server作为EurekaServer端的基础依赖,但同时这个包也把EurekaClient端的以来也导入进来了,spring-boot-starter-web作为web服务的基础依赖是不可缺少的。
3.2 配置启动类
代码如下(示例):
/
* 注册中心启动类
* @EnableEurekaServer : 开启EurekaServer服务端
*/
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication1010
{
public static void main( String[] args )
{
SpringApplication.run(EurekaServerApplication1010.class);
}
}
3.3 application.yml配置文件
代码如下(示例):
server:
port: 1010 #端口
eureka:
instance:
hostname: localhost #主机
client: #客户端配置
registerWithEureka: false #EurekaServer自己不要注册到EurekaServer自己 ,只有EurekaClient才注册
fetchRegistry: false #EurekaServer不要拉取服务的通信地址列表 ,只有EurekaClient才拉取地址列表
serviceUrl: #注册中心的注册地址
#http://${eureka.instance.hostname}:${server.port}/eureka/
defaultZone: http://localhost:1010/eureka/
server:
enable-self-preservation: false # 关闭eureka自动保护
- serviceUrl是服务注册地址,EurekaClient需要注册到EurekaServer就得跟上该地址。
- registerWithEureka=false :禁止自己向自己注册
- fetchRegistry=false : 禁止拉取服务注册列表
3.4 Eureka自我保护
默认情况下,当EurekaServer接收到服务续约的心跳失败比例在15分钟之内低于85%,EurekaServer会把这些服务保护起来,即不会把该服务从服务注册地址清单中剔除掉,但是在此种情况下有可能会出现服务下线,那么消费者就会拿到一个无效的服务,请求会失败,那我们需要对消费者服务做一些重试,或在熔断策略。
当EurekaServer开启自我保护时,监控主界面会出现红色警告信息,我们可以使用eureka.server.enable-self-preservation=false来关闭EurekaServer的保护机制,这样可以确保注册中心中不可用的实例被及时的剔除,但是不推荐
注意:上面 application.yml配置文件中已配置
4.EurekaClient实战-用户服务
4.1 导入依赖
代码如下(示例):
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
提示:不要忘记导入web的基础依赖 spring-boot-starter-web
4.2 配置启动类
代码如下(示例):
/
* 用户的启动类
* @EnableEurekaClient: 标记该应用是 Eureka客户端
*/
@SpringBootApplication
@EnableEurekaClient
public class UserServerApplication1020
{
public static void main( String[] args )
{
SpringApplication.run(UserServerApplication1020.class);
}
}
提示:@EnableEurekaClient可加可不加,默认配置
4.3 application.yml配置
代码如下(示例):
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1010/eureka/ #注册地址
instance:
instance-id: user-service0 #实例ID
spring:
application:
name: user-service # 客户端名字
server:
port: 1030 #端口号
提示:serviceUrl是EurekaServer注册中的地址,主机和端口都应该指向springcloud-eureka-server-1010工程,这里额外指定了服务的名字,和端口,这些信息都会被注册到EurekaServer
5 Eureka Client实战-订单服务
5.1 导入依赖
代码如下(示例):
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
5.2 配置启动类
代码如下(示例):
/
* 订单的启动类
* @EnableEurekaClient: 标记该应用是 Eureka客户端
*/
@SpringBootApplication
@EnableEurekaClient
public class OrderServerApplication1030
{
public static void main( String[] args )
{
SpringApplication.run(OrderServerApplication1030.class);
}
}
5.3 application.yml配置
代码如下(示例):
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1010/eureka/ #注册地址
instance:
instance-id: order-service #实例ID
spring:
application:
name: order-service # 客户端名字
server:
port: 1020 #端口号
四,RestTemplate服务通信
1.什么是RestTemplate?
微服务的通信协议主流的有RPC,Http,SpringCloud是基于Http Restful 风格 ,在Java中发起一个Http请求的方式很多,比如 Apache的HttpClient , OKHttp等等 。Spring为我们封装了一个基于Restful的使用非常简单的Http客户端工具 RestTemplate ,我们就用它来实订单服务和用户服务的通信。需要注意的是,RestTmplate本身不具备服务发现和负载均衡器的功能,我们本章的案例只是演示在订单服务中使用RestTemplate基于ip和端口的方式向用户服务发起调用,即:不走注册中心,不使用服务发现方式。
2. 如何实现服务通信
2.1 流程说明
用订单服务springcloud-order-server-1030,和用户服务springcloud-user-server-1020 ,这两个服务来演示微服务的通信,他们的调用关系应该是:浏览器 -> 订单服务 -> 用户服务,如下图:
这里订单服务通过RestTemplate向用户服务发起调用,目的是要获取到用户服务返回的User对象,最终是需要浏览器获取到User。
2.2 解决方案
用户服务需要提供User对象,我们需要为其编写Controller接口,编写相关方法返回User,订单服务需要从用户服务获取到User对象,而浏览器需要访问订单服务获取到User对象,所以订单服务也需要编写Controller接口供浏览器来调用。
我们发现不管是用户服务还是订单服务都需要用到User对象,那么是不是在用户服务和订单服务都需要创建User的模型?当然没必要,公共的东西就是要抽取,所以我们会把User对象封装在一个公共的模块 springcloud-user-common中然后让用户服务和订单服务都去依赖这个模块。
3. 项目实战
3.1 搭建公共模块
项目中新建一个工程模块 springcloud-user-common
3.2 在springcloud-user-common中创建User对象,如下
代码如下(示例):
public class User {
private Long id;
private String username;
private String desc;
public User() {
}
public User(Long id, String username, String desc) {
this.id = id;
this.username = username;
this.desc = desc;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
3.2 在用户和订单服务模块导入工程模块 - User模块
代码如下(示例):
<dependency>
<groupId>cn.itsource.springboot</groupId>
<artifactId>springcloud-user-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
3.3 用户模块controller接口中
代码如下(示例):
@RestController
public class UserConroller {
@Value("${server.port}") // 获取yml中配置的端口号,区分同一个业务的不同服务
private Long port;
@GetMapping("/user/{id}")
public User getUserById(@PathVariable("id") Long id){
return new User(id,"张飞","端口号:"+port);
}
}
3.4 在订单服务controller中获取User
在订单服务中需要使用RestTemplate调用用户服务,我们需要把RestTmplate配置成Bean方便使用(当然也可以不创建Bean,用的时候直接new对象也可以,修改工程springcloud-order-server在主配置类配置RestTemplate如下:
//配置一个RestTemplate ,Spring封装的一个机遇Restful风格的http客户端 工具
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
创建controller,通过RestTemplate调用用户服务,代码如下:
@RestController
public class OrderController {
@Autowired
private RestTemplate template;
@GetMapping("/order/{id}")
public User getUser(@PathVariable("id") Long id) {
// USERSERVICE是服务名
User user = template.getForObject("http://USERSERVICE/user/" + id, User.class);
return user;
}
}
3.5 测试服务通信
依次启动Eureka Server注册中心(不启动也行) , 用户服务 ,订单服务 , 浏览器访问订单服务:http://localhost:1030/order/1
总结
以上就是对Eureka的基本介绍和基本使用,同时对RestTemplate服务通信的学习