掌握高并发、高可用架构第三章 分布式

本章介绍分布式架构的底层技术。主要说明面试过程中可能被问到的技术点。

第一节 Dubbo

Duboo 服务治理 Zookeeper

1. Dubbo的概念

Dubbo是一个分布式、高性能、透明化的RPC(远程服务调用)服务框架, 提供服务自动注册、自动发现等高效服务治理方案,可以和Spring无缝集成。

2. Dubbo的由来

当网站流量很小时,可以把所有功能都部署在一个项目中,叫单体应用框架。

随着流量的增大,应用拆分必不可少,此时会出现多个垂直应用,在美格尔应用中处理各自的业务逻辑。

当垂直应用越来越多,应用之间的交互不可避免,将核心业务抽离出来,作为独立的服务,逐渐形成稳定的服务中心。此时,用于提高业务复用和整合的 分布式服务框架 RPC 是关键。

当服务越来越多,容量的评估、小服务资源的浪费等问题逐渐显现,此时需要增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高集群利用率的 资源调度和治理中心 SOA 是关键。

3. Dubbo的主要特点透明化的远程方法调用,没有API侵入软负载均衡及容错机制,降低成本,拒绝单点服务自动注册与发现,不再需要写死服务提供者地址,注册中心基于接口名查询服务提供者的IP地址,并能够平滑的添加或删除服务提供者4. Dubbo的核心组件Provider,暴露服务的服务提供方Consumer,调用远程服务的服务消费者Registry,服务注册与发现的服务中心Monitor,统计服务的调用次数和调用时间的监控中心Container,服务运行容器

下面来解释上述的两张图:

服务容器启动、加载、运行服务提供者服务提供者在启动时,向注册中心注册自己提供的服务服务消费者在启动时,向注册中心订阅自己所需的服务,并将获得的地址列表进行缓存。如果没有订阅到自己想订阅的服务,它会不断尝试订阅注册中心返回服务提供者地址列表给消费者。当新的服务注册到注册中心后,注册中心会基于长连接将这些服务通过notify到消费者服务消费者从缓存的提供者地址列表中,基于软负载均衡算法,选一台进行服务调用(此处有容错机制)服务提供者和消费者,在各自的内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心5. Dubbo的核心配置配置配置说明dubbo:service服务配置,用于暴露服务,定义服务的元信息,一个服务可用多个协议暴露,也可以注册到多个注册中心,对应ServiceBeandubbo:reference引用配置,用于创建一个远程服务代理,一个引用可以指向多个注册中心。对应ReferenceBeandubbo:protocol协议配置,用于配置提供服务的协议信息,协议由提供方指定,消费方被动接受。对应ProtocolConfigdubbo:application应用配置,用于配置当前应用信息,不管应用是服务提供方还是消费方 。对应ApplicationConfigdubbo:module模块配置,用于配置当前模块信息,可选。对应ModuleConfigdubbo:registry注册中心配置。对应RegistryConfigdubbo:monitor监控中心配置。对应MonitorConfigdubbo:provider提供者配置,当没有配置ProtocolConfigServiceBean时,采用该配置项,可选。对应ProviderConfigdubbo:consumer消费方配置,当没有配置ReferenceBean时,采用该配置项,可选。对应ConsumerConfigdubbo:method方法配置dubbo:argument参数配置6. Dubbo支持的协议协议名称实现描述连接使用场景dubbo协议(默认)传输:mina、netty、grizzly<br />序列化:hessian2、java、json缺省采用单一长连接和NIO异步通信,TCP1.传入传出参数数据包较小<br />2.消费者数量远大于生产者<br />3.常规远程服务调用<br />4.不适合传输大数据量的服务,比如文件、视频等rmi传输:rmi java<br />序列化:java标准序列化连接个数:多连接<br />连接方式:短连接<br />传输协议:TCP/IP<br />传输方式:BIO1.常规RPC调用<br />2.传入传出参数大小包混合<br />3.可传文件<br />4.不支持防火墙穿透<br />5.生产者和消费者数量差不多hessian传输:servlet容器<br />序列化:hessian2连接个数:多连接<br />连接方式:短连接<br />传输协议:HTTP<br />传输方式:同步传输1.生产者的数量比消费者多<br />2.可传文件<br />3.传入传输参数数据包较大<br />4.跨语言传输http传输:servlet容器<br />序列化:表单序列化JSON<br />采用Spring的httpInvoker实现,基于表单的远程服务调用连接个数:多连接<br />连接方式:短连接<br />传输协议:HTTP<br />传输方式:同步传输1.生产者多余消费者<br />2.数据包大小混合<br />3.需同时给应用程序和浏览器使用的服务webservice传输:HTTP<br />序列化:SOAP文本序列化连接个数:多连接<br />连接方式:短连接<br />传输协议:HTTP<br />传输方式:同步传输1.系统集成<br />2.跨语言传输thrift与thrift rpc实现集成,并在基础上修改了报文头长连接、NIO异步传输memcachedredis7.支持的序列化框架

