spring cloud是什么?
spring cloud 是一个工具集
集成多个工具,来解决微服务中的各种问题
微服务全家桶
spring cloud 不是什么?
spring cloud 不是一个解决单一问题的工具
远程调用 - RestTemplate
负载均衡 - Ribbon
重试 - Ribbon
降级、熔断、限流 - Hystrix
监控 - Hystrix Dashboard、Turbine、Sleuth、Zipkin
配置中心 - Config server
…
1.eureka
注册中心:服务提供者启动时,向eureka一次次反复注册,直到注册成功为止
拉取注册表:服务发现者每30秒拉取一次注册表(刷新注册表)
心跳:服务提供者每30秒发送一次心跳数据
eureka连续3次收不到一个服务的心跳,会删除这个服务
自我保护模式
特殊情况
如果由于网络不稳定或中断,15分钟内,85%以上服务器出现心跳异常,就会自动进入保护模式。
在保护模式下,所有服务都不删除。
网络恢复后,可以自动退出保护模式,恢复正常
开发期间很容易达到保护模式的条件,会影响测试,在开发期间可以关闭保护模式
eureka 和 zookeeper 区别:
eureka:
强调AP(可用性)
集群结构:对等结构
zookeeper:
强调CP(一致性)
集群结构:主从结构
添加 eureka server 依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
yml配置
spring:
application:
name: eureka-server
server:
port: 2001
eureka:
server:
enable-self-preservation: false
instance:
hostname: eureka1
client:
register-with-eureka: false
fetch-registry: false
eureka 集群服务器之间,通过 hostname 来区分
eureka.server.enable-self-preservation
eureka 的自我保护状态:心跳失败的比例,在15分钟内是否超过85%,如果出现了超过的情况,Eureka Server会将当前的实例注册信息保护起来,同时提示一个警告,一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据。也就是不会注销任何微服务
eureka.client.register-with-eureka=false
不向自身注册
eureka.client.fetch-registry=false
不从自身拉取注册信息
eureka.instance.lease-expiration-duration-in-seconds
最后一次心跳后,间隔多久认定微服务不可用,默认90
主程序添加 @EnableEurekaServer
@EnableEurekaServer
@SpringBootApplication
public class Sp05EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(Sp05EurekaApplication.class, args);
}
}
修改host文件,添加 eureka 域名映射
127.0.0.1 eureka1
127.0.0.1 eureka2
service provider 服务提供者
修改 item-service、user-service、order-service,主程序添加 @EnableDiscoveryClient 注解,把微服务注册到 eureka 服务器
pom.xml 添加eureka依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
application.yml 添加eureka注册配置
eureka:
client:
service-url:
defaultZone: http://eureka1:2001/eureka
defaultZone,默认位置,可以修改为具体地理位置,比如:beiJing, shangHai, shenZhen 等,表示 eureka 服务器的部署位置, 需要云服务器提供
eureka.instance.lease-renewal-interval-in-seconds
心跳间隔时间,默认 30 秒
eureka.client.registry-fetch-interval-seconds
拉取注册信息间隔时间,默认 30 秒
访问http://eureka1:2001
更多配置见https://blog.csdn.net/weixin_38305440/article/details/102775484
2.RestTemplate
springboot 提供的远程调用工具
类似于 HttpClient,可以发送 http 请求,并处理响应。RestTemplate简化了Rest API调用,只需要使用它的一个方法,就可以完成请求、响应、Json转换
方法:
getForObject(url, 转换的类型.class, 提交的参数)
postForObject(url, 协议体数据, 转换的类型.class)
RestTemplate 和 Dubbo 远程调用的区别:
RestTemplate:http调用 效率低
Dubbo:RPC调用,Java的序列化 效率高
3.Ribbon 负载均衡和重试
添加 ribbon 起步依赖(可选)
eureka 依赖中已经包含了 ribbon
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
@LoadBalanced 负载均衡注解,会对 RestTemplate 实例进行封装,创建动态代理对象,并切入(AOP)负载均衡代码,把请求分发到集群中的服务器
@LoadBalanced //负载均衡注解
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
@Autowired
private RestTemplate rt;
@GetMapping("/item-service/{orderId}")
public JsonResult<List<Item>> getItems(@PathVariable String orderId) {
//这里服务器路径用 service-id 代替,ribbon 会向服务的多台集群服务器分发请求
return rt.getForObject("http://item-service/{1}", JsonResult.class, orderId);
}
pom.xml 添加 spring-retry 重试依赖
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
application.yml 配置 ribbon 重试
spring:
application:
name: ribbon
server:
port: 3001
eureka:
client:
service-url:
defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka
ribbon:
MaxAutoRetriesNextServer: 2
MaxAutoRetries: 1
OkToRetryOnAllOperations: true
OkToRetryOnAllOperations=true
默认只对GET请求重试, 当设置为true时, 对POST等所有类型请求都重试
MaxAutoRetriesNextServer更换实例的次数
MaxAutoRetries当前实例重试次数,尝试失败会更换下一个实例
主程序设置 RestTemplate 的请求工厂的超时属性
@LoadBalanced
@Bean
public RestTemplate getRestTemplate() {
SimpleClientHttpRequestFactory f = new SimpleClientHttpRequestFactory();
f.setConnectTimeout(1000);
f.setReadTimeout(1000);
return new RestTemplate(f);
//RestTemplate 中默认的 Factory 实例中,两个超时属性默认是 -1,
//未启用超时,也不会触发重试
//return new RestTemplate();
}
item-service 的 ItemController 添加延迟代码,以便测试 ribbon 的重试机制
Thread.sleep()…
4.Hystrix 断路器
添加 hystrix 起步依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
主程序添加 @EnableCircuitBreaker 启用 hystrix 断路器,可以使用 @SpringCloudApplication 注解代替三个注解
//@EnableCircuitBreaker
//@EnableDiscoveryClient
//@SpringBootApplication
@SpringCloudApplication
Controller 中添加降级方法
为每个方法添加降级方法,例如 getItems() 添加降级方法 getItemsFB()
添加 @HystrixCommand 注解,指定降级方法名
@GetMapping("/item-service/{orderId}")
@HystrixCommand(fallbackMethod = "getItemsFB") //指定降级方法的方法名
public JsonResult<List<Item>> getItems(@PathVariable String orderId) {
return rt.getForObject("http://item-service/{1}", JsonResult.class, orderId);
}
//降级方法的参数和返回值,需要和原始方法一致,方法名任意
public JsonResult<List<Item>> getItemsFB(String orderId) {
return JsonResult.err("获取订单商品列表失败");
}
hystrix 超时设置
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds
hystrix等待超时后, 会执行降级代码, 快速向客户端返回降级结果, 默认超时时间是1000毫秒
为了测试 hystrix 降级,我们把 hystrix 等待超时设置得非常小(500毫秒)
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 500
5.hystrix dashboard 断路器仪表盘
actuator 是 spring boot 提供的服务监控工具,提供了各种监控信息的监控端点
management.endpoints.web.exposure.include 配置选项,
可以指定端点名,来暴露监控端点
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
yml文件中添加监控点
management:
endpoints:
web:
exposure:
include: hystrix.stream
访问 actuator 路径,查看监控端点
http://localhost:3001/actuator
Hystrix dashboard 仪表盘
添加仪表盘依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
yml文件配置信息,允许对哪台服务器开启监控
spring:
application:
name: hystrix-dashboard
server:
port: 4001
eureka:
client:
service-url:
defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka
hystrix:
dashboard:
proxy-stream-allow-list: localhost
主程序添加 @EnableHystrixDashboard 和 @EnableDiscoveryClient
@EnableDiscoveryClient
@EnableHystrixDashboard
@SpringBootApplication
public class Sp08HystrixDashboardApplication {
public static void main(String[] args) {
SpringApplication.run(Sp08HystrixDashboardApplication.class, args);
}
}
启动访问 hystrix dashboard
http://localhost:4001/hystrix
填入 hystrix 的监控端点,开启监控
http://localhost:3001/actuator/hystrix.stream
通过 hystrix 访问服务多次,观察监控信息
6.feign 声明式客户端接口
微服务应用中,ribbon 和 hystrix 总是同时出现,feign 整合了两者,并提供了声明式消费者客户端
添加依赖
application.yml
spring:
application:
name: feign
server:
port: 3001
eureka:
client:
service-url:
defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka
主程序添加 @EnableDiscoveryClient 和 @EnableFeignClients
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class Sp09FeignApplication {
public static void main(String[] args) {
SpringApplication.run(Sp09FeignApplication.class, args);
}
}
feign 声明式客户端
ItemFeignService
@FeignClient("item-service")
public interface ItemFeignService {
@GetMapping("/{orderId}")
JsonResult<List<Item>> getItems(@PathVariable String orderId);
@PostMapping("/decreaseNumber")
JsonResult decreaseNumber(@RequestBody List<Item> items);
}
注意,如果请求参数名与方法参数名不同,@RequestParam不能省略,并且要指定请求参数名:
@RequestParam(“score”) Integer s
FeignController
@RestController
public class FeignController {
@Autowired
private ItemFeignService itemService;
@GetMapping("/item-service/{orderId}")
public JsonResult<List<Item>> getItems(@PathVariable String orderId) {
return itemService.getItems(orderId);
}
@PostMapping("/item-service/decreaseNumber")
public JsonResult decreaseNumber(@RequestBody List<Item> items) {
return itemService.decreaseNumber(items);
}
}
调用流程