SpringCloud之Eureka服务注册与发现(eureka怎么注册服务)
本文已参与「新人创作礼」活动,一起开启掘金创作之路。
1、Eureka基础知识
1.1、什么是服务治理?
在传统的rpc
远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务与服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。
SpringCloud
封装了Netflix
公司开发的Eureka
模块来实现服务治理。
1.2、什么是服务注册与发现?
Eureka Server
作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用Eureka
的客户端连接到Eureka Server
并维持心跳连接。这样系统的维护人员就可以通过Eureka Server
来监控系统各个微服务是否正常运行。
服务注册与发现
在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器的信息,比如服务地址通讯地址等以别名方式注册到注册中心上。另一方(消费者、服务提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,然后再实现本地RPC
调用RPC
。远程调用框架核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系(服务治理概念)。在任何rpc
远程框架中,都会有一个注册中心(存放服务地址相关信息(接口地址))。
1.3、Eureka两大组件
Eureka
包含两个组件:Eureka Server
和Eureka Client
。
Eureka Server
:提供服务注册服务,各个微服务节点通过配置启动后,会在Eureka Server
中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。Eureka Client
:通过注册中心进行访问。是一个Java客户端,用于简化Eureka Server
的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server
发送心跳(默认周期为30秒)。如果Eureka Server
在多个心跳周期内没有接收到某个节点的心跳,Eureka Server
2、单机Eureka构建步骤
1. 建Module
名称为
cloud-eureka-server7001
2. 改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"> <parent> <artifactId>cloud02</artifactId> <groupId>com.xiao</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>cloud-eureka-server7001</artifactId> <dependencies> <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>com.xiao</groupId> <artifactId>cloud-api-commons</artifactId> <version>${project.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> </dependencies> </project> 复制代码
3. 改YML
server: port: 7001 eureka: instance: hostname: localhost #eureka服务端的实例名字 client: #表识不向注册中心注册自己 register-with-eureka: false #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务 fetch-registry: false service-url: #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ 复制代码
4. 主启动
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class EurekaMain7001 { public static void main(String[] args) { SpringApplication.run(EurekaMain7001.class,args); } } 复制代码
5. 测试结果
6. 包结构截图
3、支付模块入驻Eureka Server
1. 建Module
前面已经写过支付模块,直接拿来使用。名称为
cloud-provider-payment8001
。
2. 改POM
新增的内容
<!--新添加的依赖--> <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> 复制代码
3. 改YML
新增的内容
# 新添加的内容 eureka: client: # 标识自己要入驻 Eureka Server register-with-eureka: true fetchRegistry: true service-url: defaultZone: http://localhost:7001/eureka 复制代码
4. 主启动
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class PaymentMain8001 { public static void main(String[] args) { SpringApplication.run(PaymentMain8001.class,args); } } 复制代码
5. 测试结果
4、订单模块入驻Eureka Server
1. 建Module
前面已经写过订单模块,直接拿来使用。名称为
cloud-consumer-order80
。
2. 改POM
新增的内容
<!--新添加的依赖--> <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> 复制代码
3. 改YML
新增的内容
spring: application: name: cloud-order-service eureka: client: register-with-eureka: true fetchRegistry: true service-url: defaultZone: http://localhost:7001/eureka 复制代码
4. 主启动
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class OrderMain80 { public static void main(String[] args) { SpringApplication.run(OrderMain80.class,args); } } 复制代码
5. 测试结果
5、集群Eureka构建
5.1、Eureka工作原理
先启动
eureka
注册中心启动服务提供者
payment
支付服务支付服务启动后会把自身信息(比如服务地址以别名方式注册进
eureka
)消费者
order
服务在需要调用接口时,使用服务别名去注册中心获取实际的RPC
远程调用地址。消费者获得调用地址后,底层实际是利用
HttpClient
技术实现远程调用。消费者获得服务地址后会缓存在本地
jvm
中,默认每间隔30
秒更新一次服务调用地址。
5.2、Eureka集群原理说明
多个
Eureka Server
相互注册,互相守望,对外呈现一个Eureka
服务,从而实现高可用。
5.3、Eureka集群搭建步骤
1. 准备工作
在主机中修改对应的映射文件
添加的内容为
127.0.0.1 eureka7001.com 127.0.0.1 eureka7002.com 复制代码
2. 建Module
新建
Module
,名称为cloud-eureka-server7002
。
3. 改POM
cloud-eureka-server7002
的pom
文件不变,cloud-eureka-server7002
的pom
文件和cloud-eureka-server7001
的相同。
4. 改YML
cloud-eureka-server7001
的YML
文件
server: port: 7001 eureka: instance: hostname: eureka7001.com #eureka服务端的实例名字 client: register-with-eureka: false #表识不向注册中心注册自己 fetch-registry: false #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务 service-url: defaultZone: http://eureka7002.com:7002/eureka/ #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址 复制代码
cloud-eureka-server7002
的YML
文件
server: port: 7002 eureka: instance: hostname: eureka7002.com #eureka服务端的实例名字 client: register-with-eureka: false #表识不向注册中心注册自己 fetch-registry: false #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务 service-url: defaultZone: http://eureka7001.com:7001/eureka/ #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址 复制代码
5. 主启动类
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaServer public class EurekaMain7002 { public static void main(String[] args) { SpringApplication.run(EurekaMain7002.class,args); } } 复制代码
6. 测试结果
5.4、将支付模块入驻Eureka Server
将yml
文件修改为以下内容
server: port: 8001 spring: application: name: cloud-payment-service datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false username: root password: 123456 eureka: client: # 标识自己要入驻 Eureka Server register-with-eureka: true fetchRegistry: true #defaultZone: http://localhost:7001/eureka 单机版 service-url: defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版 mybatis: mapperLocations: classpath:mapper/*.xml type-aliases-package: com.xiao.cloud.entities 复制代码
5.5、将订单模块入驻Eureka Server
将yml
文件修改为以下内容
server: port: 80 spring: application: name: cloud-order-service eureka: client: register-with-eureka: true fetchRegistry: true service-url: #defaultZone: http://localhost:7001/eureka 单机版 defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版 复制代码
5.6、支付服务提供者的集群搭建步骤
1. 新建一个名称为新建cloud-provider-payment8002的 Module
其与
cloud-provider-payment8001
唯一不同的就是yml
文件的端口号为8002
。
2. 对支付模块的controller类进行修改
import com.xiao.cloud.entities.CommonResult; import com.xiao.cloud.entities.Payment; import com.xiao.cloud.service.PaymentService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @RestController @Slf4j public class PaymentController { @Autowired private PaymentService paymentService; @Value("${server.port}") private String ServerPort; @PostMapping("/payment/create") public CommonResult create(@RequestBody Payment payment){ int result = paymentService.create(payment); log.info("*****插入结果为:" + result); if(result > 0){ return new CommonResult(200,"插入数据库成功,端口号为:" + ServerPort,result); }else { return new CommonResult(444,"插入数据库失败",null); } } @GetMapping("/payment/get/{id}") public CommonResult getPaymentById(@PathVariable("id") Long id){ Payment payment = paymentService.getPaymentById(id); log.info("*****查询结果为:" + payment); if(payment != null){ return new CommonResult(200,"查询数据库成功,端口号为:" + ServerPort,payment); }else { return new CommonResult(444,"查询数据库失败,没有对应记录,id为:" + id,null); } } } 复制代码
当进行查询的时候将端口号也进行输出。
除上述修改以外,其他部分都和
cloud-provider-payment8001
相同。
3. 对订单模块的controller类中的URL进行修改
public static final String URL = "http://CLOUD-PAYMENT-SERVICE"; 复制代码
这里我们通过微服务的名称进行访问。
4. 对订单模块的配置类进行修改
import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class ApplicationContextConfig { @Bean @LoadBalanced public RestTemplate getRestTemplate(){ return new RestTemplate(); } } 复制代码
多添加了一个
@LoadBalanced
注解,从而实现负载均衡。
5. 测试结果
多次使用订单模块对支付模块进行调用,每次调用的端口号不尽相同。从而实现负载均衡。
5.7、actuator微服务信息完善
在cloud-provider-payment8001
和cloud-provider-payment8002
的yml
配置文件中加入以下内容
eureka: instance: instance-id: payment8001 # 如果是cloud-provider-payment8002,则此处为payment8002 prefer-ip-address: true 复制代码
对服务名称进行修改。
并且在访问的时候有
ip
显示。
5.8、服务发现Discovery配置
1. 用途
我们可以通过
Discovery
配置来获取服务的相关详细信息。
2. 在Controller类上新添的内容
@Autowired private DiscoveryClient discoveryClient; @GetMapping("/payment/discovery") public Object discovery(){ List<String> services = discoveryClient.getServices(); for (String service : services) { log.info("*****服务:" + service); } List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE"); for (ServiceInstance instance : instances) { log.info("****详细信息:" + instance.getServiceId() + "\t" + instance.getHost() + "\t" + instance.getPort() + "\t" + instance.getUri()); } return this.discoveryClient; } 复制代码
3. 在主启动类上新加的注解
@EnableDiscoveryClient 复制代码
4. 测试结果
5.9、Eureka自我保护
5.9.1、现象
5.9.2、自我保护机制的内容
一句话:某时刻某一个微服务不可用了,
Eureka
不会立刻清理,依旧会对该微服务的信息进行保存。属于
CAP
里面的AP
分支。自我保护机制是一种应对网络异常的安全保护措施。
5.9.3、为什么需要自我保护机制?
为了防止
EurekaClient
可以正常进行,但是与EurekaServer
网络不通情况下,EurekaServer
不会立刻将EurekaClient
服务剔除。
5.9.4、怎么进制自我保护?
在Eureka服务端yml文件中加入下述内容
eureka: server: enable-self-preservation: false eviction-interval-timer-in-ms: 2000 复制代码
在Eureka客户端yml文件加入下述内容
eureka: instance: # Eureka客户端向服务端发送心跳的时间间隔,单位为秒 lease-expiration-interval-in-seconds: 1 #Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒,超时将剔除服务 lease-expiration-duration-in-seconds: 2
作者:崇尚学技术的科班人
链接:https://juejin.cn/post/7048782131614449694