远程调用Rest Template
服务注册与发现&分布式配置管理
Consul
下载安装
官网https:/ldeveloper.hashicorp.com/consul/downloads
开发者模式启动consul agennt -dev
浏览器访问本地端口:8500
服务注册与发现
Maven引入
<!--SpringCloud consul discovery -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
YML配置
server:
port: 8001
# ==========applicationName + druid-mysql8 driver===================
spring:
application:
name: cloud-payment-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db2024?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
password: 123456
####Spring Cloud Consul for Service Discovery
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}
# ========================mybatis===================
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.atguigu.cloud.entities
configuration:
map-underscore-to-camel-case: true
主启动类添加@EnableDiscoveryClient
注解
启动服务查看consul
使用RestTemplate需要在配置类@Bean
下添加@LoadBalanced
此时使用RestTemplate向支付服务发起请求
指定URL只需填写yml中服务配置的名称
public static final String PaymentSrv_URL = "http://cloud-payment-service";//服务注册中心上的微服务名称
CAP
C Consistency强一致性
A Availability可用性
P Partition tolerance分区容错性
最多只能同时较好的满足两个。
CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,
因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三 大类:
CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。
CP - 满足一致性,分区容忍性的系统,通常性能不是特别高。
AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。
Consul与其他注册中心的比较
AP 保证高可用, 新值尚未同步也返回旧值(给个交代)
CP 为保证一致性, 拒绝请求(必须正确),违背了可用性A的要求
服务配置与刷新
Maven引入依赖
<!--SpringCloud consul config-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
bootstrap与application yml
bootstrap有更高的优先级, 从外部源(配置中心)获取,
本地application的配置默认无法覆盖bootstrap的配置
Consul Key/Value配置
bootstrap中修改间隔符
spring:
application:
name: cloud-payment-service
####Spring Cloud Consul for Service Discovery
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}
config:
profile-separator: '-' # default value is ",",we update '-'
format: YAML
# config/cloud-payment-service/data
# /cloud-payment-service-dev/data
# /cloud-payment-service-prod/data
application中profiles:active:可选择Consul中生效的配置Data文件
server:
port: 8001
# ==========applicationName + druid-mysql8 driver===================
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db2024?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
password: 123456
profiles:
active: dev # 多环境配置加载内容dev/prod,不写就是默认default配置
# ========================mybatis===================
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.atguigu.cloud.entities
configuration:
map-underscore-to-camel-case: true
新建文件夹config/
再建子文件夹
cloud-payment-service-dev/
cloud-payment-service-prod/
cloud-payment-service/
再分别建data文件, 编写配置
动态刷新
默认55秒间隔就会自动刷新,
如果要修改
主启动类添加注解@RefreshScope
bootstrap.yml中添加
spring:cloud:consul:config:watch:wait-time:1
配置1秒刷新
Consul配置持久化
重启后Consul配置是否还在?
服务间调用与负载均衡
Loadbalancer
工作流程
- 从Consul获取服务列表
- 按照指定负载均衡策略(默认轮询)选择服务地址
loadbalancer本地负载均衡客户端 VS Nginx服务端负载均衡区别
Nginx是服务器负载均衡,客户端所有请求都会交给nginx,然后由nginx实现转发请求,即负载均衡是由服务端实现的。
Loadbalancer本地负载均衡,在调用微服务接口时候,会在注册中心上获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程服务调用技术。
调用负载均衡原理
感觉导不导这个包没什么区别?
<!--loadbalancer-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
查看Consul中的所有服务和获取实例信息
@Resource
private DiscoveryClient discoveryClient;
@GetMapping("/consumer/discovery")
public String discovery()
{
List<String> services = discoveryClient.getServices();
for (String element : services) {
System.out.println(element);
}
System.out.println("===================================");
List<ServiceInstance> instances = discoveryClient.getInstances("cloud-payment-service");
for (ServiceInstance element : instances) {
System.out.println(element.getServiceId()+"\t"+element.getHost()+"\t"+element.getPort()+"\t"+element.getUri());
}
return instances.get(0).getServiceId()+":"+instances.get(0).getPort();
}
负载算法切换
默认算法有两种: 轮询和随机
都是通过实现接口ReactorServiceInstanceLoadBalancer
浅看一下源码(不用深入,非重点)
一般轮询足够, 除非需要自定义实现该接口
从默认的轮询切换为随机
修改RestTemplateConfig
@Configuration
@LoadBalancerClient(
//下面的value值大小写一定要和consul里面的名字一样,必须一样
value = "cloud-payment-service",configuration = RestTemplateConfig.class)
public class RestTemplateConfig
{
@Bean
@LoadBalanced //使用@LoadBalanced注解赋予RestTemplate负载均衡的能力
public RestTemplate restTemplate(){
return new RestTemplate();
}
// 修改为随机算法
@Bean
ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
}
}
⭐OpenFeign(重要)
通用配置
超时控制
配置默认超时时间
同时还可指定对某个服务的超时时间
根据"就近原则",两者同时存在时, 指定服务的也会生效(全局默认3秒,pay服务5秒,那么pay服务会最多等5秒而不是3秒)
重试机制
请求失败后,默认只会调用一次结束
在客户端(发起请求的服务)新增FeignConfig
@Configuration
public class FeignConfig
{
@Bean
public Retryer myRetryer()
{
//return Retryer.NEVER_RETRY; //Feign默认配置是不走重试策略的
//最大请求次数为3(1+2)失败1次重试2次,共计3次,初始间隔时间为100ms,重试间最大间隔时间为1s
return new Retryer.Default(100,1,3);
}
}
默认HttpClient修改
请求/响应压缩
日志打印
服务熔断和降级
Circuit Breaker
CircuitBreaker的目的是保护分布式系统免受故障和异常,提高系统的可用性和健壮性。
当一个组件或服务出现故障时,CircuitBreaker会迅速切换到开放OPEN状态(保险丝跳闸断电),阻止请求发送到该组件或服务从而避免更多的请求发送到该组件或服务。这可以减少对该组件或服务的负载,防止该组件或服务进一步崩溃,并使整个系统能够继续正常运行。同时,CircuitBreaker还可以提高系统的可用性和健壮性,因为它可以在分布式系统的各个组件之间自动切换,从而避免单点故障的问题。
Resilience
Circuit Breaker是规范和接口,Resilience是落地实现者
分布式链路追踪
SpringCloud Sleuth -》 Micrometer Tracing