Saturday, December 12, 2015

海量数据处理系列



http://djt.qq.com/article/view/156
   这个时候为什么所有用户发现操作都是失败的呢? 为什么不是1/10的用户发现操作能成功呢? 因为请求量和处理能力之间巨大的差异使得5.6s内就迅速填满了socket接收缓冲区(平均能缓存1000个请求,1000/(200-20)=5.6s),并且该缓冲区将一直保持满的状态。这意味着,一个请求被追加到缓冲区里后,要等待50s(缓存1000个请求,每秒处理20个,需要50s)后才能被进程A 取出来处理,这个时候用户早就看到操作超时了。换句话说,进程A每次处理的请求,都已经是50s以前产生的,进程A一直在做无用功。雪球产生了。
1、  每个系统,自己的最大处理能力是多少要做到清清楚楚。例如案例一中的前端进程A,他的最大处理能力不是50次/s,也不是20次/S,而是10次/S。因为它是单进程同步的访问后端B, 且访问后端B的超时时间是100ms,所以他的处理能力就是1S/100ms=10次/S。而平时处理能力表现为50次/S,只是运气好。

2、  每个系统要做好自我保护,量力而为,而不是尽力而为。对于超出自己处理能力范围的请求,要勇于拒绝。

3、  每个系统要有能力发现哪些是有效的请求,哪些是无效的请求。上面两个案例中,过载的系统都不具备这中慧眼,逮着请求做死的处理,雪球时其实是做无用功。

4、  前端系统有保护后端系统的义务,sla中承诺多大的能力,就只给到后端多大的压力。这就要求每一个前后端接口的地方,都有明确的负载约定,一环扣一环。

5、  当过载发生时,该拒绝的请求(1、超出整个系统处理能力范围的;2、已经超时的无效请求)越早拒绝越好。就像上海机场到市区的高速上,刚出机场就有电子公示牌显示,进入市区某某路段拥堵,请绕行。

6、  对于用户的重试行为,要适当的延缓。例如登录发现后端响应失败,再重新展现登录页面前,可以适当延时几秒钟,并展现进度条等友好界面。当多次重试还失败的情况下,要安抚用户。

7、  产品特性设计和发布上,要尽量避免某个时刻导致大量用户集体触发某些请求的设计。发布的时候注意灰度。

8、  中间层server对后端发送请求,重试机制要慎用,一定要用的话要有严格频率控制。

9、  当雪球发生了,直接清空雪球队列(例如重启进程可以清空socket 缓冲区)可能是快速恢复的有效方法。

10、过载保护很重要的一点,不是说要加强系统性能、容量,成功应答所有请求,而是保证在高压下,系统的服务能力不要陡降到0,而是顽强的对外展现最大有效处理能力。

  对于“每个系统要有能力发现哪些是有效的请求,哪些是雪球无效的请求”,这里推荐一种方案:在该系统每个机器上新增一个进程:interface进程。Interface进程能够快速的从socket缓冲区中取得请求,打上当前时间戳,压入channel。业务处理进程从channel中获取请求和该请求的时间戳,如果发现时间戳早于当前时间减去超时时间(即已经超时,处理也没有意义),就直接丢弃该请求,或者应答一个失败报文。

  Channel是一个先进先出的通信方式,可以是socket,也可以是共享内存、消息队列、或者管道,不限。

  Socket缓冲区要设置合理,如果过大,导致及时interface进程都需要处理长时间才能清空该队列,就不合适了。建议的大小上限是:缓存住超时时间内interface进程能够处理掉的请求个数(注意考虑网络通讯中的元数据)。
对于延时敏感的服务,当外部请求超过系统处理能力,如果系统没有做相
应保护,可能导致历史累计的超时请求达到一定的规模,像雪球一样形成恶性循环,由于系统处理的每个
请求都因为超时而无效,系统对外呈现的服务能力为0,且这种情况不能自动恢复。我们的系统就是要尽
量避免这种情况的出现
http://talentluke.iteye.com/blog/1841589
一  有过载问题的系统
数据处理流程:
       1) 前端将请求发送给数据解析及转发系统,
       2)数据解析及转发系统将封装好的数据发送后台数据请求,设置超时时间(假设300ms),线程同步等待处
理结果从后台返回。
      3)在300ms内正确返回结果后,则将处理的结果返回给前端,如果在300ms内超时,则将数据发送到一次超
时处理系统(假设设置超时时间500ms),线程同步等待结果返回。
      4)在500ms内正确返回结果后,则将处理的结果返回给前端,如果再一次超时,返回一个默认的处理结果给前
端,后端对数据进行本地化,然后可以将数据发送到离线处理系统进行二次处理。
假设开50个线程,每个线程秒平均处理一个请求,那么系统每秒可以处理的最大请求数是50个。一旦前端数据请求超
过50个每秒,在任务队列中将会堆积大量的请求,前台不断发送过来,后来处理不过来,前端又设置了套接字超时,导
致队列中的大量请求超时,直接使得后端线程从队列中取出套接字解析的时候,套接字已经被前台关闭了,引发I/O异常。
堆积的量一旦雪崩,将使前台发送过来的请求全部I/O异常,后台处理系统跟挂掉无异了。
二  相对完善的系统
在上面的系统中,对请求是来者不拒的状态,具体来讲就是将所有的请求都保存到任务队列。请求堆积到一定程度,
队列中的很多请求都超时,这是可以采取清空请求队列的方式,这个可以通过采取一定的监控方式来实现。例如上图
中的心跳监控模块,它可以通过这样的方式来实现,就是模拟客户端的请求,每隔一定时间发送一些请求过去,如果
有大部分都正常返回,说明后端处理系统正常;当出现大部分超时的时候,说明后台系统已经挂掉了,这时候重启数
据解析及转发系统,清空系统中的任务请求队列,这样可以暂时处理请求高峰期的情况。
      但是这个方式也是治标不治本的,后台最多只能处理这么多请求,重启后照样会导致大量堵塞导致系统又挂掉,
然后监控系统又重启,这样会使得很多的请求没有得到有效的处理,大大降低系统的处理能力。为了保证后台系统每
时每刻都最大限度的发挥自己的处理能力,当负载超过系统自身的处理能力时,拒绝该请求。拒绝后可以将该请求本
地系列化,保存相关的数据发送到离线数据处理系统进行处理。
   在前一篇文章《海量数据处理系列之Java线程池使用》第四节中有界队列线程池使用中有提到这种方式的具体实现。
以上面的系统为例,有界线程池可以这样配置,corePoolSize为30,maximumPoolSize为50,有界队列为
ArrayBlockingQueue<Runnable>(100)。
这样系统在处理请求的时候采用如下策略:
1) 当一个请求过来,线程池开启一个线程来处理,直到30个线程都在处理请求。
2) 当线程池中没有空闲线程了,就将请求添加到有界队列当中,直到队列满为止。
3) 当队列满以后,在开启线程来处理新的请求,直到开启的线程数达到maximumPoolSize。
4) 当开启的线程数达到maximumPoolSize后,任务队列又已经满了后,此时再过来的请求将被拒绝,被拒绝的请求
在本地系列化,将保存的数据同步到离线数据系统进行处理。
        海量数据处理都是采用分布式的,每台机器的处理能力有限,可以将请求分布到不同的机器上去。如果每台机器被
拒绝的请求数过多的时候,就要考虑添加处理的机器了。


Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts