Open wuyongxiu opened 8 years ago
打那么多字不累吗?
周末的时候做的,还好
2017-07-28 16:55 GMT+08:00 Pikahug notifications@github.com:
打那么多字不累吗?
— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/wuyongxiu/wuyongxiu.github.io/issues/4#issuecomment-318599078, or mute the thread https://github.com/notifications/unsubscribe-auth/AQmeIeCG-U-Kg92NIUohfHzgto_yWBtYks5sSaHmgaJpZM4Jjns_ .
写在前面的话: 回首一周,竟发现没有什么可写的,上周实在玩得太嗨了。不过倒是买了2本不错的书,一本是雨痕签名版的《go语言学习笔记》(这本书完全是出于情怀),另一本是《大型分布式网站架构设计与实践》。由于之前对于分布式开发基本没有概念(其实是对于开发没概念),随着最近这几周的学习,稍微有了些了解(只是浅薄的了解啊)。所以这本《大型分布式网站架构设计与实践》于我而言倒是一本难度适宜的科普知识,而且与我做的工作倒是很契合,可以随着理理思路。
基础知识
RPC:Remote Process Call 远程过程调用
单台服务器的处理能力受硬件成本的限制,不可能无限制地提升。RPC将原来的本地调用转变为调用远端的服务器上的方法,给系统的处理能力和吞吐量带来了近似于无限制提升的可能。RPC是实现分布式计算的基础。RPC包括服务的调用方与服务的提供方。
对象的序列化
HTTP协议栈(具体参考OSI协议栈)
基于TCP和基于HTTP的RPC的比较
基于TCP协议实现的RPC,处于协议栈的下层,能够更灵活地对协议字段进行定制,减少网络传输字节数,降低网络开销,提高性能,实现更大的吞吐量和并发数。但是需要更多地关注底层复杂的细节,实现代价更高,且由于所定义协议自身的局限性,难以得到平台厂商和开源社区的支持,较难实现跨平台的调用。
基于HTTP协议的RPC可以使用JSON或者XML格式的响应数据,开源的解析工具已经相当成熟,在其上进行二次开发屏蔽了很多底层烦琐的细节,非常便捷和简单。开发人员可以将更多的精力集中在业务的实现上,而非处理底层细节。劣势就是由于是上层协议,发送包含同等内容的信息,使用HTTP协议传输所占用的字节数肯定要比使用TCP协议传输所占用的字节数更多,而且传输所占用的时间要更长。可以通过优化代码实现和使用gzip数据压缩,缩小差距。结合实际环境来看,基于HTTP协议的RPC优势更大。
服务的路由和负载均衡
服务路由
SOA架构中,服务消费者通过服务名称,在众多服务中找到要调用的服务的地址列表,称为服务的路由。
服务的负载均衡
对于负载较高的服务来说,往往对应着由多台服务器组成的集群。在请求到来时,为了将请求均衡地分配到后端服务器,负载均衡程序将从服务对应的地址列表中,通过相应的负载均衡算法和规则,选取一台服务器进行访问,这个过程称为服务的负载均衡。
负载均衡算法
轮询法(Round Robin)
将请求按顺序轮流地分配到后端服务器上,它均衡地对待后端每一台服务器,不关心服务器实际的连接数和当前的系统负载。
随机法(Random)
通过系统随机函数,根据后端服务器列表的大小值来随即选取其中一台进行访问。随着调用量的增大,其就达到了轮询的效果。
源地址哈希法
源地址哈希法的思想是获取客户端访问的IP地址值,通过哈希函数计算得到一个数值,用该数值对服务器列表的大小进行取模运算,得到的结果便是要访问的服务器的序号。采用哈希法进行负载均衡,统一IP地址的客户端,当后端服务器列表不变时,它每次都会被映射到统一台后端服务器进行访问。
加权轮询(Weight Round Robin)法
不同的后端服务器可能机器的配置和当前系统的负载并不相同,因此它们的抗压能力也不尽相同。给配置高、负载低的机器配置更高的权重,让其处理更多的请求。
加权随机(Weight Random)法
与加权轮询类似
最小连接数(Least Connection)法
根据后端服务器当前的连接情况,动态地选取其中当前积压连接数最少的一台服务器来处理当前请求。
服务的路由和负载均衡问题
服务信息的静态注册和获取
服务规模小的时候可以通过将服务地址和配置写在代码中,或者采用设备例如LVS或者Nginx等,通过相关配置解决服务的路由和负载均衡问题。 优点:实现起来简单,或者有现成的解决方案或者设备。 缺点:当服务越来越多,规模越来越大时,对应的机器数量也越来越大,单靠人工来管理和维护服务以及地址的配置信息,变得越来越困难。另外,单点故障的问题也开始凸显,一旦服务路由或者负载均衡服务器宕机,依赖它的所有服务均将失效。
服务的动态注册和获取
服务配置中心,用来动态注册和获取服务信息,从而来统一管理服务名称和其对应的服务器列表信息。 服务提供者在启动时,将其提供的服务名称、服务器地址注册到服务配置中心。服务消费者通过服务配置中心来获得需要调用的服务的机器列表,通过相应的负载均衡算法,选取其中一台服务器进行调用。当服务器宕机或者下线时,相应的机器需要能够动态地从服务配置中心里面移除,并通知相应的服务消费者,否则服务消费者就有可能因为调用到已经失效的服务而发生错误。在这个过程中,服务消费者只有在第一次调用服务时需要查询服务配置中心,然后将查询到的信息缓存到本地,后面的调用直接使用本地缓存的服务地址列表信息,而不需要重新发起请求到服务配置中心去获取相应的服务地址列表,直到服务的地址列表有变更(机器上线或者下线)。这种无中心化的结构解决了之前负载均衡设备所导致的单点故障问题。
路由和负载均衡地实现
ZooKeeper的znode的特点和watcher机制,让其能作为动态注册和获取服务信息的配置中心,统一管理服务名称和其对应的服务器列表信息,让我们能够近乎实时地感知到后端服务器的状态。同时,ZooKeeper集群间通过Zab协议(保证数据一致性),服务配置信息能够保持一致,而Zookeeper本身容错特性和leader选举机制,能保障我们方便地进行扩容。(Etcd也类似)
HTTP服务网关
近年来,平台厂商开始做开放平台,将数据有限地开放给第三方开发者,这样第三方开发者可以利用这些数据为用户提供更完善的服务,形成了良性循环。在开放平台开放服务时,由于公共网络的环境复杂多变,必须得搭建一个强大的安全体系,来保障相关数据和接口的安全。网关(gateway)因此应运而生。网关接收各种HTTP请求,完成相应的权限与安全校验。当校验通过后,根据传入的服务名称,到服务配置中心找到相应的服务名称节点,并加载对应服务提供者的地址列表,通过前面所提到的负载均衡算法,选取机器发起远程调用,将客户端参数传递到后端服务器。服务提供方根据所传入的参数,给出正确的响应,当gateway接收到响应后,再将响应输出给客户端APP。
一方面通过gateway能够很好地解决安全问题,在恶意请求或者非授权请求到达后端服务器之前进行拦截和过滤。另一方面,gateway通过服务名称进行服务的路由和负载均衡调度,使得不同的平台之间能够很好地复用公共的业务逻辑,降低了开发和运维成本。
服务提供者是不直接对外提供服务的,因此,对于外部的APP来说,它依赖gateway进行服务的路由以及请求的转发,gateway是整个网络的核心节点,一旦gateway失效,所有依赖它的外部APP都将无法使用。并且由于所有的请求均经过gateway进行安全校验和请求转发,其流量是整个后端集群流量之和。因此,在设计之初,就需要考虑到系统流量的监控和容量规划,以及gateway集群的可扩展性,以便在流量达到极限之前,能够快速方便地进行系统扩容。