hessian(默认)、dubbo(不建议)、fastjson、Java自带序列化

8. 支持的通信框架

默认是Netty的NIO通信,还支持mina、Grizzly、Http等

9. 支持的集群容错机制集群容错方案说明Failover Cluster(默认)失败自动切换,自动重试其他服务器Failfast Cluster快速失败,立即报错,只发起一次调用Failsafe Cluster失败安全,出现异常时,直接忽略Failback Cluster失败自动恢复,记录失败请求,定时重发Forking Cluster并行调用多个服务器,只要一个成功立即返回Broadcast Cluster广播逐个调用所有生产者,任意一个报错则报错

读操作建议使用Failover失败自动切换,默认重试两次

写操作建议使用Failfast快速失败,调用一次失败就报错

10. 支持的负载均衡算法负载均衡测量说明Random LoadBalance(默认)随机,按权重分配随机概率RoundRobin LoadBalance轮询,按公约后的权重设置轮询比率LeastActive LoadBalance最少活跃调用数,相同活跃数的随机ConsistendHash LoadBalance一致性Hash,相同参数的请求总是发到同一生产者11. 支持的注册中心Multicast注册中心Zookeeper注册中心Redis注册中心Simple注册中心12. 服务暴露和服务消费的过程

服务暴露:在容器启动时,按照Spring的加载流程初始化BeanDefinition,把服务提供者解析成ServiceBean。然后调用export()方法进行暴露。(暴露过程相当长,以后慢慢看吧)

ServiceBean拿到对外提供服务的实际类ref(如HelloWorldImpl)通过ProxyFactorygetInvoker()方法使用ref生成一个AbstractProxyInvoker实例。到这一步就完成了到Invoker的转换将Invoker转换为Exporter,这个根据不同的协议会有不同的实现Dubbo的实现:发生在DubboProtocolexport(),主要是打开socket侦听服务,并接收客户端发来的各种请求RMI的实现:发生在RmiProtocolexport()

服务消费,分为消费端的初始化和服务引用过程。

初始化:

把服务引用的信息封装成URL,并注册到zk中心监听注册中心服务的上下线连接服务提供端,创建NettyClient对象将这些信息包装成DubboInvoker消费端的调用链,创建消费端Invoker实例的服务代理并返回

服务引用:

经过负载均衡策略,调用提供者选择其中一个服务的URL与提供者netty建立连接,使用ProxyFactory创建远程代理或本地通信的Invoker,并将Invoker发送到netty提供端服务提供端接到该Invoker请求后,找到对应的本地Invoker,处理获取异步、同步处理结果异步调用,不需要立即拿到返回值,使用ExchangeClient.send()同步调用,需要立即拿到返回值,使用ExchangeClient.request(),返回一个ResponseFuture,一直阻塞到拿到返回值

ReferenceBeaninit()方法调用Protocalref()方法生成Invoker实例将Invoker实例转换成客户端需要的接口类