分布式架构设计之接入层

接入层(注①):

    反向代理(注②):

        nginx异步非阻塞(注③)IO密集型(注④),适合做反向代理。

        apache每个请求独占一个线程,适合做webserver。(注⑤)

        webserver中间件:nginx(c)、OpenResty(lua)、apache、tomcat、jetty、tengine

    负载均衡:

        一般互联网公司使用DNS做一级负载均衡(注⑥),后端服务器用Nginx或LVS(Linux Virtual Server)等作为二级负载均衡。

        DNS:DNS服务商配置,多级缓存,更新慢(注⑦)

        Nginx:自带多种负载均衡策略:轮询(Round-Robin)、最少连接(Least-connected)、最少耗时(Least-time)、会话保持(session persistence)、自定义hash、权重。(注⑧)

    限流:(注⑨)

        简单计数法(注⑩)

        滑动窗口法(滑动统计最近一段时间的请求量。精度提升)(注⑾)

        漏桶算法(漏桶以一定的速度出水)(注⑿)

        令牌桶算法(系统以恒定的速度向桶里放令牌)(注⒀)

    降级:(注⒁)

    熔断:(注⒂)

        快速失败,不会真正去请求外部资源。

        异常情况超出阈值进入熔断状态,服务调用不会真正去请求外部资源,快速失败。减少不稳定的外部依赖对核心服务的影响。

        当熔断器开关处于打开状态,经过一段时间后, 熔断器会自动进入半开状态,这时熔断器只允许一个请求通过。当该请求调用成功时,熔断器恢复到关闭状态。若该请求失败,熔断器继续保持打开状态,接下来的请求被禁止通过。

        熔断开关:服务的健康状况 = 请求失败数 / 请求总数,通过阈值设定和滑动窗口控制开关。

    超时 

    防雪崩 :(注⒃)

        [容错组件:Hystrix(netflix,java,封装了熔断、限流、隔离、降级等能力)]



注释:

    注① :接入层

         通常把网络中直接面向用户连接或访问网络的部分称为接入层(接入层目的是允许终端用户连接到网络)

    注②:反向代理与正向代理

        正向代理:客户端 <一> 代理一>服务端

        反向代理:客户端一>代理 <一> 服务端

    注③:nginx异步非阻塞

        Nginx通过I/O多路复用实现异步非阻塞 (参考明哥之前的博客《IO复用(select poll epoll)》)

        web server刚好属于网络io密集型应用,不算是计算密集型。web server的这种性质决定了每个request的大部份时间都消耗在网络传输中,实际上花费在server机器上的时间片不多。异步非阻塞,使用epoll,和大量细节处的优化,这就是Nginx几个进程就解决高并发的秘密所在。            

    注④:CPU密集型与IO密集型

        CPU密集型:硬盘、内存性 > CPU。I/O在等CPU

        IO密集型:CPU性能 > 硬盘、内存。CPU在等IO

        CPU密集型 :需要进行大量的计算的任务,消耗很多CPU资源,比如计算圆周率、对视频进行高清解码等。由于主要消耗CPU资源,因此代码运行效率至关重要。像Python这样的脚本语言运行效率很低,完全不适合计算密集型任务。对于计算密集型任务,最好用C语言编写。

        IO密集型:对于IO密集型任务,最合适的语言就是开发效率最高(代码量最少)的语言,脚本语言是首选,C语言最差。

    注⑤:Nginx与Apache对于高并发处理上的区别

        对于Apache,每个请求都会独占一个工作线程,当并发数到达几千时,就同时有几千的线程在处理请求了。这对于操作系统来说,占用的内存非常大,线程的上下文切换带来的cpu开销也很大,性能就难以上去,同时这些开销是完全没有意义的。

        对于Nginx来讲,一个进程只有一个主线程,通过异步非阻塞的事件处理机制,实现了循环处理多个准备好的事件,从而实现轻量级和高并发

    注⑥:DNS负载均衡

        对某个域的请求分配在不同机器上的技术。

    注⑦:DNS负载均衡还存在一些问题

  第一,域名服务器是一个分布式系统,是按照一定的层次结构组织的。当用户将域名解析请求提交给本地的域名服务器,它会因不能直接解析而向上一级域名服务器提交,上一级域名服务器再依次向上提交,直到RR-DNS 域名服务器把这个域名解析到其中一台服务器的IP 地址。可见,从用户到RR-DNS 间存在多台域名服务器,而它们都会缓冲已解析的名字到IP 地址的映射,这会导致该域名服务器组下所有用户都会访问同一Web 服务器,出现不同Web 服务器间的负载不平衡。为了保证在域名服务器中域名到IP 地址的映射不被长久缓冲,RR-DNS 在域名到IP 地址的映射上设置一个TTL(Time To Live)值,过了这一段时间,域名服务器将这个映射从缓冲中淘汰。当用户请求,它会再向上一级域名服务器提交请求并进行重新映射。这就涉及到如何设置这个TTL值,若这个值太大,在这个TTL 期间,很多请求会被映射到同一台Web 服务器上,同样会导致负载不平衡。若这个值太小,例如是0,会导致本地域名服务器频繁地向RR-DNS提交请求,增加了域名解析的网络流量,同样会使RR-DNS 成为系统中一个新的瓶颈。

  第二,用户机器会缓冲从名字到IP 地址的映射,而不受TTL 值的影响,用户的访问请求会被送到同一台Web 服务器上。由于用户访问请求的突发性和访问方式不同,例如有的人访问一下就离开了,而有的人访问可长达几个小时,所以各台服务器间的负载仍存在倾斜(Skew)而不能控制。假设用户在每个会话中平均请求数为20,负载最大的服务器获得的请求数额高于各服务器平均请求数的平均比率超过百分之三十。也就是说,当TTL 值为0 时,因为用户访问的突发性也会存在着较严重的负载不平衡。

  第三,系统的可靠性和可维护性不好。若一台服务器失效,会导致将域名解析到该服务器的用户看到服务中断,即使用户按“Reload”按钮,也无济于事。系统管理员也不能随时地将一台服务器切出服务进行维护,如进行操作系统和应用软件升级,这需要修改RR-DNS 服务器中的IP 地址列表,把该服务器的IP 地址从中划掉,然后等上一段时间,等所有域名服务器将该域名到这台服务器的映射淘汰,和所有映射到这台服务器的客户机不再使用该站点为止。

        RR-DNS方法只是一个简单的负载平衡方案,如果你有更高要求,可以研究LVS集群(IPVS和KTCPVS、TCPHA),实现基于IP的负载均衡和基于内容的负载均衡。

    注⑧:nginx负载均衡策略

        1.轮询(默认)——每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。

        2.weight ——指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。

        3. ip_hash ——每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器。

        4.backup——其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。

        5.down——表示单前的server暂时不参与负载

        6.fair(第三方)按后端服务器的响应时间来分配请求,响应时间短的优先分配。与weight分配策略类似。

    注⑨:限流

        限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量已达到保护系统的目的。一般来说系统的吞吐量是可以被测算的,为了保证系统的稳定运行,一旦达到的需要限制的阈值,就需要限制流量并采取一些措施以完成限制流量的目的。比如:延迟处理,拒绝处理,或者部分拒绝处理等等。

     注⑩:简单计数法

        计数器是最简单粗暴的算法。比如某个服务最多只能每秒钟处理100个请求。我们可以设置一个1秒钟的滑动窗口,窗口中有10个格子,每个格子100毫秒,每100毫秒移动一次,每次移动都需要记录当前服务请求的次数。内存中需要保存10次的次数。可以用数据结构LinkedList来实现。格子每次移动的时候判断一次,当前访问次数和LinkedList中最后一个相差是否超过100,如果超过就需要限流

    注⑾:滑动窗口法

        简单计数法算法虽然简单,但是有一个十分致命的问题,那就是临界问题

        假设有一个恶意用户,他在900毫秒时,瞬间发送了10个请求,并且又在1000毫秒时瞬间发送了10个请求,那么其实这个用户在 100毫秒里面,瞬间发送了20个请求。我们刚才规定的是1秒最多100个请求,也就是说100毫秒内最多10个请求。用户通过在时间窗口的重置节点处突发请求, 可以瞬间超过我们的速率限制。用户有可能通过算法的这个漏洞,瞬间压垮我们的应用。

        刚才的问题其实是因为我们统计的精度太低。那么如何很好地处理这个问题呢?或者说,如何将临界问题的影响降低呢?

        比如图中,我们就将滑动窗口划成了10格,所以每格代表的是100毫秒。每过100毫秒,我们的时间窗口就会往右滑动一格。每一个格子都有自己独立的计数器counter,

    注⑿:漏桶算法

        1.一个固定容量的漏桶,按照常量固定速率流出水滴;

        2.如果桶是空的,则不需流出水滴;

        3.可以以任意速率流入水滴到漏桶;

        4.如果流入水滴超出了桶的容量,则流入的水滴溢出了(被丢弃),而漏桶容量是不变的。

        漏桶算法比较好实现,在单机系统中可以使用队列来实现(.Net中TPL DataFlow可以较好的处理类似的问题,你可以在这里找到相关的介绍),在分布式环境中消息中间件或者Redis都是可选的方案。

    注⒀:令牌桶算法

        1.令牌将按照固定的速率被放入令牌桶中。比如每秒放10个。

        2.桶中最多存放b个令牌,当桶满时,新添加的令牌被丢弃或拒绝。

        3.当一个n个字节大小的数据包到达,将从桶中删除n个令牌,接着数据包被发送到网络上。

        4.如果桶中的令牌不足n个,则不会删除令牌,且该数据包将被限流(要么丢弃,要么缓冲区等待)。

    漏桶和令牌桶的比较

        令牌桶可以在运行时控制和调整数据处理的速率,处理某时的突发流量。放令牌的频率增加可以提升整体数据处理的速度,而通过每次获取令牌的个数增加或者放慢令牌的发放速度和降低整体数据处理速度。而漏桶不行,因为它的流出速率是固定的,程序处理速度也是固定的。

        整体而言,令牌桶算法更优,但是实现更为复杂一些。

    注⒁:服务降级

        当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作。

        自动降级:

            超时降级 —— 主要配置好超时时间和超时重试次数和机制,并使用异步机制探测恢复情况

            失败次数降级 —— 主要是一些不稳定的API,当失败调用次数达到一定阀值自动降级,同样要使用异步机制探测回复情况

            故障降级 —— 如要调用的远程服务挂掉了(网络故障、DNS故障、HTTP服务返回错误的状态码和RPC服务抛出异常),则可以直接降级

            限流降级 —— 当触发了限流超额时,可以使用暂时屏蔽的方式来进行短暂的屏蔽

        例:当我们去秒杀或者抢购一些限购商品时,此时可能会因为访问量太大而导致系统崩溃,此时开发者会使用限流来进行限制访问量,当达到限流阀值,后续请求会被降级;降级后的处理方案可以是:排队页面(将用户导流到排队页面等一会重试)、无货(直接告知用户没货了)、错误页(如活动太火爆了,稍后重试)。

     注⒂:服务熔断

        服务熔断和电路熔断是一个道理,如果一条线路电压过高,保险丝会熔断,防止出现火灾,但是过后重启仍然是可用的。

        而服务熔断则是对于目标服务的请求和调用大量超时或失败,这时应该熔断该服务的所有调用,并且对于后续调用应直接返回,从而快速释放资源,确保在目标服务不可用的这段时间内,所有对它的调用都是立即返回,不会阻塞的。再等到目标服务好转后进行接口恢复。

    注⒃:防雪崩

        雪崩过程

        上面是一组简单的服务依赖关系A,B服务同时依赖于基础服务C,基础服务C又调用了服务D

        服务D是一个辅助类型服务,整个业务不依赖于D服务,某天D服务突然响应时间变长,导致了核心服务C响应时间变长,其上请求越积越多,C服务也出现了响应变慢的情况,由于A,B强依赖于服务C,故而一个无关紧要的服务却影响了整个系统的可用。

        雪崩是系统中的蝴蝶效应导致其发生的原因多种多样,有不合理的容量设计,或者是高并发下某一个方法响应变慢,亦或是某台机器的资源耗尽。从源头上我们无法完全杜绝雪崩源头的发生,但是雪崩的根本原因来源于服务之间的强依赖,所以我们可以提前评估,做好熔断,隔离,限流。

    Hystrix理论(豪猪):        

        在一个分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,如何能够保证在一个依赖出问题的情况下,不会导致整体服务失败,这个就是Hystrix需要做的事情。Hystrix提供了熔断、隔离、Fallback、cache、监控等功能,能够在一个、或多个依赖同时出现问题时保证系统依然可用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容