1、Ribbon、Fegin和OpenFegin

  1. Ribbon
    1. Ribbon是 Netflix开源的基于HTTP和TCP等协议负载均衡组件
    2. Ribbon 可以用来做客户端负载均衡,调用注册中心的服务
    3. Ribbon的使用需要代码里手动调用目标服务,请参考官方示例:https://github.com/Netflix/ribbon
  2. Feign
    1. Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客户端
    2. Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。
    3. Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务
    4. Feign支持的注解和用法请参考官方文档:https://github.com/OpenFeign/feign
    5. Feign本身不支持Spring MVC的注解,它有一套自己的注解
  3. OpenFeign
    1. OpenFeign是Spring Cloud 在Feign的基础上支持了Spring MVC的注解,如@RequesMapping等等。
    2. OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,
    3. 并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。

fegin组件远程调用服务请求方发送了2次请求,先问nacos要地址,然后再请求

2、GateWay网关

动态上下线:发送请求需要知道商品服务的地址,如果商品服务器有123服务器,1号掉线后,还得改,所以需要网关动态地管理,他能从注册中心中实时地感知某个服务上线还是下线。【先通过网关,网关路由到服务提供者】
拦截:请求也要加上询问权限,看用户有没有权限访问这个请求,也需要网关。
网关是请求流量的入口,常用功能包括路由转发,权限校验,限流控制等。springcloud gateway取代了zuul网关。
三大核心概念:

  1. Route路由: 发一个请求给网关,网关要将请求路由到指定的服务。路由有id,目的地uri,断言的集合,匹配了断言就能到达指定位置,
  2. Predicate断言: 就是java里的断言函数,匹配请求里的任何信息,包括请求头等。根据请求头路由哪个服务
  3. Filter: 过滤器请求和响应都可以被修改。

客户端发请求给服务端。中间有网关。先交给映射器,如果能处理就交给handler处理,然后交给一系列filer,然后给指定的服务,再返回回来给客户端。
image.png

3、Spring Session

使用Spring Session解决session跨域跨服务存储读取问题需要进行一下步骤

  1. pom文件导入

    1. <dependency>
    2. <groupId>org.springframework.session</groupId>
    3. <artifactId>spring-session-data-redis</artifactId>
    4. </dependency>
  2. application.properties加入

    1. spring.redis.host=192.168.56.10
    2. spring.redis.port=6379
    3. spring.session.store-type=redis
    4. server.servlet.session.timeout=30m
  3. 启动类加上@EnableRedisHttpSession

  4. 配置子域session到父域并配置redis序列化器

    1. @Configuration
    2. public class GulimallSessionConfig {
    3. // 配置子域session共享到父域上
    4. @Bean
    5. public CookieSerializer cookieSerializer(){
    6. DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
    7. cookieSerializer.setDomainName("gulimall.com");
    8. cookieSerializer.setCookieName("GULISESSION");
    9. return cookieSerializer;
    10. }
    11. // 配置Redis Json序列化器,若不配置,则需要每个vo上实现JDK的序列化器,过于繁琐
    12. @Bean
    13. public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
    14. return new GenericJackson2JsonRedisSerializer();
    15. }
    16. }

    3.1、原理

    Spring Session 原理首先从启动类上的注解开始说起
    @EnableRedisHttpSession里面导入了 RedisHttpSessionConfiguration.class 的配置,

  5. 这个配置首先给容器中添加了一个组件 RedisOperationsSessionRepository,

    1. 它的主要作用是:使用 Redis 操作 session,相当于是 session 的增删改查封装类;
  6. 这个配置还继承了 SpringHttpSessionConfiguration
    1. 这个类只要一构造起来,构造器就会初始化CookieSerializer,就是 cookie 的默认序列化
    2. 还初始化了一个监听器,来监听 服务器的停机,以及 session 的序列化、反序列化、等过程
    3. 还初始化了一个 SessionRepositoryFilter(session 存储过滤器)
      1. 这个过滤器底层实现了 Filter,相当于每个请求过来都必须经过 Filter 组件;
      2. 创建的时候,自动从容器中获取到了 SessionRepository(专门存 session 的仓库);
      3. 它里面重写了doFilterInternal,这就是 Spring Session 最核心的原理

image.png

  1. 这里面,首先将当前的sessionRepository(session 的操作类)放到当前请求共享的数据中
  2. 将原生的请求对象:请求、响应、当前上下文包装起来,这是一个典型的装饰者模式
  3. 然后又将原生的响应对象包装了起来
  4. filterChain 要放行的时候,它将包装之后的对象应用到后面的整个执行链
  5. 后面的执行链(Controller)中要使用 session 的时候,以前是从原生的HttpServletRequest中获取,而这里的HttpServletRequest已经被包装成了 SessionRepositoryRequestWrapper,它底层是从SessionRepository中获取的 session,而这个 SessionRepository正是我们一开始注入的RedisOperationsSessionRepository

所以它的核心原理就是装饰者模式,SessionRepositoryRequestWrapper规定怎么获取 session,最终就怎么获取。
而SessionRepositoryRequestWrapper就是把原生servlet对session的一套操作自己又重新实现了一遍,加上了自己的功能。
Sping Session 模拟了 session 的完整功能,每次请求都会刷新redis中的过期时间。只要浏览器不关,就可以为 session 自动续期,如果浏览器关了,就会正常走 redis 的过期时间

4、Spring Cache

image.png

  1. 每一个需要缓存的数据我们都来指定要放到那个名字的缓存。【缓存的分区(按照业务类型分)】 代表当前方法的结果需要缓存,如果缓存中有,方法都不用调用,如果缓存中没有,会调用方法。最后将方法的结果放入缓存
  2. 默认行为
    1. 如果缓存中有,方法不再调用
    2. key是默认生成的:缓存的名字::SimpleKey::
    3. 缓存的value值,默认使用jdk序列化机制,将序列化的数据存到redis中
    4. 默认过期时间是 -1:
  3. 自定义操作:
    1. 指定生成缓存的key:key属性指定,接收一个Spel
    2. 指定缓存的数据的存活时间:配置文档中修改存活时间
    3. 将数据保存为json格式

Spirng-Cache的不足

  1. 读模式:
    1. 缓存穿透:查询一个null数据。解决:缓存空数据:cache-null-values=true
    2. 缓存击穿:大量并发进来同时查询一个正好过期的数据。解决:加锁,默认无锁,sync=true
    3. 缓存雪崩:大量的key同时过期。解决:加随机时间。加上过期时间 spring.cache.redis.time-to-live=3600000
  2. 写模式:(缓存与数据库一致)
    1. 写入加锁
    2. 引入canal,感受到mysql的变化
    3. 读多写多,直接去数据库查询就行
  3. 总结:
    1. 常规数据(读多写少,即时性,一致性要求不高的数据,完全可以使用spring-cache)
    2. 特殊数据:特殊设计

[

](https://blog.csdn.net/zimou5581/article/details/89949852)