- ZooKeeper和Eureka
- 总结
- SpringCloud技术栈
- 注册中心
- 用来修改eureka server默认接收心跳的最大时间默认是90s
eureka.instance.lease-expiration-duration-in-seconds=10
#指定客户端多久向eureka server发送一次心跳 默认是30s
eureka.instance.lease-renewal-interval-in-seconds=5 - 服务调度
- 服务熔断
- 2.不同
- 服务熔断是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑.
- 管理目标的层次不一样,熔断其实是一个框架级别的处理,每个微服务都需要,而降级一般需要对业务有层级之分
# 3.总结
- 熔断必会触发降级,所以熔断也是降级的一种.区别在于熔断是对调用链路的保护,而降级是对系统过载的一种保护处理. - 断路器打开的条件:
- 当满足一定的阈值的时候(默认10秒内超过20个请求)
- 当失败率达到一个百分比的时候(默认10秒内超过50%的失败率)
# 断路器关闭的条件:
- 一定时间之后(默认是5S),断路器会变为半开状态,会使一个请求通过.如果请求成功,断路器会关闭,如果失败继续开启 - 1.引入依赖
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
# 2.开启openfeign支持服务降级
#开启openfeign支持降级
feign.hystrix.enabled=true
# 3.在OpenFeign客户端加入Hystrix的FallBack
@FeignClient(value = “Product”, fallback = ProductFallBack.class)
public interface ProductClient {
@GetMapping(“/product/hystrix”)
String testHystrix(@RequestParam String name);
}
# 4.开发fallback处理类
@Component
public class ProductFallBack implements ProductClient {
@Override
public String testHystrix(String name) {
return “我是客户端的Hystrix服务实现”;
}
}
注意:如果服务端降级和客户端降级同时开启,要求服务端降级方法的返回值必须与客户端方法降级的返回值一致 - 服务网关
- http://localhost:9999/ #指定转发路径
uri: lb://users
predicates:
- Path=/users/ #指定路由规则
- id: products
# uri: http://localhost:9998/
uri: lb://products #lb:代表使用负载均衡策略 products代表注册中心具体服务名
predicates:
- Path=/products/
discovery:
locator:
enabled: true #开启根据服务名获取路由地址 负载均衡">1.说明
- 现有路由配置方式,都是基于服务地址写死的路由转发,能不能根据服务名称进行路由转发的同时实现负载均衡呢?
spring:
application:
name: gateway
cloud:
consul:
port: 8500
host: localhost
discovery:
service-name: ${spring.application.name}
gateway:
routes:
- id: users #指定路由key 唯一
# uri: http://localhost:9999/ #指定转发路径
uri: lb://users
predicates:
- Path=/users/ #指定路由规则
- id: products
# uri: http://localhost:9998/
uri: lb://products #lb:代表使用负载均衡策略 products代表注册中心具体服务名
predicates:
- Path=/products/
discovery:
locator:
enabled: true #开启根据服务名获取路由地址 负载均衡
自定义Filter
@Configuration
public class CustomGlobalFilter implements GlobalFilter, Ordered {
@Override
public Monofilter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 如果请求参数含有username
if (exchange.getRequest().getQueryParams().get(“username”) != null) {
return chain.filter(exchange);
}">作用
- 可以方便的把公共模块抽取出来,起到类似于AOP的功能.比如可以抽离日志,鉴权等功能.
内置的Filter
自定义Filter
@Configuration
public class CustomGlobalFilter implements GlobalFilter, Ordered {
@Override
public Monofilter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 如果请求参数含有username
if (exchange.getRequest().getQueryParams().get(“username”) != null) {
return chain.filter(exchange);
}- Config
- https://gitee.com/qumingbo98/springcloudconfig.git
#spring.cloud.config.server.git.username=
#spring.cloud.config.server.git.password=">配置远端仓库配置地址
spring.cloud.config.server.git.uri=https://gitee.com/qumingbo98/springcloudconfig.git
#spring.cloud.config.server.git.username=
#spring.cloud.config.server.git.password= - 拉取远端配置规则
- label/name-profiles.yml
label 代表去哪个分支获取 默认使用master分支<br />
name 代表读取那个具体的配置文件名称
`profile 代表读取配置文件环境 - 本地存放配置文件的路径一定要使用相对路径
#配置分支和本地仓库的位置(本地仓库目录一定是一个空目录,首次拉取配置时会将目录清空)
spring.cloud.config.server.git.basedir=configserver7878/src/main/resources/config
spring.cloud.config.server.default-label=master - 1.说明
- 在生产环境中,微服务可能非常的多,每次修改完配置之后,不可能对所有的服务都重新启动,这个时候需要让修改配置的服务能够刷新远端修改之后的配置,从而不需要每次都要重启服务,进一步提高微服务系统的维护效率.在SpringCloud中也为我们提供了手动刷新配置和自动刷新配置两种策略.
在config client端加入刷新暴露节点management.endpoints.web.exposure.incloud=* #开启所有web端点暴露
在需要刷新代码的类中加入刷新配置的注解
@RestController
@RefreshScope
@Slf4j
public class TestController {
@Value(“${name}”)
private String name;
@GetMapping(“/test/test”)
public String get() {
log.info(“当前加载配置文件信息为:[{}]”, name);
return name;
}
} - Bus
- Spring Cloud Alibaba
ZooKeeper和Eureka
总结
1.ZooKeeper保证的是CP,Eureka保证的是AP
ZooKeeper在选举期间注册服务瘫痪,虽然服务最终会恢复,但是选举期间不可用的
Eureka各个节点是平等关系,只要有一台Eureka就可以保证服务可用,而查询到的数据并不是最新的。
自我保护机制会导致:
Eureka不再从注册列表移除因长时间没收到心跳而应该过期的服务
Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点(高可用)
当网络稳定时,当前实例新的注册信息会被同步到其他节点中(最终一致性)
Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像ZooKeeper一样使得整个注册系统瘫痪
2.ZooKeeper有Leader和Follower角色,Eureka各个节点平等
3.ZooKeeper采用过半数存活原则,Eureka采用自我保护机制解决分区问题
4.Eureka本质上是一个工程,而ZooKeeper只是一个进程
https://www.yuque.com/xiaoshi-nyxlg/lqcgz7/xph3t2#d0ZKy
1、什么是微服务
微服务就是一种架构方式,将单个的整体应用分割成小的相互关联的独立的服务。一个服务通常实现一组独立的特性或者功能,包含自己的业务逻辑。各个服务之间的关联通过暴露API完成。这些独立的微服务不需要部署在同一个虚拟机,同一个系统和同一个应用服务器中。
2、架构演变
单体应用
- 单体应用架构在项目初期开发方便,测试方便,部署方便。
- 随着项目的发展,功能越来越多,会造成项目代码相当臃肿。
- 如果新加入的模块想要使用新的技术和框架,将会无法升级。
- 任意一个模块发生问题都会影响到整体应用的运行。
微服务应用
版本对应关系
Spring Cloud Release Train | Spring Boot Version |
---|---|
Hoxton | 2.2.x |
Greenwich | 2.1.x |
Finchley | 2.0.x |
Edgware | 1.5.x |
Dalston | 1.5.x |
Camden | 1.4.x |
Brixton | 1.3.x |
Angle | 1.2.x |
SpringCloud技术栈
注册中心
Eureka
Eureka Server
- 引入依赖
- 修改配置文件
server.port=8761
spring.application.name=eurekaserver
#eureka暴露的服务中心地址
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
#注册中心延迟注册自己
eureka.client.fetch-registry=false
#不向自己注册自己
eureka.client.register-with-eureka=false
- 启动类增加注解
@EnableEurekaServer
- 修改配置文件
server.port=8888
spring.application.name=eurekaclient
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
- 启动类添加注解
@EnableEurekaClient
- 查看Eureka实例列表注册成功!
- Eureka自我保护机制
细心的同学可能发现,当服务注册到Eureka上后,Eureka的DashBoard出现报警,这就是Eureka的自我保护机制。
当服务频繁启动时,就会触发Eureka的自我保护机制。从而报警。
EMERGENCY!EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT.RENEWALS ARE LESSER THAN WHRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE
默认情况下,如果Eureka在一定时间内(90s)没有收到某个服务的心跳,注册中心就会认为该服务已经下线,从而将该服务从实例列表中移除,但是如果存在网络故障,服务并没有下线,而是因为网络问题无法正常与注册中心通信,此时不应该移除该服务。所以Eureka引入了自我保护机制。Eureka在运行期间会统计15分钟内心跳比例是否低于85%,如果低于85%Eureka会将这些实例保护起来,不让这些实例过期。
关闭Eureka的自我保护机制
eureka.client.enable-self-preservation=false #关闭自我保护机制
eureka.client.eviction-interval-timer-in-ms=3000 #超时3s自动清除
- 缩短心跳间隔
用来修改eureka server默认接收心跳的最大时间默认是90s
eureka.instance.lease-expiration-duration-in-seconds=10
#指定客户端多久向eureka server发送一次心跳 默认是30s
eureka.instance.lease-renewal-interval-in-seconds=5
consul
下载,安装和启动
下载地址:https://www.consul.io/
下载之后解压,windows双击exe启动,mac以及linux使用命令consul agent -dev启动。
引入依赖
修改配置文件
server.port=8898
spring.application.name=consulclinet
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
启动类增加注解(可加可不加)
@EnableDiscoveryClient
启动服务,查看DashBoard
consul健康检查问题
服务注册之后会发现服务名前会有一个红色X号表示服务不可用,这是consul的健康检查机制。解决方案有两个:
1.关闭consul的健康检查(不推荐)
2.引入soringboot的健康检查依赖
CAP定理
CAP定理又称CAP原则。指在同一个分布式系统中,一致性、可用性、分区容错性。CAP原则指的是,这三个要素同时只能满足两个,无法同时满足三个原则。
一致性:在分布式系统中的所有数据备份,在同一时刻是否有同样的值。(所有节点访问同一份最新的数据副本)
可用性:在集群中一部分节点故障之后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
分区容错性:就是高可用性,一个节点宕机并不影响其他节点的正常运行。
Eureka的特点
Eureka没有使用任何数据的强一致性算法保证集群间Server的数据一致,只是通过数据拷贝的方式来实现注册中心数据的最终一致性,但是它实现了服务的高可用性,保证服务的健壮。
Consul的特点
Consul是强一致性的注册中心,因为leader节点承担了所有的处理工作,所以降低了服务的可用性。
Zookepper的特点
基于zab协议,zookepper可以用于构建数据强一致性的服务注册和发现中心,相对的因此牺牲了服务的可用性并提高了注册需要的时间。
组件名 | 语言 | CAP | 一致性算法 | 服务健康检查 | 对外暴露接口 | SpringCloud集成 |
---|---|---|---|---|---|---|
Eureka | Java | AP | 无 | 可配置支持 | HTTP | 已集成 |
Consul | Go | CP | Raft | 支持 | HTTP/DNS | 已集成 |
Zookepper | Java | CP | Zab | 支持 | 客户端 | 已集成 |
服务调度
基于RestTemplate的服务调用
RestTemplate是Spring提供的访问Rest服务的客户端,内置了大量的发送Http请求的方法,可以很方便的替代httpclient,okhttp等第三方框架。
RestTemplate的缺点:
- RestTemplate无法根据服务的状态去调用服务,当某些服务宕机后如果去调用该服务会发生错误。
- RestTemplate代码是写死的当服务分布式部署的时候,代码会非常冗余。
Ribbon
引入Ribbon依赖
如果使用的注册中心为Eureka或者Consul,不需要显式引入Ribbon依赖,因为在Eureka和Consul的依赖中已经引入了Ribbon的依赖。
如果使用的是其他注册中心,想要使用Ribbon做负载均衡就要显式引入Ribbon依赖,Ribbon依赖如下。
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
DiscoveryClient
@Autowire
private DiscoveryClient discoveryClient;
// 因为我以products9998的名字启动了两个products实例,在注册中心上会存在两个名为products9998的实例
List
// 此时获取到名为products9998的实例后 打印实例的host和port 因为注册中心注册了两个实例所以会分别打印两个实例的host和port
for (ServiceInstance serviceInstance : products9998) {
System.out.println(serviceInstance.getHost());
System.out.println(serviceInstance.getPort());
}
此时关闭任意一个products实例,再次请求接口,看看会发生什么?
可以看到,关闭一个实例之后,注册中心立马获取到该实例已经下线,使consul里的实例数量变为一个。
再次请求接口来看看!
可以看到,请求接口后获取到的实例仅仅只有一个,正是我们未关闭的另一个实例的信息。
LoadBalancerClient
@Autowire
private LoadBalancerClient loadBalancerClient;
ServiceInstance serviceInstance = loadBalancerClient.choose(“products9998”);
RestTemplate restTemplate = new RestTemplate();
String forObject =
restTemplate.getForObject(“http://“ + serviceInstance.getHost() + “:” + serviceInstance.getPort() +
“/product/findAll”, String.class);
LoadBalancerClient采用的轮询的负载均衡算法,我们启动服务之后,连续请求两次端口,查看控制台输出的host和port。
可见第一次请求被分发到9997这个端口的服务上,第二次请求分发到端口为9998这个服务上。
@LoadBalanced方式调用
配置RestTemplate,使得RestTemplate具有负载均衡功能。
@Configuration
public class RestTemplateConfig {
@Bean<br /> //加上这个注解返回的RestTemplate就具有了负载均衡的功能<br /> @LoadBalanced<br /> public RestTemplate getRestTemplate() {<br /> return new RestTemplate();<br /> }<br />}<br />@Autowire<br />private final RestTemplate restTemplate;
//直接使用服务名来代替host:port来调用服务,ribbon会自动完成负载均衡的请求分发。
String forObject = restTemplate.getForObject(“http://products9998/product/findAll“, String.class);
Ribbon负载均衡算法
- ribbon负载均衡算法
- RoundRobinRule 轮询策略 按照顺序选择服务
- RandomRule 随机策略 随机选择Server
- AvailabilityFilteringRule 可用过滤策略
> 会先过滤由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问
- WeightedResponseTimeRule 响应时间加权策略
> 根据平均响应的时间计算所有服务的权重,响应时间越快的服务权重越大被选中的几率就越高,刚启动时如果统计信息不足,则使用RoundRobinRule策略,等到统计信息足够会切换到响应时间加权策略
- RetryRule 重试策略
> 先按照RoundRobinRule的策略获取服务,如果获取失败则在指定时间内重试,获取可用的服务.
- BestAviableRule 最低并发策略
> 先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务OpenFeign
- 为什么要使用Feign
- 每次调用服务都要使用RestTemplate写重复的代码.
-
OpenFeign组件
Feign是一个声明式的伪HTTP客户端,使得发送HTTP请求更加简单,使用Feign,只需要写一个接口并增加注释,它具有可插拔的注解特性(可以使用SpringMVC的注解),可使用Feign注解和JAX-RS注解.Feign支持可插拔的编码器和解码器,Feign默认集成了Ribbon,默认实现了负载均衡的效果并且SpringCloud为Feign添加了SpringMVC的注解支持.
OpenFeign服务调用
引入OpenFeign依赖
- 启动类开启OpenFeign支持
@SpringBootApplication
@EnableFeignClients //开启支持OpenFeign组件方式调用
public class Users9999Application {
public static void main(String[] args) {<br /> SpringApplication.run(Users9999Application.class, args);<br /> }
}
- 编写Feign调用接口类
/*
@author admin
调用商品服务的 openFeign组件
/
// 用来标记当前接口是一个feign的组件 值写的是调用服务的名字
@FeignClient(value = “products9998”)
public interface ProductClient {
/**<br /> * 接口上方写需要调用服务的路径<br /> * @return 返回值和调用接口的返回值相同<br /> */<br /> @GetMapping("/product/show")<br /> String getShowMsg();<br />}
- 发送请求查看是否请求成功,以及负载均衡的效果.
- 发送请求时如何携带参数?
- GET请求
在Feign调用的接口中,传入参数并使用@RequestParam注解修饰
/*
查询一个商品信息
使用openFeign的Get方式传递参数,参数必须添加@RequestParam注解
@param productId 商品id
@return 商品信息
/
@GetMapping(“/product/findOne”)
Map
- POST请求
在Feign调用的接口中,参数使用@RequestBody注解修饰
/*
post调用
@param product
@return
*/
@PostMapping(“/product/save”)
Map
OpenFeign设置超时时间
OpenFeign默认规定1S内得不到响应就会抛出异常,提示连接超时。
在调用方配置超时时间
feign.client.config.default.read-timeout=5000
feign.client.config.default.connect-timeout=5000
OpenFeign开启调用日志
配置:
- Feign日志级别:
‘NONE’ 不记录任何日志
‘BASIC’ 仅记录请求方法,URL,响应状态代码及执行时间
‘HEADERS’ 记录Basic基础上,记录请求和响应时间的header
‘FULL’ 记录请求和响应的Header,Body和元数据
开启日志
feign.client.config.default.logger-level=full
服务熔断
Hystrix
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统中,许多依赖不可避免的会调用失败,超市,异常等情况.Hystrix可以保证一个依赖出现问题的时候,不会导致全部失败,避免服务雪崩,提高分布式系统的可用性.
服务雪崩
在微服务调用中,由于某一个服务发生故障.导致其他服务级联故障,成为服务雪崩.
服务熔断
当某个服务发生故障之后,通过断路器的故障监控,某个异常条件被处罚,直接熔断整个服务.向调用方法返回一个FallBack,而不是长时间的等待或者抛出调用方法无法处理的异常,就保证了服务调用方的线程不会长时间占用,避免故障在分布式系统中蔓延,乃至雪崩.如果服务恢复正常就回复调用.服务熔断是解决服务雪崩的重要手段.
服务降级
服务压力剧增的时候根据当前的业务情况以及流量对一些服务和页面有策略的降级,从而缓解服务器的压力,保证核心任务正常运行.保证部分甚至大部分客户都能得到正确的响应.
服务降级和服务熔断的异同
# 1.共同点
- 都是从可用性可靠性着想,为了防止系统的整体崩溃而做出的手段.
- 最终表现相同,用户所感知到的某些功能暂时不可用.
- 粒度都是服务级别,业界有其他更细粒度的方法,比如做到方法级别.
- 熔断模式一般都是服务基于策略的自动触发,降级虽说可人工降级,但是并不能所有的降级都需要人工处理.
2.不同
- 服务熔断是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑.
- 管理目标的层次不一样,熔断其实是一个框架级别的处理,每个微服务都需要,而降级一般需要对业务有层级之分
# 3.总结
- 熔断必会触发降级,所以熔断也是降级的一种.区别在于熔断是对调用链路的保护,而降级是对系统过载的一种保护处理.
实现服务熔断
- 引入Hystrix依赖,并开启断路器
- 模拟降级方法
- 进行测试
- 引入Hystrix依赖
- 开启断路器
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker //打开断路器
public class Products9998Application {
public static void main(String[] args) {<br /> SpringApplication.run(Products9998Application.class, args);<br /> }
}
- 使用注解完成熔断快速返回
/*
测试方法
@param id id
@return id
*/
@GetMapping(“/product/broke”)
@HystrixCommand(fallbackMethod = “brokeFallBack”)
public String broke(Integer id) {
if (id <= 0) {
throw new RuntimeException(“参数错误”);
}
return “通过Hystrix,参数为:” + id;
}
/**<br /> * 触发熔断的FallBack方法<br /> * @param id 触发熔断时的参数<br /> * @return 触发熔断时的信息<br /> */<br /> public String brokeFallBack(Integer id) {<br /> return "参数错误,请更改后重试";<br /> }
- 断路器打开条件
断路器打开的条件:
- 当满足一定的阈值的时候(默认10秒内超过20个请求)
- 当失败率达到一个百分比的时候(默认10秒内超过50%的失败率)
# 断路器关闭的条件:
- 一定时间之后(默认是5S),断路器会变为半开状态,会使一个请求通过.如果请求成功,断路器会关闭,如果失败继续开启
实现服务降级
1.引入依赖
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
# 2.开启openfeign支持服务降级
#开启openfeign支持降级
feign.hystrix.enabled=true
# 3.在OpenFeign客户端加入Hystrix的FallBack
@FeignClient(value = “Product”, fallback = ProductFallBack.class)
public interface ProductClient {
@GetMapping(“/product/hystrix”)
String testHystrix(@RequestParam String name);
}
# 4.开发fallback处理类
@Component
public class ProductFallBack implements ProductClient {
@Override
public String testHystrix(String name) {
return “我是客户端的Hystrix服务实现”;
}
}
注意:如果服务端降级和客户端降级同时开启,要求服务端降级方法的返回值必须与客户端方法降级的返回值一致
Hystrix Dashboard
Hystrix Dashboard收集了每个HystrixCommand的一组度量.Hystrix Dashboard以简洁明了的方式显示每个断路器的工作状况.
- 引入依赖
- 启动类开启Hystrix Dashboard注解
@SpringBootApplication
@EnableHystrixDashboard
public class Hystrixdashboard9990Application {
public static void main(String[] args) {<br /> SpringApplication.run(Hystrixdashboard9990Application.class, args);<br /> }
}
- 访问页面查看仪表盘
被监控服务入口类增加监控路径配置.
@Bean
public ServletRegistrationBean getServlet() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings(“/hystrix.stream”);
registrationBean.setName(“HystrixMetricsStreamServlet”);
return registrationBean;
}服务网关
Gateway
什么是服务网关
# 1.说明
- 网关统一服务入口,可方便实现对平台众多服务接口进行管控,对访问服务的身份认证,防报文重放与防数据篡改,功能调用的业务鉴权,响应数据的脱敏,流量与并发控制,甚至基于API调用的计量或者计费等等.
- 网关 = 路由转发 + 过滤器
路由转发: 接收一切外界请求,转发到后端的微服务上去;<br />
在服务网关中可以完成一系列的横切功能,例如权限校验,限流以及监控等,这些都可以通过过滤器完成
# 2.为什么需要服务网关
- 1.网关可以实现服务的统一管理
- 2.网管额可以解决微服务中通用代码的冗余问题(如权限控制,流量监控,限流等)
# 3.网关组件在微服务中架构
网关动态路由
网关配置有两种方式,一种是使用配置文件配置,一种是使用Java代码配置.
org.springframework.cloud
spring-cloud-starter-gateway
注意! gateway使用了webflux异步非阻塞框架,所以使用gateway的时候不能引入spring-boo-starter-web的依赖
配置gateway
使用配置文件配置
server:
port: 8080
spring:
application:
name: gateway
cloud:
consul:
port: 8500
host: localhost
discovery:
service-name: ${spring.application.name}
gateway:
routes:
- id: users #指定路由key 唯一
uri: http://localhost:9999/ #指定转发路径
predicates:
- Path=/users/ # 指定路由规则
- id: products
uri: http://localhost:9998/
predicates:
- Path=/products/
使用Java代码配置
@Configuration
public class GatewayConfig {
@Bean<br /> public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {<br /> return builder.routes().route("order_route", r -> r.path("/order/**")<br /> .uri("http://localhost:9997")).build();<br /> }<br />}
配置开启web端点
management:
endpoints:
web:
exposure:
include: “*” #暴露路由规则web端点
访问http://localhost:8080/actuator/gateway/routes
配置网关的负载均衡
1.说明
- 现有路由配置方式,都是基于服务地址写死的路由转发,能不能根据服务名称进行路由转发的同时实现负载均衡呢?
spring:
application:
name: gateway
cloud:
consul:
port: 8500
host: localhost
discovery:
service-name: ${spring.application.name}
gateway:
routes:
- id: users #指定路由key 唯一
# uri: http://localhost:9999/ #指定转发路径
uri: lb://users
predicates:
- Path=/users/ #指定路由规则
- id: products
# uri: http://localhost:9998/
uri: lb://products #lb:代表使用负载均衡策略 products代表注册中心具体服务名
predicates:
- Path=/products/
discovery:
locator:
enabled: true #开启根据服务名获取路由地址 负载均衡
常用路由predicate(断言,验证)
常用的predicate:
- After=2021-03-17T22:45:06.452+08:00[Asia/Shanghai] #指定日期之后的请求进行路由
- Before=2021-03-17T22:48:06.452+08:00[Asia/Shanghai] #指定日期之前的请求进行路由
- Between=2021-03-18T00:00:00.000+08:00[Asia/Shanghai],2021-03-19T23:59:59.999+08:00[Asia/Shanghai] #指定日期之间的请求进行路由
- Cookie=key, value #携带指定Cookie的请求进行路由
- Header=X-Request-Id, \d+ #请求头中指定属性的正则匹配路由
- Method=GET,POST #指定请求方式进行路由
常用的filter以及自定义filter
- 路由过滤器允许以某种方式修改传入的HTTP请求或者发出的HTTP响应.路由筛选器的作用域是特定路由,Spring Cloud Gateway包含多个内置的GatewayFilter工厂.
作用
- 可以方便的把公共模块抽取出来,起到类似于AOP的功能.比如可以抽离日志,鉴权等功能.
内置的Filter
自定义Filter
@Configuration
public class CustomGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 如果请求参数含有username
if (exchange.getRequest().getQueryParams().get(“username”) != null) {
return chain.filter(exchange);
}
// 如果请求参数含有username
if (exchange.getRequest().getQueryParams().get(“username”) != null) {
return chain.filter(exchange);
}
// 拒绝访问<br /> return exchange.getResponse().setComplete();<br /> }
@Override<br /> public int getOrder() {<br /> //设置过滤器执行顺序,数字越小,越优先执行<br /> return -1;<br /> }<br />}
Config
config就是统一配置中心,他可以将微服务的配置进行统一管理,优点在于进行集权部署的时候,应用相同配置的服务可以实现修改一份配置就可以全部修改完成,而不用一个一个服务的去修改配置.
Config Server
- 引入依赖
- 启动类增加开启Config的注解
@SpringBootApplication
@EnableConfigServer
@EnableDiscoveryClient
public class Configserver7878Application {
public static void main(String[] args) {<br /> SpringApplication.run(Configserver7878Application.class, args);<br /> }
}
- 直接启动项目,查看报错信息
- 配置git远程仓库地址
配置远端仓库配置地址
spring.cloud.config.server.git.uri=https://gitee.com/qumingbo98/springcloudconfig.git
#spring.cloud.config.server.git.username=
#spring.cloud.config.server.git.password=
- 再次启动配置中心查看远程配置
拉取远程配置的三种方式
- 1.http://localhost:7878/配置文件名-xxx.properties
- 2.http://localhost:7878/配置文件名-xxx.yml
- 3.http://localhost:7878/配置文件名-xxx.json
- 拉取远端配置规则
拉取远端配置规则
- label/name-profiles.yml
label 代表去哪个分支获取 默认使用master分支<br />
name 代表读取那个具体的配置文件名称
`profile 代表读取配置文件环境
- 查看远端配置详细信息
访问http://localhost:7878/client/dev #client是配置文件名 dev指配置文件后缀名
- 指定拉取配置文件的分支和本地存放配置文件的路径
本地存放配置文件的路径一定要使用相对路径
#配置分支和本地仓库的位置(本地仓库目录一定是一个空目录,首次拉取配置时会将目录清空)
spring.cloud.config.server.git.basedir=configserver7878/src/main/resources/config
spring.cloud.config.server.default-label=master
Config Client
引入config-client依赖
在远端添加配置
配置拉取配置
#开启远端配置查找
spring.cloud.config.discovery.enabled=true
#configserver在注册中心上的服务名
spring.cloud.config.discovery.service-id=configserver
#拉取配置的分支
spring.cloud.config.label=master
#拉取配置的名字
spring.cloud.config.name=client
#拉取配置的环境
spring.cloud.config.profile=dev
spring.application.name=configclient
注意:配置文件改名bootstrap,否则会无法拉取远端配置
手动刷新远程配置
1.说明
- 在生产环境中,微服务可能非常的多,每次修改完配置之后,不可能对所有的服务都重新启动,这个时候需要让修改配置的服务能够刷新远端修改之后的配置,从而不需要每次都要重启服务,进一步提高微服务系统的维护效率.在SpringCloud中也为我们提供了手动刷新配置和自动刷新配置两种策略.
在config client端加入刷新暴露节点
management.endpoints.web.exposure.incloud=* #开启所有web端点暴露
在需要刷新代码的类中加入刷新配置的注解
@RestController
@RefreshScope
@Slf4j
public class TestController {
@Value(“${name}”)
private String name;
@GetMapping(“/test/test”)
public String get() {
log.info(“当前加载配置文件信息为:[{}]”, name);
return name;
}
}
Bus
Spring Cloud Bus links nodes of a distributed system with a lightweight message broker. This can then be used to broadcast state changes (e.g. configuration changes) or other management instructions. AMQP and Kafka broker implementations are included with the project. Alternatively, any Spring Cloud Stream binder found on the classpath will work out of the box as a transport.
Spring Cloud Bus将轻量级消息代理程序链接到分布式系统的节点。 然后可以将其用于广播状态更改(例如配置更改)或其他管理指令。 该项目包括AMQP和Kafka经纪人实施。 另外,在类路径上找到的任何Spring Cloud Stream活页夹都可以作为传输工具使用。
实现配置刷新的原理
广播通知刷新配置
服务端引入Bus依赖
服务端和连接端配置rabbitmq的地址
spring.rabbitmq.host=47.117.114.56
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
启动服务端和连接端
增加配置快速失败机制
spring:
cloud:
config:
discovery:
enabled: true
service-id: configserver
label: master
name: client
profile: prod
fail-fast: true
修改远程配置后访问http://localhost:7878/actuator/bus-refresh刷新配置
指定服务刷新配置
默认情况下向http://localhost:7878/actuator/bus-refresh这种方式刷新配置是广播形式刷新.所有的微服务都会刷新配置,但是有的时候我们仅仅想让某个服务刷新配置.
- 指定端口刷新某个具体的服务 http://localhost:7878/actuator/bus-refresh/configclient:9090
- 指定服务id刷新服务集群节点 http://localhost:7878/actuator/bus-refresh/configclient
Webhooks刷新配置
打开Git仓库的设置,选择Webhooks选项
选择Add webhook
回调Url输入公网的地址,Content-type选择json类型,Secret设置签名信息,下方选择什么时候触发该回调,我们选择每次push操作的时候触发该webhookSpring Cloud Alibaba
引入springcloudalibaba的依赖