目录
简介 SpringCloud是什么?
SpringCloud是一系列框架的有序集合。它以SpringBoot框架为基础,将各家公司的所造的值得信赖的轮子通过SpringBoot进行集成的一款微服务框架。
单体应用与分布式架构的区别
- 单体应用:所有模块部署在一起。
- 分布式应用
- 每个模块可以单独运行
- 模块可以按照业务进行划分,便于维护
- 项目开发时,每个项目组可以只负责自己的模块
- 模块划分后代码量减小
一、eureka
1、 简介
eureka组件,在SpringCloud中承担服务注册中心的角色。
eureka在使用中分为两个角色eureka-server和eureka-client,eureka-client又分为消费者和生产者
1.1 eureka功能
- 服务注册:在生产者服务启动时,eureka-client会向eureka-server注册,eureka-server会保存注册过的服务的信息
- 服务列表拉取:eureka-server在不存在缓存的情况下,eureka-client可以获取最新的注册表
#启用服务消费者从注册中心拉取服务列表的功能
eureka.client.fetch-registry=true
#设置服务消费者从注册中心拉取服务列表的间隔
eureka.client.registry-fetch-interval-seconds=30
- 状态同步:在eureka-server集群中,保证集群中各个节点的服务注册表里服务的状态一致。
- 服务的剔除:在server中会有一个线程来监控注册表里的服务,若90s没有进行一次心跳续约,则将该服务剔除。
服务续约任务的调用间隔时间,默认为30秒
eureka.instance.lease-renewal-interval-in-seconds=30
服务失效的时间,默认为90秒。
eureka.instance.lease-expiration-duration-in-seconds=90
- 心跳续约:eureka服务端默认30s钟向eureka服务端发送一条续约请求。
- 状态变更通知:eureka客户端在下线时,会通知eureka服务端,eureka服务端将该服务从注册表中删除。(eureka-client 在下线时不会自动发送下线请求)
//下线前手动调用
DiscoveryManager.getInstance().shutdownComponent();
1.2 eureka事件的监听
引用场景:在分布式环境中,有些服务特别的重要,例如 支付服务、网关、注册中心等,如果这些服务宕机,对整个微服务的架构影响特别大,为了及时告知开发人员或者运维人员,eureka提供了对应的监听事件。
- EurekaInstanceCanceledEvent:服务下线事件
- EurekaInstanceRegisteredEvent:服务注册事件
- EurekaInstanceRenewedEvent:服务续约事件
- EurekaRegistryAvailableEvent:注册可用事件
- EurekaServerStartedEvent:服务启动事件
package com.example.listener;
/**
* @BelongsProject: springcloudday01
* @BelongsPackage: com.example.listener
* @Author: mrmei
* @CreateTime: 2020-11-10 17:22
* @Description: eureka事件监听类
*/
@Component
public class EurekaListener {
/**
* eureka注册中心被注册服务下线监听事件
* @param event
*/
@EventListener
public void eurekaListenerEvent(EurekaInstanceCanceledEvent event){
System.out.println("有服务下线了。。。。。。。。。。。。。");
System.out.println(event.getAppName()+"服务下线了");
System.out.println(event.toString());
}
/**
* 服务注册监听事件
* @param event
*/
@EventListener
public void eurekaListenerEvent(EurekaInstanceRegisteredEvent event){
System.out.println("有服务来进行注册了。。。。。。。。。。。。。");
System.out.println(event.toString());
}
/**
* 服务续约监听事件
* @param event
*/
@EventListener
public void eurekaListenerEvent(EurekaInstanceRenewedEvent event){
System.out.println("有服务来续约了。。。。。。。。。。。。。");
System.out.println(event.getAppName()+"服务进行续约");
System.out.println(event.toString());
}
/**
* eureka服务可以注册其它服务事件
* @param event
*/
@EventListener
public void eurekaListenerEvent(EurekaRegistryAvailableEvent event){
System.out.println("服务可以注册其它服务了。。。。。。。。。。。。。");
System.out.println(event.toString());
}
/**
* eureka服务启动事件
* @param event
*/
@EventListener
public void eurekaListenerEvent(EurekaServerStartedEvent event){
System.out.println("eureka服务启动了。。。。。。。。。。。。。");
System.out.println(event.toString());
}
}
1.3 eureka分区
用户量比较大,用户地理位置分布较广,会布置多个机房,如果服务之间需要互相调用,希望同一个机房的服务可以优先调用,当同一个机房的服务不可用时,再去访问其它机房的服务,达到减少网络延迟的效果,提升用户的体验。eureka分区的功能借鉴了亚马逊aws的思想。
- region(区域):地理上的分区
#配置服务的region
eureka:
client:
region: wuhan
- zone(空间):机房
#配置所在region的zone
eureka:
instance:
metadata-map:
zone: wuhan-jifang1
client:
#配置每个region可用的zone
availability-zones:
wuhan: wuhan-jifang1,wuhan-jifang2
shanghai: shanghai-jifang1
1.4 eureka多级缓存机制
图片是借鉴别人的,如有雷同,是我copy的。。。。。
二、RestTemplate
RestTemplate时spring提供的访问rest服务的工具。
三种使用方式:
- 硬编码
RestTemplate restTemplate = new RestTemplate();
String response restTemplate.getForObject("http://localhost:2001/getUserServiceDetail", String.class);
- 使用SpringCloud负载均衡的功能,利用loadBalancerClient通过应用名获取url,然后使用restTemplate
ServiceInstance serviceInstance = loadBalancerClient.choose("USER");
String url = String.format("http://%s:%s", serviceInstance.getHost(), serviceInstance.getPort()) + "/getUserServiceDetail";
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject(url, String.class);
- 使用SpringCloud负载均衡的功能,在@Bean注解上添加@@LoadBalanced注解获得restTemplate对象
String response = restTemplate.getForObject("http://USER/getUserServiceDetail", String.class);
三、openFegin
openFeign为springcloud组件,实现分布式架构中各节点的同步调用。
使用步骤:
- maven仓库添加openFeign依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
- 在启动类上添加@EnableFeignClients注解
- 创建对应服务的openFeign的接口,接口里的抽象方法对应生产者服务中controller中的接口
//注解的name属性为服务的对应的spring.application.name
@FeignClient(name = "user")
@RequestMapping("user")
public interface UserFeign {
/**
* 注册的接口
* @param user
* @return
*/
@PostMapping("login")
ResEntity login(@RequestBody User user);
}
- 在消费者的controller中注入生产者的feign接口
//消费者服务的controller
@RestController
@RequestMapping("order")
public class OrderController {
@Autowired
private UserFeign userFeign;
@GetMapping("login")
public ResEntity login(){
User user = new User("root","root");
ResEntity login = userFeign.login(user);
return login;
}
}
//生产者服务的controller
@RestController
@RequestMapping("user")
public class UserController {
@Value("${spring.application.name}")
private String serviceName;
@Value("${server.port}")
private String port;
@PostMapping("login")
public ResEntity login(@RequestBody User user){
if(user==null){
return ResEntity.fail().msg("用户名或密码不能为空");
}else{
if("root".equals(user.getUserName()) && "root".equals(user.getPassword())){
return ResEntity.success(null);
}else{
return ResEntity.fail().msg("用户名或密码错误");
}
}
}
}
由以上代码可知,生产者调用user服务的feign接口,猜测openFeign的实现原理为jdk的动态代理。