1、Ribbon、Fegin和OpenFegin
- Ribbon
- Ribbon是 Netflix开源的基于HTTP和TCP等协议负载均衡组件
- Ribbon 可以用来做客户端负载均衡,调用注册中心的服务
- Ribbon的使用需要代码里手动调用目标服务,请参考官方示例:https://github.com/Netflix/ribbon
- Feign
- Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客户端
- Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。
- Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务
- Feign支持的注解和用法请参考官方文档:https://github.com/OpenFeign/feign
- Feign本身不支持Spring MVC的注解,它有一套自己的注解
- OpenFeign
- OpenFeign是Spring Cloud 在Feign的基础上支持了Spring MVC的注解,如@RequesMapping等等。
- OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,
- 并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。
fegin组件远程调用服务请求方发送了2次请求,先问nacos要地址,然后再请求
2、GateWay网关
动态上下线:发送请求需要知道商品服务的地址,如果商品服务器有123服务器,1号掉线后,还得改,所以需要网关动态地管理,他能从注册中心中实时地感知某个服务上线还是下线。【先通过网关,网关路由到服务提供者】
拦截:请求也要加上询问权限,看用户有没有权限访问这个请求,也需要网关。
网关是请求流量的入口,常用功能包括路由转发,权限校验,限流控制等。springcloud gateway取代了zuul网关。
三大核心概念:
- Route路由: 发一个请求给网关,网关要将请求路由到指定的服务。路由有id,目的地uri,断言的集合,匹配了断言就能到达指定位置,
- Predicate断言: 就是java里的断言函数,匹配请求里的任何信息,包括请求头等。根据请求头路由哪个服务
- Filter: 过滤器请求和响应都可以被修改。
客户端发请求给服务端。中间有网关。先交给映射器,如果能处理就交给handler处理,然后交给一系列filer,然后给指定的服务,再返回回来给客户端。
3、Spring Session
使用Spring Session解决session跨域跨服务存储读取问题需要进行一下步骤
pom文件导入
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
application.properties加入
spring.redis.host=192.168.56.10
spring.redis.port=6379
spring.session.store-type=redis
server.servlet.session.timeout=30m
启动类加上@EnableRedisHttpSession
配置子域session到父域并配置redis序列化器
@Configuration
public class GulimallSessionConfig {
// 配置子域session共享到父域上
@Bean
public CookieSerializer cookieSerializer(){
DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
cookieSerializer.setDomainName("gulimall.com");
cookieSerializer.setCookieName("GULISESSION");
return cookieSerializer;
}
// 配置Redis Json序列化器,若不配置,则需要每个vo上实现JDK的序列化器,过于繁琐
@Bean
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
return new GenericJackson2JsonRedisSerializer();
}
}
3.1、原理
Spring Session 原理首先从启动类上的注解开始说起
@EnableRedisHttpSession里面导入了 RedisHttpSessionConfiguration.class 的配置,这个配置首先给容器中添加了一个组件 RedisOperationsSessionRepository,
- 它的主要作用是:使用 Redis 操作 session,相当于是 session 的增删改查封装类;
- 这个配置还继承了 SpringHttpSessionConfiguration
- 这个类只要一构造起来,构造器就会初始化CookieSerializer,就是 cookie 的默认序列化
- 还初始化了一个监听器,来监听 服务器的停机,以及 session 的序列化、反序列化、等过程
- 还初始化了一个 SessionRepositoryFilter(session 存储过滤器)
- 这个过滤器底层实现了 Filter,相当于每个请求过来都必须经过 Filter 组件;
- 创建的时候,自动从容器中获取到了 SessionRepository(专门存 session 的仓库);
- 它里面重写了doFilterInternal,这就是 Spring Session 最核心的原理
- 这里面,首先将当前的sessionRepository(session 的操作类)放到当前请求共享的数据中
- 将原生的请求对象:请求、响应、当前上下文包装起来,这是一个典型的装饰者模式
- 然后又将原生的响应对象包装了起来
- filterChain 要放行的时候,它将包装之后的对象应用到后面的整个执行链
- 后面的执行链(Controller)中要使用 session 的时候,以前是从原生的HttpServletRequest中获取,而这里的HttpServletRequest已经被包装成了 SessionRepositoryRequestWrapper,它底层是从SessionRepository中获取的 session,而这个 SessionRepository正是我们一开始注入的RedisOperationsSessionRepository
所以它的核心原理就是装饰者模式,SessionRepositoryRequestWrapper规定怎么获取 session,最终就怎么获取。
而SessionRepositoryRequestWrapper就是把原生servlet对session的一套操作自己又重新实现了一遍,加上了自己的功能。
Sping Session 模拟了 session 的完整功能,每次请求都会刷新redis中的过期时间。只要浏览器不关,就可以为 session 自动续期,如果浏览器关了,就会正常走 redis 的过期时间
4、Spring Cache
- 每一个需要缓存的数据我们都来指定要放到那个名字的缓存。【缓存的分区(按照业务类型分)】 代表当前方法的结果需要缓存,如果缓存中有,方法都不用调用,如果缓存中没有,会调用方法。最后将方法的结果放入缓存
- 默认行为
- 自定义操作:
- 指定生成缓存的key:key属性指定,接收一个Spel
- 指定缓存的数据的存活时间:配置文档中修改存活时间
- 将数据保存为json格式
Spirng-Cache的不足
- 读模式:
- 缓存穿透:查询一个null数据。解决:缓存空数据:cache-null-values=true
- 缓存击穿:大量并发进来同时查询一个正好过期的数据。解决:加锁,默认无锁,sync=true
- 缓存雪崩:大量的key同时过期。解决:加随机时间。加上过期时间 spring.cache.redis.time-to-live=3600000
- 写模式:(缓存与数据库一致)
- 写入加锁
- 引入canal,感受到mysql的变化
- 读多写多,直接去数据库查询就行
- 总结:
- 常规数据(读多写少,即时性,一致性要求不高的数据,完全可以使用spring-cache)
- 特殊数据:特殊设计
[