目录
1、RPC
RPC(Remote Procedure Call)—远程过程调用 ,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发分布式程序就像开发本地程序一样简单。
RPC采用客户端(服务调用方)/服务器端(服务提供方)模式, 都运行在自己的JVM中。客户端只需要引入要使用的接口,接口的实现和运行都在服务器端。RPC主要依赖的技术包括序列化、反序列化和数据传输协议,这是一种定义与实现相分离的设计。
目前Java使用比较多的RPC方案主要有RMI(JDK自带)、Hessian、Dubbo以及Thrift等。
注意: RPC主要指内部服务之间的调用,RESTful也可以用于内部服务之间的调用,但其主要用途还在于外部系统提供服务,因此没有将其包含在本知识点内。
常见RPC框架:
- RMI(JDK自带)
- Dubbo:Dubbo是 阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成;
- Hessian:Hessian是一个轻量级的remotingonhttp工具,使用简单的方法提供了RMI的功能。 相比WebService,Hessian更简单、快捷。采用的是二进制RPC协议,因为采用的是二进制协议,所以它很适合于发送二进制数据;
- Thrift:Apache Thrift是Facebook开源的跨语言的RPC通信框架,目前已经捐献给Apache基金会管理,由于其跨语言特性和出色的性能,在很多互联网公司得到应用,有能力的公司甚至会基于thrift研发一套分布式服务框架,增加诸如服务注册、服务发现等功能;
功能 | Hessian | Montan | rpcx | gRPC | Thrift | Dubbo | Dubbox | SpringCloud |
---|---|---|---|---|---|---|---|---|
开发语言 | 跨语言 | Java | Go | 跨语言 | 跨语言 | Java | Java | Java |
分布式(服务治理) | × | √ | √ | × | × | √ | √ | √ |
多序列化框架支持 | hessian | √(支持hessian2,json,可扩展) | √ | ×(只支持protobuf) | ×(thrift格式) | √ | √ | √ |
多种注册中心 | × | √ | √ | × | × | √ | √ | √ |
管理中心 | × | √ | √ | × | × | √ | √ | √ |
跨编程语言 | √ | ×(支持php和C server) | × | √ | √ | × | × | × |
支持REST | × | × | × | × | × | × | √ | √ |
关注度 | 低 | 中 | 低 | 中 | 中 | 中 | 高 | 中 |
上手难度 | 低 | 低 | 中 | 中 | 中 | 低 | 低 | 中 |
运维成本 | 低 | 中 | 中 | 中 | 低 | 中 | 中 | 中 |
开源机构 | Caucho | Apache | Apache | Alibaba | Dangdang | Apache |
2、MQ
消息中间件,也可以叫做中央消息队列或者是消息队列(区别于本地消息队列,本地消息队列指的是JVM内的队列实现),是一种独立的队列系统,消息中间件经常用来解决内部服务之间的 异步调用问题 。请求服务方把请求队列放到队列中即可返回,然后等待服务提供方去队列中获取请求进行处理,之后通过回调等机制把结果返回给请求服务方。
消息产品 | Kafka | RocketMQ | RabbitMQ |
---|---|---|---|
设计定位 | 系统间数据流管道,实时数据处理。例如:常规的消息系统 | 非日志可靠消息传输。例如:订单、交易、充值、流计算、消息推送、流式处理、binglog分发等 | 可靠消息传输,类似RocketMQ |
成熟度 | 日志领域成熟 | 成熟 | 成熟 |
客户端SDK | Java, Scala, Go etc | Java, C++, Go | Java, .NET, C++ etc |
持久化方式 | 磁盘文件 | 磁盘文件 | 内存、文件 |
集群管理 | zk | name server | - |
选主方式 | 从ISR中自动选一个leader | 不支持自动选主,通过设置brokername,brokerid实现,brokername相同,brokerid=0为master,其他为slaver | 最早加入集群的broker |
主从切换 | 自动切换,N个副本,允许N-1个失败,master失效后自动从is中选一个主 | 不支持自动切换,master失效以后不能向master发送消息,consumer大概30s(默认)可以感知此事件,此后从slaver消费,如果master无法恢复,异步复制时可能出现消息丢失 | 自动切换,最早加入集群的slaver会成为master,因为新加入的slaver不会同步master之前的数据,所以可能会出现部分数据丢失 |
数据可靠性 | 很好,支持producer单条发送、同步刷盘、同步复制、但这场景下性能明显下降 | 很好,producer单条发送,broker支持同步刷盘、异步刷盘,同步双写,异步复制 | 好,producer支持同步/异步ack,支持队列数据持久化,镜像模式中支持主从同步 |
消息写入 性能 | 非常好,每条10KB测试,百万TPS | 很好,每条10KB测试,单机单broker7wTPS,单机3broker12wTPS | RAM为RocketMQ的1/2 DISK为RAM的1/3 |
性能稳定性 | 队列/分区多时性能不稳定,明显下降,消息堆积时性能稳定 | 队列较多,消息堆积时性能稳定 | 消息堆积时,性能不稳定,明显下降 |
单机支持的队列数 | 单机超过64个队列/分区,load会发生明显的飙高,队列越多,load越高,发消息响应时间边长 | 单机支持最高5万个队列,load不会发生明显变化 | 依赖于内存 |
堆积能力 | 非常好,消息存储在log中,每个分区一个log文件 | 非常好,所有消息存储在同一个commit log中 | 一般,生产者,消费者正常时,性能稳定 |
复制备份 | 消息先写入leader的log中,follower从leader中pull,pull到数据以后先ack leader,然后写入log中,ISR中维护与leader同步的队列,落后太多的follower会删掉 | 同步双写,异步复制:slaver启动线程从master中拉数据 | 普通模式下不复制,镜像模式下:消息先到master,然后写到slaver上,入集群之前的消息不会被复制到新的slaver上 |
消息投递实时性 | ms级别,具体由consumer轮询间隔时间决定 | ms级别,支持pull,push两种模式 | ms级别 |
顺序消费 | 支持,但是一台broker宕机后,就会产生消息乱序 | 支持,在顺序消息场景小,消费失败时消费队列会暂停 | 支持,但是如果有一个消费失败,此消息会乱序 |
定时消息 | 不支持 | 开源版本仅支持定时Level | 不支持 |
事务消息 | 不支持 | 支持 | 不支持 |
Broker消息过滤 | 不支持 | 支持,通过tag过滤,类似于子topic | 不支持 |
消息查询 | 不支持 | 支持,根据MessageId、MessageKey查询, | 不支持 |
消费失败重试 | 不支持,offset存储在consumer中,无法保证,0.8.2版本后支持将offset存储在zk中 | 支持,offset存储在broker中 | 支持 |
发送端负载均衡 | 支持 | 支持 | 需要单独loadbalancer 支持 |
消费并行度 | 消费并行度和分区数一致 | 顺序消费:消费并行度和分区数一致 乱序消费:消费服务器的消费线程数之和 | 镜像模式下其实也是从master消费 |
消费方式 | consumer pull | consumer pull / broker push | broker push |
批量发送 | 支持,默认producer缓存、压缩、然后批量发送 | 不支持 | 不支持 |
消息清理 | 指定文件保存时间,过期删除 | 指定文件保存时间,过期删除 | 可用内存少于80%(默认)出发gc,gc时找到相交的两个文件,合并right文件到left |
访问权限控制 | 无 | 无 | 类似数据库一样,需要配置用户名密码 |
3、MQ优点:
- 解耦 : 一个业务的非核心流程需要依赖其他系统,但结果并不重要,有通知即可。
- 最终一致性 : 指的是两个系统的状态保持一致,可以有一定的延迟,只要最终达到一致性即可。经常用在解决分布式事务上。
- 广播 : 消息队列最基本的功能。生产者只负责生产消息,订阅者接收消息。
- 错峰和流控
4、引入的问题:
- 系统可用性降低:系统引入的外部依赖越多,越容易挂掉。
- 系统复杂度提高:重复消费、消息丢失、消息顺序
-
一致性问题:A 系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是 BCD 三个系统那里,BD 两个系统写库成功了,结果 C 系统写库失败了,你这数据就不一致了。