目录
- 为什么要进行系统拆分?如何进行系统拆分?拆分后不用dubbo可以吗?dubbo和thrift有什么区别呢?
- 说一下的dubbo的工作原理?注册中心挂了可以继续通信吗?
- dubbo支持哪些序列化协议?说一下hessian的数据结构?PB知道吗?为什么PB的效率是最高的?
- dubbo负载均衡策略和高可用策略都有哪些?动态代理策略呢?
- dubbo的负载均衡策略:
- dubbo的集群容错策略
- Dubbo的动态代理是啥
- dubbo的spi思想是什么?
- 如何基于dubbo进行服务治理、服务降级、失败重试以及超时重试?
- 分布式服务接口的幂等性如何设计(比如不能重复扣款)?
- 分布式服务接口请求的顺序性如何保证?
- 如何自己设计一个类似dubbo的rpc框架?
- 使用redis如何设计分布式锁?使用zk来设计分布式锁可以吗?这两种分布式锁的实现方式哪种效率比较高?
- 分布式事务了解吗?你们如何解决分布式事务问题的?TCC如果出现网络连不通怎么办?XA的一致性如何保证?
- 集群部署时的分布式session如何实现?
- zookeeper有哪些应用场景
- 如何设计一个高并发的系统?
为什么要进行系统拆分?如何进行系统拆分?拆分后不用dubbo可以吗?dubbo和thrift有什么区别呢?
如果不拆分,一个大的项目可能有数十万行代码,多人维护,很容易出现代码冲突,效率低下,而且每次更改的话都需要重启项目,重新测试,很麻烦。
如果拆分成多个应用的话,每个人负责自己的那块,然后只要保证交互的接口无误即可,效率高而且事务抄。我们只需要关注分布式的相关问题即可。
可以不用dubbo,大不了各个系统各自维护一个记录关联系统接口地址的配置文件,用接口来保持通信。不过会比较痛苦,比如接口重连,负载均衡等等。
dubbo做的就是代理这个请求,然后跟远程机器通信,负载均衡,超时重连等等。
说一下的dubbo的工作原理?注册中心挂了可以继续通信吗?
工作步骤:
1)provider向注册中心去注册
2)consummer从注册中心去订阅服务,注册中心会通知consummer注册好服务
3)consummer调用provider
4)consummer和provider都异步的去通知监控中心
挂了依然可以重新通信,因为初始化的时候,消费者会把提供者的地址等信息拉取到本地缓存,所以注册中心挂了依然可以继续通信。
dubbo支持哪些序列化协议?说一下hessian的数据结构?PB知道吗?为什么PB的效率是最高的?
dubbo协议:默认走的就是这个,单一长连接,nio异步通信,基于hessian作为序列化的协议
适用的场景是传输量小(100kb以内)并发量高。
rmi协议:走java的二进制序列化,多个短连接,适用于文件传输,用的比较少,消费者和提供者差不多
hessian:走hessian序列化协议,多个短连接,适用于文件传输,用的比较少,提供者比消费者多
http协议:走json序列化
webservice:走soap文本序列化
dubbo负载均衡策略和高可用策略都有哪些?动态代理策略呢?
dubbo工作原理:服务注册,注册中心,消费者,代理通信,负载均衡
网络通信序列化:dubbo协议,长连接,nio,hessian序列化
负载均衡策略,集群容错机制
dubbo的负载均衡策略:
1)random LoadBalance:默认是这种,可以对provider不同实例来设置权重,根据权重来负载均衡,权重大的分配的流量越高。最常用
2)roundrobin LoadBalance:默认均匀地把流量打到各个机器上,但是如果机器性能不一样,很容易导致某个性能差的机器负载过高
3)leastactive LoadBalance
自动感知,如果有个机器的性能越差,那么接受到的请求越少,越不活跃,此时会给不活跃性能差的机器更少的请求。
4)consistanthash LoadBalance
一致性hash算法,相同参数请求一定分发到一个provider,provider挂掉,会基于虚拟节点均匀分配剩余流量,如果需要不是随机负载的话,是一类请求都落到一个节点,那么就用这个策略
dubbo的集群容错策略
1)failover:失败自动切换,自动重试其他机器,默认,常见于读操作
2)failfast:一次调用失败立即失败,常见于写操作
3)failsafe:出现异常忽略,用于不重要接口的调用,比如记录日志
4)failback:失败后自动记录请求,然后定时重发,比较适合写消息队列这种
5)forking:并行调用多个provider,只要有一个成功就立即返回
6)broadcast:逐个调用所有的provider
Dubbo的动态代理是啥
dubbo的动态代理是默认使用javassist动态字节码生成的,创建代理类
但是可以利用spi扩展机制来配置自己的动态代理策略
dubbo的spi思想是什么?
service provider interface
有一个接口,接口有三个实现类,在系统运行期间对这个接口该怎么选择哪个实现类呢?这就需要spi,需要根据指定的配置或者默认的配置,去找对应的实现类加载进来,然后用这个实现类的实例对象。
如何基于dubbo进行服务治理、服务降级、失败重试以及超时重试?
服务根治:
生成调用链:
因为大型的分布式服务,由大量的服务组成,所以首先需要用dubbo,对各个服务之间的调用记录下来,自动将各个服务之间的依赖关系和调用链路生成出来,做成一张图,方便查阅定位。
服务访问压力和时长统计:
自动统计各个接口和服务之间调用次数和访问延迟。第一是看粒度,即调用次数,第二是完成一次请求全链路各个服务的请求延迟是多少,方便我们扩容和优化。
服务分层,调用链路的失败和预警,每个服务可用性的监控。
服务降级:
A调用B,B挂了,A重试了几次都不行,直接降级调用一个备用的逻辑,给用户响应
失败重试以及超时重试
消费者调用提供者失败,重试
<dubbo:reference id=“xxxx” interface=“xx” check=“true” async=“false” retries=“3” timeout=“2000”/>
分布式服务接口的幂等性如何设计(比如不能重复扣款)?
每个请求必须有一个唯一的标识
每次处理完必须有一个标识代表处理过了
如果是新增流水的话,先进行唯一主键的判断
分布式服务接口请求的顺序性如何保证?
尽量在服务中合并,如果是在不行的话用dubbo的一致性hash策略,把某几个服务都落到一个机器上,然后请求丢到内存队列中强制排队。可能会导致热点问题请求比较多。
如何自己设计一个类似dubbo的rpc框架?
首先我们得要注册中心去注册服务吧,那么用zookeeper来搞
然后消费者得去注册中心拿服务吧,每台服务可能存在多台机器
接着呢,消费者要去发起请求,基于动态代理,面向接口获取一个接口的动态代理,这个代理就是接口再本地的一个代理,根据这个代理找到服务对应的机器地址
然后要找哪个机器发送请求,那就用到负载均衡算法了,我们这边就搞个最简单的随机轮询
找到机器之后,要发请求了,这边就涉及到序列化和反序列化了,这边可以用hessian
然后服务器那边也一样,针对自己服务生成一个动态代理,监听,收到请求之后调用对应的服务代码。
使用redis如何设计分布式锁?使用zk来设计分布式锁可以吗?这两种分布式锁的实现方式哪种效率比较高?
利用redis的setnx nx就是不存在才会设置成功,那个进程可以set成功就可以操作共享变量,用完即删。
zk的话利用有序节点,多个进程去基于某个目录创建有序节点,然后最小的节点可以操作共享变量,此时其他节点监听最小的节点,用完就删。
redis比较差,redis你得不断地setnx尝试获取锁,而zk是监听器。
分布式事务了解吗?你们如何解决分布式事务问题的?TCC如果出现网络连不通怎么办?XA的一致性如何保证?
2PC: 事务管理器,先轮询所有数据库是否准备好,都反馈ok之后正式提交事务,如果有任何数据库不ok,则回滚。
TCC:try confirm,cancel 补偿的概念
try:对各个服务器资源做检测以及对资源进行锁定和预留
confirm:这个阶段是在各个服务器中执行实际的操作
cancel:如果任何一个服务的业务方法执行出错,那么这边就要进行补偿,就是执行回滚。
类似于银行转账
可靠性消息最终一致性
大概的意思就是:
1)A系统先发送一个prepared消息到mq,如果这个prepared消息发送失败那么就直接取消操作别执行了
2)如果这个消息发送成功过了,那么接着执行本地事务,如果成功就告诉mq发送确认消息,如果失败就告诉mq回滚消息
3)如果发送了确认消息,那么此时B系统会接收到确认消息,然后执行本地的事务
4)mq会自动定时轮询所有prepared消息回调你的接口,问你,这个消息是不是本地事务处理失败了,所有没发送确认消息?那是继续重试还是回滚?一般来说这里你就可以查下数据库看之前本地事务是否执行,如果回滚了,那么这里也回滚吧。这个就是避免可能本地事务执行成功了,别确认消息发送失败了。
5)这个方案里,要是系统B的事务失败了咋办?重试咯,自动不断重试直到成功,如果实在是不行,要么就是针对重要的资金类业务进行回滚,比如B系统本地回滚后,想办法通知系统A也回滚;或者是发送报警由人工来手工回滚和补偿
最大努力通知型
1)系统A本地事务执行完之后,发送个消息到MQ
2)这里会有个专门消费MQ的最大努力通知服务,这个服务会消费MQ然后写入数据库中记录下来,或者是放入个内存队列也可以,接着调用系统B的接口
3)要是系统B执行成功就ok了;要是系统B执行失败了,那么最大努力通知服务就定时尝试重新调用系统B,反复N次,最后还是不行就放弃
集群部署时的分布式session如何实现?
tomcat+redis,用RedisSessionManager把存储的seesion放到redis中。配置一下就好了。
springsession+redis springSessionRepositoryFilter来把session放到redis中
zookeeper有哪些应用场景
分布式协调:A发送了消息给MQ,然后B消费了这个消息,A想知道B的处理接口,这边就可以这样搞,
A发送完消息之后在ZK上监听某个值,然后B改完之后去ZK上修改这个值,这样A就可以收到通知。
分布式锁:zk的有序节点,每次都监听最小值,然后领取到的进程才能操作共享变量
注册中心:比如dubbo的注册中心
HA高可用:利用zk的master选举来做主备切换,master选举。
如何设计一个高并发的系统?
首先考虑系统拆分,将一个系统拆分成多个仔细同,可以用dubbo来搞,然后每个系统连一个数据库,多库来抗高并发。
然后应对高并发,肯定是要上缓存的,大部分的高并发场景都是读多写少,我们可以考虑用redis来做缓存。
然后肯定是得上MQ的,大量的请求灌到MQ中,然后后面系统消费慢慢写,控制在数据库可以承载的范围内。mq还可以用来处理异步,提高并发性。
分库分表,读写分离,提高数据库抗高并发的压力
可能还需要加分布式搜索引擎es,这是天然的分布式,可以随便扩容。