杂项02

nacos单点启动

默认集群方式启动,指定参数单点启动
startup.cmd -m standalone

技术专题

亮点: 拦截器, 自定义注解, AOP, 分页查询, 单点登录, starter类(项目虽小,功能俱全)

  • 配置两个拦截器, 第一个全部拦截用于刷新token;第二个部分拦截用于拦截未登录用户拦截器
  • AOP + 自定义注解 + 日志记录
  • 统一异常处理 + 常量定义 + 使用自定义异常自定义结果类,链式调用优雅 + 自定义工具类
  • 分页查询
  • starter类
  • JWT + Redis
    token令牌的登录方式,访问认证速度快,session共享,安全性
    Redis做了令牌和用户信息的对应管理,进一步增加了安全性,登录用户做了缓存,过期时间踢掉线
  • threadLocal使用了保存用户信息,请求的线程之内可以随时获取登录用户,做了线程隔离
  • 使用完threadLocal之后做了value删除,防止内存泄漏
  • 线程池,面试7个核心参数(对当前主业务流程 无影响的操作,放入线程池执行), 登录时,记录日志,不能因为日志功能影响登录主业务流程应该放入线程池, 多线程技术
  • 权限系统 + 单点登录
  • 使用ThreadLocal保存用户信息,拦截完成之后删除value值
  • session存储敏感信息问题, 转成UserDTO对象, 同时可以节省内存占用

自定义starter

它允许您将一组相关的功能、配置和依赖项封装到一个可重用的模块中,以便在多个项目中共享和使用。



AOP

AOP理解

AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。

AOP是一种编程范式,旨在将横切关注点(cross-cutting concerns)从应用程序的主要逻辑中分离出来,以提高代码的可维护性和可重用性。

Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么 Spring AOP 会使用 JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 Cglib 生成一个被代理对象的子类来作为代理;


Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。

Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。AspectJ 相比于 Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单,

image-20230914200259248

切面

@Aspect

切入点

@Pointcut定义要拦截哪些类的哪些方法;

切入点的匹配规则:

image-20230913213012501

通知

定义了拦截之后方法要做什么;

前置通知@Before

  • 声明前置通知, 并将通知应用到指定的切入点上
  • 目标类的方法执行前, 执行该通知

返回通知@AfterReturning

  • 声明返回通知, 并将通知应用到指定的切入点上
  • 目标类的方法在无异常执行后, 执行该通知

最终通知@After

  • 声明最终通知, 并将通知应用到指定的切入点上
  • 目标类的方法在执行后, 执行该通知(有异常和无异常最终都会执行)

异常通知@AfterThrowing

  • 声明异常通知, 并将通知应用到指定的切入点上
  • 目标类的方法在执行异常时, 执行该通知

环绕通知@Around

  • 声明环绕通知, 并将通知应用到指定的切入点上
  • 目标类的方法执行前后, 都可通过环绕通知定义相应的处理
  • 需要通过显示调用的方法, 否则无法访问指定方法

SpringCache

常用注解

只支持String, 支持单表,不支持多表; 多表只能用RedisTemplate

  • @CacheConfig:

    @CacheConfig(cacheNames = {“user”})

    类级别的注解, 统一该类的所有缓存都是“user::”为前缀

  • @Cacheable
    方法级注解, 用于将方法的结果redis缓存起来,
    例如如果select方法被调用,先从缓存中读取数据,如果没有找到数据,再执行方法体进行sql查询,最后把返回值添加到缓存中,且是同步操作
    缓存中有直接用,不用执行方法体了

  • @CacheEvict
    方法级注解, 用于删除缓存
    先执行方法体,再根据参数执行删除缓存
    @CacheEvict(value = "myCache", key = "#id")用于清除名为 "myCache" 的缓存中键为 id 的缓存条目。

  • @CachePut
    方法级注解, 用于更新缓存, 不会先查redis, 直接执行方法体, 再更新缓存

  1. springCache的注解是将方法的返回值进行缓存, 所以有时候会缓存一些不必要的数据
  2. 缓存是缓存在spring容器存放在服务器的, 占用服务器内存, 会给服务器造成过大压力,
  3. 那么我们可以配置将缓存在redis中, 在yml文件中配置指定redis, 然后可以写一个配置类配置一些不同方法的过期时间, 重写为json序列化器等
  4. 缓存的值默认是序列化的(io流的序列化), 所以返回的结果类需要实现序列化Serializable,有时候会忘记(重写为json之后不需要)

Redisson分布式

setnx

集群模式或分布式系统, 加锁还是会出现并发问题, 需要使用分布式锁

因为每个服务都是一个单独的JVM维护一个锁监视器

消息中间件篇

4.1消息队列

4.2RabbitMQ

死信交换机和延迟队列

消息堆积

  • 增加更多的消费者,提高消费速度
  • 开启线程池加快消息处理速度
  • 扩大队列容积

高可用

镜像集群
  • 镜像队列结构是一主多从,所有操作都是主节点完成,然后同步给镜像节点
  • 主节点宕机后,镜像节点会替代成新的主节点
仲裁队列
  • 如果有丢失数据采用仲裁队列解决,与镜像队列一样都是主从模式,支持主从同步,主从同步基于Raft协议强一致,只需要在声明队列的时候指定即可

4.3Kafka

如何保证消费的顺序性

一个topic的数据可能存储在不同的分区中,每个分区都有一个按照顺序的存储的偏移量,如果消费者关联了多个分区不能保证顺序性;

  • 发送消息时指定分区号
  • 发送消息时按照相同的业务设置相同的key

数据清理机制

Kafka存储结构
  • Kafka中的topic的数据存储在分区上,分区如果文件过大会分段存储segment
  • 每个分段都在磁盘上以索引和日志文件的形式存储
  • 分段能够减少单个文件内容的大小,查找数据方便,方便Kafka进行日志清理
日志清理策略
  • 根据消息的保留时间,当消息超过指定时间就会触发清理,默认168小时(7天)
  • 根据topic存储的数据大小,当topic所占的日志文件大小大于一定的阈值,则开始删除最久的消息(默认关闭)

高可用

  • 集群
  • 复制机制

高性能

  • 消息分区—不受单台服务器的限制,可以不受限的处理更多的数据
  • 顺序读写—磁盘顺序读写,提升读写效率
  • 页缓存—把磁盘中的数据缓存到内存中,直接对内存访问
  • 零拷贝—减少上下文切换及数据拷贝

Lock锁

posted @ 2024-03-13 14:39  好滴都  阅读(39)  评论(0)    收藏  举报