一、Nacos配置管理
1、统一配置管理
配置更改热更新
在Nacos中添加配置信息:
在弹出表单中填写配置信息:
配置获取的步骤如下:
1.引入Nacos的配置管理客户端依赖:
2.在userservice中的resource目录添加一个bootstrap.yml文件,这个文件是引导文件,优先级高于application.yml:
我们在user-service中将pattern.dateformat这个属性注入到UserController中做测试:
总结:
将配置交给Nacos管理的步骤
2、配置热更新
配置自动刷新
Nacos中的配置文件变更后,微服务无需重启就可以感知。不过需要通过下面两种配置实现:
方式一:在@Value注入的变量所在类上添加注解@RefreshScope
方式二:使用@ConfigurationProperties注解
总结:
Nacos配置更改后,微服务可以实现热更新,方式:
注意事项:
3、配置共享
微服务启动时会从nacos读取多个配置文件:
[spring.application.name]-[spring.profiles.active].yaml,例如:userservice-dev.yaml
[spring.application.name].yaml,例如:userservice.yaml
无论profile如何变化,[spring.application.name].yaml这个文件一定会加载,因此多环境共享配置可以写入这个文件
多种配置的优先级:
服务名-profile.yaml >服务名称.yaml > 本地配置
总结:
微服务会从nacos读取的配置文件:
优先级:
4、搭建Nacos集群
集群结构图:
集群搭建步骤:
二、Feign远程调用
1、Feign替代RestTemplate
RestTemplate方式调用存在的问题
先来看我们以前利用RestTemplate发起远程调用的代码:
存在下面的问题:
1、代码可读性差,编程体验不统一
2、参数复杂URL难以维护
Feign的介绍
Feign是一个声明式的http客户端,官方地址:GitHub - OpenFeign/feign: Feign makes writing java http clients easier
其作用就是帮助我们优雅的实现http请求的发送,解决上面提到的问题。
定义和使用Feign客户端
使用Feign的步骤如下:
1.引入依赖:
2.在order-service的启动类添加注解开启Feign的功能
3.编写Feign客户端:
主要是基于SpringMVC的注解来声明远程调用的信息,比如:
4.用Feign客户端代替RestTemplate
总结:
Feign的使用步骤
2、自定义配置
Feign运行自定义配置来覆盖默认配置,可以修改的配置如下:
一般我们需要配置的就是日志级别。
配置Feign日志有两种方式:
方式一:配置文件方式
1、全局生效:
2、局部生效:
配置Feign日志的方式二:java代码方式,需要先声明一个Bean:
1、而后如果是全局配置,则把它放到@EnableFeignClients这个注解中:(在启动类上)
2、如果是局部配置,则把它放到@FeignClient这个注解中:
总结:
Feign的日志配置:
3、Feign使用优化
Feign底层的客户端实现:
因此优化Feign的性能主要包括:
Feign的性能优化-连接池配置
Feign添加HttpClient的支持:
引入依赖:
配置连接池:
总结:
Feign的优化:
4、最佳实践
方式一(继承):给消费者的FeignClient和提供者的controller定义统一的父接口作为标准。
但会出现问题:
1、服务紧耦合
2、父接口参数列表中的映射不会被继承
方式二(抽取):将FeignClient抽取为独立模块,并且把接口有关的POJO、默认的Feign配置都放到这个模块中,提供给所有消费者使用
总结:
Feign的最佳实践:
抽取FeignClient
实现最佳实践方式二的步骤如下:
1.首先创建一个module,命名为feign-api,然后引入feign的starter依赖
2.将order-service中编写的UserClient、User、DefaultFeignConfiguration都复制到feign-api项目中
3.在order-service中引入feign-api的依赖
4.修改order-service中的所有与上述三个组件有关的import部分,改成导入feign-api中的包
5.重启测试
当定义的FeignClient不在SpringBootApplication的扫描包范围时,这些FeignClient无法使用。有两种方式解决:
总结:
不同包的FeignClient的导入有两种方式:
三、Gateway服务网关
1、为什么需要网关
网关功能:
1、身份认证和权限校验
2、服务路由、负载均衡
3、请求限流
在SpringCloud中网关的实现包括两种:
1、gateway
2、zuul
Zuul是基于Servlet的实现,属于阻塞式编程。而SpringCloudGateway则是基于Spring5中提供的WebFlux,属于响应式编程的实现,具备更好的性能。
总结:
网关的作用:
1、对用户请求做身份认证、权限校验
2、将用户请求路由到微服务,并实现负载均衡
3、对用户请求做限流
2、gateway快速入门
搭建网关服务的步骤:
1.创建新的module,引入SpringCloudGateway的依赖和nacos的服务发现依赖:
2.创建启动类
3..编写路由配置及nacos地址
创建多个断言:
搭建网关服务
总结:
网关搭建步骤:
路由配置包括:
3、断言工厂
网关路由可以配置的内容包括:
1、路由id:路由唯一标示
2、uri:路由目的地,支持lb和http两种
3、predicates:路由断言,判断请求是否符合要求,符合则转发到路由目的地
4、filters:路由过滤器,处理请求或响应
我们在配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变为路由判断的条件
例如Path=/user/**是按照路径匹配,这个规则是由org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类来处理的
像这样的断言工厂在SpringCloudGateway还有十几个
Spring提供了11种基本的Predicate工厂:
名称 | 说明 | 示例 |
After | 是某个时间点后的请求 | - After=2037-01-20T17:42:47.789-07:00[America/Denver] |
Before | 是某个时间点之前的请求 | - Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai] |
Between | 是某两个时间点之前的请求 | - Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver] |
Cookie | 请求必须包含某些cookie | - Cookie=chocolate, ch.p |
Header | 请求必须包含某些header | - Header=X-Request-Id, \d+ |
Host | 请求必须是访问某个host(域名) | - Host=**.somehost.org,**.anotherhost.org |
Method | 请求方式必须是指定方式 | - Method=GET,POST |
Path | 请求路径必须符合指定规则 | - Path=/red/{segment},/blue/** |
Query | 请求参数必须包含指定参数 | - Query=name, Jack或者- Query=name |
RemoteAddr | 请求者的ip必须是指定范围 | - RemoteAddr=192.168.1.1/24 |
Weight | 权重处理 |
总结:
读取用户定义的断言条件,对请求做出判断
路径是以/user开头的就认为是符合的
4、过滤器工厂
路由过滤器 GatewayFilter
GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应做处理:
Spring提供了31种不同的路由过滤器工厂。例如:
名称 | 说明 |
AddRequestHeader | 给当前请求添加一个请求头 |
RemoveRequestHeader | 移除请求中的一个请求头 |
AddResponseHeader | 给响应结果中添加一个响应头 |
RemoveResponseHeader | 从响应结果中移除有一个响应头 |
RequestRateLimiter | 限制请求的流量 |
... |
案例:给所有进入userservice的请求添加一个请求头
给所有进入userservice的请求添加一个请求头:Truth=itcast is freaking awesome!
实现方式:在gateway中修改application.yml文件,给userservice的路由添加过滤器:
如果要对所有的路由都生效,则可以将过滤器工厂写到default下。格式如下:
总结:
5、全局过滤器
全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样。
区别在于GatewayFilter通过配置定义,处理逻辑是固定的。而GlobalFilter的逻辑需要自己写代码实现。
定义方式是实现GlobalFilter接口。
案例:定义全局过滤器,拦截并判断用户身份
需求:定义全局过滤器,拦截请求,判断请求的参数是否满足下面条件:
如果同时满足则放行,否则拦截
步骤1:自定义过滤器
自定义类,实现GlobalFilter接口,添加@Order注解:
总结:
对所有路由都生效的过滤器,并且可以自定义处理逻辑
过滤器执行顺序
请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter
请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter,合并到一个过滤器链(集合)中,排序后依次执行每个过滤器
-每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前。
-GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定order值,由我们自己指定
-路由过滤器和defaultFilter的order由Spring指定,默认是按照声明顺序从1递增。
-当过滤器的order值一样时,会按照 defaultFilter > 路由过滤器 > GlobalFilter的顺序执行。
可以参考下面几个类的源码来查看:
总结:
6、跨域问题
跨域问题处理
跨域:域名不一致就是跨域,主要包括:
1、域名不同: www.taobao.com 和 www.taobao.org 和 www.jd.com 和 miaosha.jd.com
2、域名相同,端口不同:localhost:8080和localhost8081
跨域问题:浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题
解决方案:CORS
网关处理跨域采用的同样是CORS方案,并且只需要简单配置即可实现:
CORS跨域要配置的参数包括哪几个?
整体框架
学习路径
限流过滤器
限流:对应用服务器的请求做限制,避免因过多请求而导致服务器过载甚至宕机。限流算法常见的包括两种:
1、计数器算法,又包括窗口计数器算法、滑动窗口计数器算法
2、漏桶算法(Leaky Bucket)
3、令牌桶算法(Token Bucket)
限流过滤器-计数器算法
固定窗口计数器算法概念如下:
1、将时间划分为多个窗口;
2、在每个窗口内每有一次请求就将计数器加一,当时间到达下一个窗口时,计数器重置。
3、如果计数器超过了限制数量,则本窗口内所有的请求都被丢弃。
限流过滤器-漏桶算法
漏桶算法说明:
1、将每个请求视作"水滴"放入"漏桶"进行存储;
2、"漏桶"以固定速率向外"漏"出请求来执行,如果"漏桶"空了则停止"漏水”;
3、如果"漏桶"满了则多余的"水滴"会被直接丢弃。
限流过滤器-令牌桶算法
漏桶算法说明:
1、以固定的速率生成令牌,存入令牌桶中,如果令牌桶满了以后,多余令牌丢弃
2、请求进入后,必须先尝试从桶中获取令牌,获取到令牌后才可以被处理
3、如果令牌桶中没有令牌,则请求等待或丢弃
总结:
限流有什么作用?
限流算法: