前言
社招3年后端 工作时间长之后还是需要在场景和组件功能原理方面做更深的了解,以及对各种实现方式理念的学习理解.代码脱胎于理念. 项目介绍30MIN.一共1H+;
1. 个人介绍
2. 我们Rabbitmq和Kafka选型的原因.使用Kafka替代Rabbitmq是否可行
这里如何结合业务场景进行选型的思考比较重要,而不是为了使用而用反而会增加技术债务.我说的原因并没有让面试官觉得必须要用Rabbitmq(但其实是Rabbitmq先用后用的Kafka,而且是基于实现Websocket实时通信引用).
- 拓展消费能力,Rabbitmq上增加消费者进行并发消费比Kafka方便,Kafka需要预先预留多个分区来防止消费能力跟不上生产能力而在同一消费组增加消费者的情况
- Rabbitmq开箱即用,不需要额外的注册管理中心并且支持多租户模式,可以不同业务使用不同vhost,增加小项目的资源利用率.并且还有管理插件进行可视化操作
- 支持多种协议拓展插件,例如我们实时通信Spring-Websocket使用的STOMP文本协议(我们主要使用实时通信引入Rabbitmq,然后顺便做了其他服务业务通信的解耦.)
- Rabbitmq多用于金融场景,其安全可靠性(消费确认+死信队列)和实时性(内存存储,主动推送)更高一点(提了低延时,但是应该面试官觉得这个不是作为kafka不能用在业务通信上的理由).并且也可以设置消费者未消费确认阈值,缓解消费者压力
- Rabbitmq消费路由模式让消息分发更加灵活与自由(我们系统数据中台上游业务系统是可拓展的,对不同数据消息处理方式可能不一样所以更希望能有更灵活的消息路由分发方式)
- 支持消息有效期+延时队列
3. Websocket应用为多节点时,同一用户保证只有一条连接
- 维护连接记录 : 维护统一的节点记录,当断开连接则将该用户从连接记录中去除.用户连接时则先判断记录,如果有则断开之前的连接/拒绝当前连接
- 消息统一发送 : 需向多个节点发送消息时,将消息发送至消息队列中,再广播至各个应用上,由应用进行发送消息
4. 微服务实现方式/需要哪方面组件/服务间通信治理的理论了解
服务治理 : 配置中心、注册发现、负载均衡、熔断降级、限流和重试、服务通信、链路追踪
5. 链路追踪了解以及实现原理
讲了当前比较热门的链路追踪组件 : skywalking、zipkin、pinpoint、cat
实现原理,只提了埋点(需加强学习).
参考: 各大厂分布式链路跟踪系统架构对比、分布式链路追踪技术对比
6. ConcurrentMap1.7和1.8的了解
- 1.7由Segment+数组+链表+可重入锁(对桶加锁)
- 1.8由数组+链表+红黑树+cas写入+sync冲突时写入
- 加锁粒度与方式变更; 插入方式变更(put);
- Guide-ConcurrentHashMap
7. 线程池核心参数
8. Rabbitmq有没有对底层原理深入了解
- 没明白问的底层原理说的是什么.面试官说比如集群模式实现原理、消息确认机制实现原理、工作方式之类的(可能是让介绍对应的概念或者AMQP协议?)
- Rabbitmq入门级基础概念原理介绍
9. volitale关键字作用
- 多线程间变量可见性
- 增加内存屏障,防止CPU进行指令重排序,避免因重排序导致的读写不一致问题
10. syncronacize关键字1.6优化了那些
- 优化前提 : syncronacize为重量锁是因为当出现锁竞争的情况下会导致线程出现唤醒和阻塞的情况,而Java线程是由系统内核线程映射而来,唤醒和阻塞线程会导致系统由用户态转换为内核态,进行唤醒和阻塞线程操作.所以比较耗费系统资源
- 优化目的 : 减少/减缓当出现锁竞争时而出现的线程阻塞操作
- 优化方式 : 自旋+锁升级
- 自旋+自适应自旋 : 当线程发现目标对象已经被加锁时,会先默认自旋一定次数,获取对象锁,
当自旋完毕后未获取到锁才会进入阻塞状态
.自适应自旋是依据上次该对象线程自旋获取锁情况,来决定本次自旋次数.- 锁升级 : 1.
一个对象首次被线程加锁时会先将该线程ID加到对象头中,置为偏向锁(无锁竞争时),当同一线程再次获取锁则可重入,无需再释放+加锁.
2.当出现锁竞争并且该对象头已是偏向锁时,会将该锁状态改为轻量级锁,当自旋执行CAS加锁一定次数未获取到对象锁或者有另外线程也尝试获取该锁则会将该锁升级为重量级锁(并加入该对象的阻塞队列中)
3.当线程解锁会以CAS方式替换对象头,当替换失败发现锁是重量级锁,则会去唤醒阻塞队列中的线程
- 锁升级配置 : 偏向锁升级轻量级锁会发生STW(锁升级会等到安全点,此时其他线程是被阻塞的),所以当系统锁竞争严重时最好关闭偏向锁(
-XX:-UseBiasedLocking
). 当系统线程加锁执行时间比较长则也尽量关闭自旋,防止忙等待占用CPU(-XX:-UseSpinning
),自旋锁适用于持有锁时间比较短的线程- 参考: 听说
synchronized
性能不行,是真的吗?、性能优化-偏向锁