Eureka服务注册与发现
Eureka基础知识
什么是服务治理?
Spring Cloud 封装了Netfix公司开发的Eureka模块来实现服务治理, 传统的RPC远程调用框架中,管理每个服务于服务之间的依赖关系无比复杂,管理比较复杂,所以需要服务治理管理,管理服务于服务之间的依赖关系。可以实现服务调用,负载均衡,容错等。实现服务发现与注册。
什么是服务注册与发现?
Eureka采用了CS的设计架构,Eureka Server作为服务注册功能的服务器,他是服务注册中心。而系统中其他微服务使用Eureka的客户端连接到Eureka Server并维持心跳连接。这样系统的维护人员可以通过Eureka Server来监控整个微服务是否正常运行。
在服务注册与发现中,有一个注册中心,当服务器启动的时候,会把当前自己服务器的信息 比如 服务地址通讯地址等以别名的方式注册到注册中心上,另一方面(消费者|服务提供者),以该别名的方法区注册中心上获取到实际的服务通讯地址,然后再实现本地RPC远程调用 框架设计核心思想: 在注册中心,因为使用注册中心管理每个服务与服务之间一个依赖关系(服务治理的概念)。在任何RPC远程框架中,都会有一个注册中心(存放服务地址相关信息(接口地址))
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PPD7iolI-1598955029471)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200815212013976.png)]
Eureka包含的2个组件 Eureka Server 和 Eureka Client
Eureka Server提供服务注册服务
各个微服务节点通过配置启动后,会在EureKaServer中进行注册,这样EureKaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直接观察到
EurekaClient通过注册中心进行访问
是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的,使用轮询负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接受到某个结点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)
单机Eureka构件步骤
idea生成EurekaServer端服务注册中心 类似物业公司
建Model cloud-eureka-server7001
改POM文件
<!-- eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
写Yml
server:
port: 7001
eureka:
instance:
hostname: localhost # eureka服务端实例名称
# hostname: eureka7001
client: # false 表示不向注册中心注册自己
register-with-eureka: false # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要检索服务
fetch-registry: false
service-url:
# 设置与Eureka Server 交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://localhost:7001/eureka
# defaultZone: http://eureka7002.com:7002/eureka 集群 相互守望
主启动类
@SpringBootApplication
@EnableEurekaServer // Server提供注册服务
public class EurekaMain7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaMain7001.class,args);
}
}
测试
http://localhost:7001/
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LSGzkvIE-1598954975050)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200815221517548.png)]
No application available没有服务被发现 因为没有注册服务进来
EurekaClient端cloud-provider-payment8001将服务注册进EurekaServer成为服务提供provider
服务提供者模板 建model 改pom 写yml 写主启动类 写业务类
目录结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ROh6AO0O-1598954975052)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200815223930294.png)]
pom文件
<dependencies>
<!-- 包含了sleuth zipkin 数据链路追踪-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-zipkin</artifactId>-->
<!-- </dependency>-->
<!-- 引入自己定义的api通用包, 可以使用Payment支付的Entity-->
<dependency>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- eureka client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<!--如果没写版本,从父层面找,找到了就直接用,全局统一-->
</dependency>
<!--mysql-connector-java-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--jdbc-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
写yml
server:
port: 8001
spring:
application:
name: cloud-payment-service
datasource:
# 当前数据源操作类型
type: com.alibaba.druid.pool.DruidDataSource
# mysql驱动类
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: admin
eureka:
client:
register-with-eureka: true # false 表示不向注册中心注册自己
fetch-registry: true # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要检索服务
service-url:
# 设置与Eureka Server 交互的地址查询服务和注册服务都需要依赖这个地址
# defaultZone: http://localhost:7001/eureka 单机版
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版
instance:
instance-id: payment8001
prefer-ip-address: true # 访问路径可以提示IP地址
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.atguigu.springcloud.entities # 所有Entity别名类在的包
主启动类上 + @EnableEurekaClient
EurekaCilent端cloud-consumer-order80将注册进EurekaServer成为服务消费者consumer
层级目录
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0hO8GP04-1598954975056)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200815225101913.png)]
改pom
<dependencies>
<!-- eureka-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- 引入自己定义的api通用包, 可以使用Payment支付的Entity-->
<dependency>
<groupId>com.atguigu.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
写yml
server:
port: 80 # 模拟不用加端口
spring:
application:
name: cloud-order-service
eureka:
client: # false 表示不向注册中心注册自己
register-with-eureka: true # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要检索服务
fetch-registry: true
service-url:
# 设置与Eureka Server 交互的地址查询服务和注册服务都需要依赖这个地址
# defaultZone: http://localhost:7001/eureka/ 单机版
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版
启动类
@SpringBootApplication
@EnableEurekaClient
public class OrderMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderMain80.class, args);
}
}
测试
- 必须先启动EurekaServer http://localhost:7001/ 2.微服务注册名配置说明
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F9Te3Vrm-1598954975058)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200815225422007.png)]
自我保护机制
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JBv8QDGG-1598954975059)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200815225443370.png)]
注意yml 语法格式
集群Eureka构件步骤
Eureka集群原理说明
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o0SakTLf-1598954975061)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200815225621790.png)]
微服务RPC远程服务调用最核心的是什么
高可用,注册中心不唯一 搭建Eureka注册中心集群实现 负载均衡+容错故障
Eureka集群环境搭建步骤
1.参考cloud-eureka-server7001 搭建cloud-eureka-server7002
2.修改pom
3.修改映射配置文件
找到C:\Windows\System32\drivers\etc
增加hosts文件内容 127.0.0.1 eureka7001.com 127.0.0.1 eureka7002.com
刷新hosts文件 ipconfig/flushdns
4.修改Yml文件
server:
port: 7001
eureka:
instance:
hostname: eureka7001.com # eureka服务端实例名称
client: # false 表示不向注册中心注册自己
register-with-eureka: false # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要检索服务
fetch-registry: false
service-url:
# 设置与Eureka Server 交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://eureka7002.com:7002/eureka
主启动类 @EnableEurekaServer
支付服务8001微服务发布到上面的2台Eureka集群配置汇总
server:
port: 8001
spring:
application:
name: cloud-payment-service
datasource:
# 当前数据源操作类型
type: com.alibaba.druid.pool.DruidDataSource
# mysql驱动类
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: admin
eureka:
client:
register-with-eureka: true # false 表示不向注册中心注册自己
fetch-registry: true # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要检索服务
service-url:
# 设置与Eureka Server 交互的地址查询服务和注册服务都需要依赖这个地址
# defaultZone: http://localhost:7001/eureka 单机版
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版
instance:
instance-id: payment8001
prefer-ip-address: true # 访问路径可以提示IP地址
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.atguigu.springcloud.entities # 所有Entity别名类在的包
订单服务80微服务发布到2台Eureka集群中
server:
port: 80 # 模拟不用加端口
spring:
application:
name: cloud-order-service
eureka:
client: # false 表示不向注册中心注册自己
register-with-eureka: true # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要检索服务
fetch-registry: true
service-url:
# 设置与Eureka Server 交互的地址查询服务和注册服务都需要依赖这个地址
# defaultZone: http://localhost:7001/eureka/ 单机版
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版
测试 ==>相互注册互相守望(先启动Server)
负载均衡
订单不能服务不能写死
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WckDk4JG-1598954975062)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200815231505655.png)]
controller类
@RestController
@Slf4j
public class OrderController {
// public static final String PAYMENT_URL = "http://localhost:8001"; 单机版
//服务名 一个服务名下可能有多个服务用端口号区别
public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";
@Resource
private RestTemplate restTemplate;
@GetMapping("/consumer/payment/create")
public CommonResult<Payment> create(Payment payment){
return restTemplate.postForObject(PAYMENT_URL + "/payment/create",payment,CommonResult.class);
}
@GetMapping("/consumer/payment/get/{id}")
public CommonResult<Payment> getPayment(@PathVariable("id") Long id){
return restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id,CommonResult.class);
}
}
实现负载均衡 增加一个配置类ApplicationContextConfig @LoadBalanced
实现默认轮询
@Configuration
public class ApplicationContextConfig {
@Bean
@LoadBalanced //做负载均衡 一个服务名下面多个端口负载均衡到服务上面 默认轮询
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
测试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u2ySpXoR-1598954975062)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200815232112946.png)]
actualtor微服务信息完善
主机名称: 服务名称修改
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ohx0LxL6-1598954975063)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200815233545783.png)]
修改cloud-provider-payment8001中yml
eureka:
client:
register-with-eureka: true # false 表示不向注册中心注册自己
fetch-registry: true # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要检索服务
service-url:
# 设置与Eureka Server 交互的地址查询服务和注册服务都需要依赖这个地址
# defaultZone: http://localhost:7001/eureka 单机版
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版
instance:
instance-id: payment8001 # 修改服务名称
prefer-ip-address: true # 访问路径可以提示IP地址
效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-45rTkjgF-1598954975064)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200815233903652.png)]
访问信息有IP地址提示信息
client:
instance:
prefer-ip-address: true # 访问路径可以提示IP地址
服务发现Discovery
对于注册eureka里面的微服务,可以通过服务发现来获取服务信息
修改提供服务的controller cloud-provider-payment8001
@RestController
@Slf4j
public class PaymentController {
@Resource
private PaymentService paymentService;
//区分相同服务名下 不同端口号提供的服务
@Value("${server.port}")
private String serverPort;
//服务发现 1********************************************
@Resource
private DiscoveryClient discoveryClient;
@PostMapping(value = "/payment/create")
public CommonResult create(@RequestBody Payment payment){
int result = paymentService.create(payment);
log.info("*****插入结果" + result);
if(result > 0){
return new CommonResult(200, "插入数据库成功,serverPort:"+serverPort,result);
}else{
return new CommonResult(444,"插入数据库失败",null);
}
}
@GetMapping(value = "/payment/get/{id}")
public CommonResult getPaymentById(@PathVariable("id") Long id){
Payment payment = paymentService.getPaymentById(id);
log.info("*****通过id查询" + payment +"用户结果");
if(payment != null){
return new CommonResult(200, "插入数据库成功serverPort:"+serverPort,payment);
}else{
return new CommonResult(444,"插入数据库失败",null);
}
}
// 2.*********************************************************
@GetMapping(value = "/payment/discovery")
public Object discovery(){
//服务名
List<String> services = discoveryClient.getServices();
for (String element : services) {
log.info("*****element"+element);
}
//实例
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;
}
}
效果图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ouQdLxfM-1598954975065)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200815234440558.png)]
Eureka自我保护
故障现象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4ayODyyG-1598954975066)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200815234532298.png)]
导致原因
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D4NhDKcA-1598954975067)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200815234652759.png)]
某个时刻微服务不可用了Eureka不会立刻清理,依旧会对服务信息进行保存CAP里面AP分枝
禁止自我保护
1.注册中心eurekaServer7001端
默认自动开启自我保护–>eureka.server.enable-self-preservation=true
使用eureka.server.enable-self-presevation=false可以禁用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EajiAeWY-1598954975068)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200815235052031.png)]
2.生产客户端eurekaClient8001
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pth7SBbA-1598954975069)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200815235304852.png)]
修改yml
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fJyytXBb-1598954975070)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200815235343296.png)]
图片上传有问题,可以私聊我要有图片版本