
分布式通信分布式系统的本质是多进程协作共同完成任务。要协作自然免不了通信这也是分布式通信技术要解决的核心问题。概述按照请求从外到内、从大到小的层次分布式通信涉及以下关键技术负载均衡把外部请求合理分配到集群内部的多个服务器API 网关作为系统入口聚合多个微服务调用服务注册与发现解决分布式系统内部服务如何感知彼此的问题服务间的远程调用(RPC)让不同机器上的服务像本地调用一样通信异步通信模式当同步直接通信难以承载时使用发布订阅或消息队列解耦而从通信模式上看主要分为三大类通信方式思想典型实现远程调用(RPC)千里眼:直接调用远程方法Dubbo、gRPC、RMI、Netty发布订阅送货上门:消息中心主动推送Kafka消息队列货物自取:消费者按需拉取RocketMQ、RabbitMQ、Kafka负载均衡什么是负载均衡分布式系统通过服务器集群提升整体处理性能——把同一个服务扩展到不同的机器上每次请求该服务时选其中一台服务器响应无论在哪台服务器上执行都能得到相同的响应。高性能集群的设计主要体现在请求分配上这种将请求按一定规则分配到不同服务器执行的过程叫作负载均衡完成负载均衡的组件叫作负载均衡器。负载均衡并非平均分配需要根据业务考虑策略(服务器负载、性能、业务类型)具体的分配规则就是负载均衡算法。负载均衡的分类以客户端请求应用服务器为例典型的负载均衡分为三层DNS 负载均衡DNS 服务器根据用户所在网络区域返回最近机房的 IP实现区域级别的负载均衡。优点是成本低、用户就近访问缺点是依赖 DNS 缓存刷新不及时且支持算法较少。硬件负载均衡如 F5 BIG-IP、NetScaler、Radware、Array。优点是支持算法多、并发高(百万级)、经过严格测试更稳定还具备防火墙、防 DoS 等安全功能缺点是贵业务发展到一定规模才会用到。软件负载均衡如 LVS、HAProxy、Nginx。配置简单、使用灵活、成本低可满足一般负载均衡需求。硬件负载均衡器 F5 的三大类功能多链路负载均衡同时接入多家 ISP(网络服务供应商)通过 INBOUND 解析请求、OUTBOUND 配合 NAT 源地址转换保证网络高可用。防火墙负载均衡通过交换机—防火墙—交换机的三明治架构在完成流量分发的同时维持用户会话完整性避免多防火墙拆分会话。服务器负载均衡对挂接的多个应用服务器做负载均衡支持健康检查、虚拟 IP(VIP)、按服务类型/端口/内容分流等。软件负载均衡软件负载均衡所在的代理层上连接入层(硬件负载均衡)下接应用服务器可实现反向代理、负载均衡、动态缓存、过滤等功能。反向代理与负载均衡Nginx 等反向代理可对外隔离、对内路由当某个服务(如订单服务)需要水平扩展时通过负载均衡在多个实例间分配请求。Nginx 的并发量计算示例worker_processes 2 # 双核 CPU worker_cpu_affinity 01 10 events { use epoll worker_connections 15000 # 单进程最大连接数 }最大并发量 ≈worker_processes × worker_connections 2 × 15000 30000。百万级并发的方案在代理层之上加入接入层(硬件 F5)由 F5 抗大流量再转给 Nginx。动态缓存与过滤把变化不频繁的数据放到代理层作为缓存降低回源频率。例如使用 Nginx Lua 脚本从 Redis 校验一些信息。负载均衡算法算法说明适用场景round-robin(轮询)默认算法,挨个请求上游服务器日常系统,服务器配置均匀weight(权重)按权重分配,资源好的机器承担更多服务器配置不均(如秒杀核心服务)IP-hash同一 IP 始终路由到同一上游需要 session 一致hash key对 key 取模路由服务器增减时 key 仍能找到原机器解决 IP-hash 在扩缩容时失准least_conn把请求转发给连接数较少的服务器请求处理时长差异较大round-robin 算法确实可以把请求均匀的分发给服务器但特殊场景下有可能某服务器分配的全是执行耗时长、任务量大的请求这时采用 least_conn 算法效果会更好。API 网关API 网关的定义网关(Gateway)最早用于描述网络设备——两个相互独立的局域网通过路由器通信中间的路由器就叫网关。在分布式系统中网关存在于客户端与微服务系统之间。API 网关在三个层面解决了门面问题业务层面客户端完成某个业务需要调用多个微服务网关把多个调用聚合成一个统一入口(类似门面模式 Facade)。系统层面系统 A 和系统 B 之间的 API 互调可由网关作为中介者。客户端层面根据不同客户端(iOS、Android、PC、小程序)提供不同的 API 网关屏蔽调用差异。由于 API 网关处在客户端与微服务系统的交界因此包括路由、负载均衡、限流、缓存、日志、发布等功能。API 网关的服务定位按服务对象可分为 5 类面向WebAPP的 API 网关(H5/网站前后端分离)面向MobileAPP的 API 网关(iOS/Android需做移动设备管理 MDM)面向合作伙伴的OpenAPI(考虑流量、安全、协议转换)企业内部可扩展 API(中台输出需关注边界划分、认证授权)(隐含)按客户端类型分层的多个 API 网关API 网关的技术原理协议转换不同协议通过通用协议(如 JSON)中转API 网关负责两端协议的翻译。链式处理采用责任链模式消息流过一系列过滤器。Netflix Zuul 就是。异步请求Zuul 1.x 一个线程处理一个请求IO 阻塞Zuul 2 引入异步把每个请求包装为事件由 CPU 内核维护监听器轮询通知时再处理提升吞吐量。API 网关和负载均衡器在路由层面是相通的在功能上可以互换。服务间的远程调用本地调用指同一进程内的函数调用远程调用是进程间函数调用是进程间通信(IPC)的一种方式。按进程是否部署在同一台机器可分两类本地过程调用 LPC同一台机器上的进程之间远程过程调用 RPC不同机器上的进程之间在分布式领域中远程调用主要指RPC关于 RPC 的内容选择合适的 RPC 已经总结过了包括 RPC 的组成WSDL、UDDI、注册中心等和历史Java 生态里 Netty 是最流行的网络通信框架。发布订阅模式什么是发布订阅发布订阅的思想随处可见报纸订阅作者将文章发布到报社(消息中心)用户向报社订阅自己感兴趣的报纸类型报社根据订阅信息送报纸。发布订阅三要素生产者(发布者)负责产生数据消费者(订阅者)向消息中心订阅感兴趣的消息消息中心存储发布数据并按订阅关系推送这种将数据送到消费者手里的行为就是送货上门。发布订阅 vs 点对点消息系统的两种典型模式模式一条消息能被多少消费者消费点对点 P2P仅一个消费者消费消费后消息中心不再存储发布订阅 Pub/Sub可被多个订阅同一主题的消费者消费KafkaKafka 是经典的发布订阅消息系统系统架构包括Producer、Broker、Consumer三部分新版本已无 ZookeeperProducer发布消息到 BrokerBroker消息中心本质是 Kafka 集群负责存储消息、管理订阅、推送数据Consumer订阅并消费消息关键概念主题(Topic)逻辑概念表示消息类型/数据类型分区(Partition)一个主题可划分成多个集合分布在不同 Broker 上消费组(Consumer Group)多个消费者的集合组内共同消费主题每个消息仅由组内一个消费者消费分区的两大好处实现负载均衡同一个主题的消息分布到多个分区/多个 Broker避免单点压力过大实现消息备份同一分区的内容可存储在多个 Broker保证系统高可靠消息过多时单个 Consumer 消费能力有限会导致 Broker 存储溢出而丢消息。Kafka 引入消费组解决这个问题——多个 Consumer 并行消费。发布订阅的关键特征系统解耦易于维护生产者只管发不知道订阅者数量订阅者只管订阅不知道生产者何时发布。两者互相独立单独维护。异步执行避免高负载消息超过消息中心容量时中心丢弃多余消息系统不会因消息过多而故障。负载均衡消费发布者消息量大、单个订阅者处理能力有限时可通过多分区 多个消费者实现负载均衡。Kafka 中分区数 ≥ 消费者数组内消费者才能均衡消费一般让一个消费组的消费者数 ≤ 该主题的分区数(或与之成倍数)避免消费者空负载或超载消费者增减、分区增减时会触发重平衡(rebalance)重新映射消费者与分区的对应关系尽量不要人为误操作导致重平衡消息队列模式什么是消息队列相比发布订阅的送货上门消息队列是货物自取消息或数据放到队列里谁需要谁就去取。以用户注册为例写数据库 400ms 发邮件 600ms 同步通信 1000ms引入消息队列后写数据库 100ms 后即可返回响应(发邮件异步执行)响应时间缩短到 500ms速度提升一倍消息队列的定义基于具有先进先出(FIFO)特点的数据结构存储具有特定格式的消息数据(如包含消息类型、唯一 ID、消息内容的结构体)。消息以特定格式放入队尾后可直接返回后续由消费者进程从队头依次取出处理。好处削峰填谷异步通信、实现组件间解耦。消息队列的工作原理核心结构三部分生产者产生消息/数据插入到消息队列(入队)消息队列FIFO 数据结构存储消息消费者从队列取出消息处理(出队)RocketMQ架构NameServer Cluster服务器集群管理 Broker 信息(地址、状态)供 Producer 和 Consumer 发现 Broker。Producer Cluster生产者集群多 Producer 并发接收用户数据提升处理效率且单点故障不影响整体业务。Broker ClusterBroker 集群负责存储消息每个 Broker 采用主从设计Master 可写可读Slave 只读Master 同步数据给 Slave 做备份Master 故障切换到 Slave。Consumer Cluster消费者集群提升消费能力避免 Broker 存储溢出。Broker 存储方式Topic Queue主题是逻辑概念一个主题可分区分布在不同 Broker每个主题分区中队列数量可由用户指定队列是资源分配的基本单元工作流程启动 NameServer启动 Broker主动向 NameServer 注册并定期发送心跳(默认 1s 一次)可携带存储数据信息创建主题确定主题数据放入哪些 BrokerProducer 发消息先到 NameServer 查询主题对应的 Broker再发送存储Consumer 消费消息先到 NameServer 查询 Broker再去拉取消息适用场景消息队列模式中消费者按需去消息队列获取数据消费消息队列中心无需提前知道消费者信息因此适合消费者为临时用户的场景。发布订阅 vs 消息队列维度发布订阅消息队列存储结构消息中心(map/数组等)队列(FIFO)触发方式消息中心主动推送给订阅者消费者主动拉取消费者要求需提前订阅(适合长驻进程)无需提前订阅(适合临时用户)一条消息消费次数可被多个订阅者消费一般一个消费者消费一次重复消费这是幂等性问题。常见方案消息端控制Kafka 用offset(消息序号)记录消费位置Consumer 定期提交 offset 表示已消费重启后从 offset 继续。业务幂等以订单号等唯一标识为去重键数据库加唯一索引或在内存中用 set 去重。Consumer 记录 offsetBroker 返回当前消费的偏移量Consumer 记录下次从该位置开始重复消费本身不可怕关键是要保证业务幂等性。总结场景对照远程调用 RPC发布订阅消息队列完整链路外部请求进入客户端 →DNS 负载均衡(区域级)→硬件负载均衡(F5接入层)→软件负载均衡(Nginx代理层)→ 应用服务器API 网关聚合在客户端与微服务之间API 网关做协议转换、链式处理、异步请求聚合多个微服务调用服务注册与发现微服务间通过服务注册中心感知彼此心跳保活本地维护路由表服务间通信根据业务场景选型——同步直接通信用RPC(Netty)异步间接通信用发布订阅(Kafka)或消息队列(RocketMQ)选型原则同步 vs 异步需直接结果(查询、下单)用同步 RPC耗时任务(发邮件、推送)用异步消息中间件临时 vs 长驻消费者长驻进程适合发布订阅(消息中心推送)临时用户/任务型适合消息队列(拉取模式)强解耦 vs 高一致性发布订阅和消息队列都能解耦要求强一致性的链路仍需 RPC 直接调用容量与吞吐百万级并发在代理层之上加 F5RPC 通信采用多路复用 IO消息中间件采用多分区消费组提升吞吐