适于互联网的SEDA高并发架构

一、前言

    最近看了一篇博士毕业论文(Matthew David Welsh--An Architecture for Highly Concurrent, Well-Conditioned Internet Services),于是将主要思想写了出来,旨在传播别人的思想,这篇论文探讨一种使用于Internet Services高并发的可扩展性架构,比较了传统的模型Thread-based模型和Event-driven模型,并提出了自己的模型SEDA。

二、背景

随着互联网的高速发展,各种各样的互联网服务相继出现,现在不再局限于静态页面的访问,如股票交易,电子商务,即时消息服务,点对点文件共享,应用托管等 等,与以前的静态页面发布服务相比,这些动态的服务,每一请求需要消耗更多的CPU,I/O等资源。导致管理和分发这些服务的系统日益复杂,包括Web Server, Cache, Middle-tier Application Server, Database等。

三、传统的并发编程模型

传统的并发编程模型主要有两种,一种是Thread-based concurrency, 另一种是Event-driven concurrency。下面分别介绍这两种模型,并比较这两种模型的优劣。

3.1 Thread-based concurrency 模型

1 Thread-based concurrency 模型,系统为每一个请求分配一个ThreadProcess,这个ThreadProcess负责处理这个请求并把结果返回给客户.这幅图中边代表控制流。

这是一种最常见的并发编程模型,为每一个请求分配一个线程或进程。如今的现代编程语言和操作系统对这种模型有很好的支持。

在这种Thread-per-request模型下,如图1所示,每一个被接受的请求被指派给一个线程或进程去处理。锁,信号量等被用于同步Thread/Process对共享数据结构的访问。操作系统负责调度这些处理每个请求的Thread, 来保证每个请求可以透明的分享计算机的CPU,I/O等资源。

这种Thread-per-request模型,编程起来简单,可以将处理一个完整请求的代码编写在一个代码路径中,并且据有很好的隔离性,每一个请求的处理都被隔离在一个Thread/Process中。请求请求之间的交换只有通过访问共享数据结构来实现。

但是thread-per-request也引起了一些挑战,资源管理,可扩展性等。资源管理粒度太粗,一个系统支持的线程数是有限制的,导致可扩展性差。

2 thread-per-request模型的性能 This benchmark measures a simple threaded server that dispatches a separate thread for each concurrent request in the system. After receiving a request, each thread performs an 8 KB read from a disk file; all threads read from the same file, so the data is always in the buffer cache. Threads are pre-allocated in the server to eliminate thread startup overhead from the measurements, and requests are generated internally to negate network effects. The server is implemented in C and is running on a 4-way 500 MHz Pentium III with 2GB of memory under Linux 2.2.14. As the number of concurrent requests increases, throughput initially increases until about 8 threads are in use. Adding additional threads causes throughput to degrade substantially. Response time becomes unbounded as request queue lengths increase; for comparison, we have shown the ideal linear response time curve (note the log scale on thehorizontal axis).


很重要的一点就是设计多线程(进程)模型是为了共享计算机的资源。随着线程(进程)数的上升,这个模型引起了更高的资源消耗,操作系统在这些线程(进程)之间的频繁切换,内存交换,缺页更加频繁,锁竞争更加激烈等,将急剧降低系统的性能,急剧降低系统的吞吐量和增加每个请求的响应时间。从图2中我们可以看出,随着线程(进程)数的增加,在线程(进程)数较低时,系统的性能是上升的(系统的吞吐量增加,每个请求的响应时间线性上身),但是到达一个临界值,随着线程(进程)数的增加系统的性能急剧下降(系统的吞吐量急剧下降,每个请求的响应时间急剧上升几乎是指数上升)。更重要的是一个系统所能支持的线程(进程)数是有限的,线程(进程)数超过一个理想值后将引起系统的性能急剧下降。

当然为了控制系统的线程(进程)数在一个理想值,避免过多的线程(进程)导致系统性能下降,可以引入线程(进程)池。在这种方式下,所有的请求被分配给一组固定大小的线程(进程)。当所有的线程(进程)忙于处理请求时,新的请求被安放在队列中等待处理。

    Thread-per-request模型的资源管理问题,Thread-per-request模型中的一些重要信息,如每一个请求的资源消耗,Blocking I/O等信息隐藏在OS的Thread scheduler中,应用层面基本上不可能去合理调度每一个请求的处理,这些是被OS给剥夺了。所以服务器基本上不可能合理的去调度每一个请求,只能祈祷OS调度了。当然我们也可以去实现应用层的线程,这样的复杂度何代价很大。

3.2 Event-driven concurrency模型

考虑到Thread-pre-request模型的可扩展性问,人们发明了Event-driven concurrency模型。在这种模型中,服务器由一组线程/进程(一般是 one per CPU)循环处理各种来自队列的事件(Event)。OS,应用都可以产生这些事件,表示某些操作需要执行,如:network或 disk I/O 准备就绪,或者完成通知,定时器,或者应用层的自定义事件。

3 Event-driven concurrency模型

在Event-driven concurrency模型中,每一个请求在系统被表示成一个 Finite State Machine(FSM,有限状态机)。每一个FSM的状态表示请求的一系列的操作。比如一个静态页面的请求可能包含这些状态,如图4:

  1. Read request from network;

  1. Parse request (e.g., process HTTP headers);

  1. Look up disk file corresponding to request;

  1. Read file data;

  1. Format reply packet;

  1. Write reply to network.

4 Finite state machine for a simple HTTP server requestThis figure depicts a static HTTP server request as a finite state machine (FSM) as used in an event-driven system. Each state represents some aspect of request processing, and edges represent transitions between states, triggered by incoming events or the completion of the processing for a given state.

当一个请求的事件到来,系统分配线程组中的一个线程处理这个请求的对应状态的操作。这些对应状态的操作一般很短,处理完后请求转换到FSM的下一个状态等待系统处理,这个线程又会被系统分配去处理下一个请求的这个状态。

Event-driven concurrency模型中实际上通过FSM来在应用层调度每一个请求,通过在请求之间切换来实现,通过使用一组过定数量的线程来处理请求的各个状态。一个线程可以处理每个请求的一种状态,或者是多个状态,或者是多个线程,这就依赖于具体实现了。这种模型要求每一个状态的操作是短暂的并且是非阻塞的,所以 Event-driven concurrency模型一般都用了非阻塞的I/O接口。Event-driven concurrency模型中的事件调度类似于OS的thread 调度,这样Event-driven concurrency模型中可以设计应用层的调度策略。

Event-driven concurrency模型一般比Thread-per-request模型更据可扩展性,利用FSM来表示每一个请求,比Thread-per-request模型用Thread(Process)来表示一个请求更据可扩展性,也降低了系统中的Thread(Process)数,降低了系统消耗的资源。

如果设计的好,Event-driven concurrency模型可以支持很高的并发度,并且随着并发度的增加,系统的整体性能的降低在一个可以接受的范围内,如图5所示。这种高性能得益于Event-driven concurrency模型降低了系统中过多的线程(进程)的使用,而降低了系统的资源消耗。

如图5所示,随着请求数的增加,系统的吞吐量增加,每个请求的响应时间缓慢线性上升,直到达到饱和,这时受限到计算机的物理硬件,CPU,内存等,达到饱和后没个请求的响应时间急剧上升,因为系统中有太多的请求等待调度。当然随着请求数的进一步上升,系统的吞吐量也会急剧下降,这时由于系统的物理内存消耗殆尽,引起频繁的缺页何内存交换,TLB失效等。

5 Event-driven server throughput: This benchmark measures an event-driven version

of the server from Figure 3. In this case, the server uses a single thread to process tasks, whereeach task reads 8 KB from a single disk file. Although the filesystem interface provided by the operating system used here (Linux 2.2.14) is blocking, because the disk data is always in the cache,this benchmark estimates the best possible performance from a nonblocking disk I/O layer. As thefigure shows, throughput remains constant as the load is increased to a very large number of tasks(note the change in the horizontal axis scale from Figure 3), and response time is linear (note thelog scale on the horizontal axis).

Event-driven concurrency模型能很好的支持高并发,但是同时也对开发者提出了更高的要求,一个很重要的就是要求事件处理代码短小精干,尽可能的执行非阻塞操作,避免拖延或阻塞事件处理线程,来保证每一个请求的公平性。

Event-driven concurrency模型的关键是设计一个高效公平的事件调度器,同时考虑高效和公平,这里就有很多要考虑的,如请求的优先级,事件的优先级,事件处理的顺序,资源的消耗等。考虑到请求的优先级,事件的优先级,事件的资源消耗都于具体的应用相关,所以Event-driven concurrency模型的通用性必然不理想。

四、SEDA并发模型

4.1 SEDA整体介绍

SEDA将应用分通过事件队列链接的网状Stage,每个Stage由一个线程池,一个业务相关的事件处理器(Event Handler),一个事件输入队列和一个多个资源控制器组成。如图6所示。

6 Staged event-driven (SEDA) HTTP server: This is a structural representation of Haboob, the SEDA-based Web server, described in detail in Chapter 6. The application is composed as a set of stages separated by queues. Edges represent the flow of events between stages. Each stage can be independently managed, and stages can be run in sequence or in parallel, or a combination of the two. The use of event queues allows each stage to be individually load-conditioned, for example, by performing admission control on its event queue. For simplicity, some event paths and stages have been elided from this figure.

SEDA的几点重要设计:

Efficient, event-driven concurrency: SEDA并发模型依赖于Event-driven concurrency 模型来支持高并发。利用一组线程来处理每个请求,而不是每一个请求一个线程,利用 Nonblocking I/O来避免资源的阻塞。

Dynamic thread pooling: 为了避免设计事件调度和达到非阻塞操作的要求,SEDA利用一系列线程组(Thread pool), 每一个事件处理器利用一个动态的线程池。这样就可以利用OS的线程调度来调度事件的处理,并且可以允许事件处理代码阻塞一小段时间,因为有多个线程(一个动态线程池)可以处理一个事件。

Structured queues for code modularity and load management: 通过事件队列将一个应用分割成一系列的Stage,可以让应用开发者只关注具体的业务逻辑(事件处理器),然后通过队列将各个State组装成应用,也可以动态的添加何卸载Stage。这样可以独立开发每一个Stage。

应用也可以在每个Stage中控制每一个请求的执行,如执行路径的改变,或终止请求等。每一个Stage可以更具自身的状态来控制请求的执行,如某一个Stage的负载太高,可能会拒绝处理这个请求。当然也可以让资源管理与控制在更细的粒度,没一个Stage都可以有自己的资源管理宇控制。

Self-tuning resource management:

4.2 Stage

Stage是SEDA中的核心基本单元,每一个Stage是一个自包含的应用组件,包含一个事件处理器(Event Handler),一个输入事件队列(incoming event queue),一个线程池(thread pool)和一个或多个资源控制器(Controller)。资源控制器负责资源消耗的管理,调度,线程分配和回收等。Stage的线程从事件输入队列批量取出事件,并调用事件处理器代码,事件处理器处理每一个事件,并输出0个或多个事件到其他的Stage的事件输入队列。如图7所示。

7 A SEDA Stage: A stage consists of an incoming event queue, a thread pool, and an application-supplied event handler. The stage’s operation is managed by a set of controllers, which dynamically adjust resource allocations and scheduling.

五、对比

六、总结

七、demo

        1.一个简单的通用框架destiny

        2.一个简单的基于通用框架destiny的服务程序luck

        3.客户端luckclient的

互联网的SEDA高并发架构相关推荐

  1. Java开发大型互联网高并发架构实战之原理概念分析

    JAVA大飞哥 2019-06-16 21:07:08 引言 高并发是指在同一个时间点,有很多用户同时访问URL地址,比如:淘宝的双11.双12,就会产生高并发.又如贴吧的爆吧,就是恶意的高并发请求, ...

  2. 大神级教程!300分钟撸一个基于Redis 6.0 版本的高并发架构

    刚好原先公司搞职位调整,我不太满意,赶上这波金三银四的面试浪潮,干了也有5年的后端开发了,不是大神也是有实战经验的,我就自信满满地去面了几家大厂,结果就遇到... 面试官这夺命连环12问,谁顶得住? ...

  3. 支付宝架构师眼里的高并发架构

    http://blog.csdn.net/sinat_41559116/article/details/79076063 前言 高并发经常会发生在有大活跃用户量,用户高聚集的业务场景中,如:秒杀活动, ...

  4. 架构师眼中的高并发架构

     00 前言   高并发经常会发生在有大活跃用户量,用户高聚集的业务场景中,如:秒杀活动,定时领取红包等. 为了让业务可以流畅的运行并且给用户一个好的交互体验,我们需要根据业务场景预估达到的并发量等因 ...

  5. java架构师眼中的高并发架构

    前言 高并发经常会发生在有大活跃用户量,用户高聚集的业务场景中,如:秒杀活动,定时领取红包等. 为了让业务可以流畅的运行并且给用户一个好的交互体验,我们需要根据业务场景预估达到的并发量等因素,来设计适 ...

  6. 如何估算代码量_千万级用户的大型网站,应该如何设计其高并发架构?(彩蛋)...

    目录 (1)单块架构 (2)初步的高可用架构 (3)千万级用户量的压力预估 (4)服务器压力预估 (5)业务垂直拆分 (6)用分布式缓存抗下读请求 (7)基于数据库主从架构做读写分离 (8)总结 本文 ...

  7. 设计自己的高并发架构

    设计自己的高并发架构 在互联网行业,未来的趋势就是高并发.分布式系统. 作为一名互联网开发人员,一定要把握发展趋势,并沿着正确的路线提升自己.我也是刚刚开始了解什么是高并发.分布式的系统,怎样进行这种 ...

  8. 微博短视频百万级高可用、高并发架构如何设计?

    本文从设计及服务可用性方面,详细解析了微博短视频高可用.高并发架构设计中的问题与解决方案. 今天与大家分享的是微博短视频业务的高并发架构,具体内容分为如下三个方面: 团队介绍 微博视频业务场景 &qu ...

  9. 高并发架构系列:什么是流量削峰?如何解决秒杀业务的削峰场景

    流量削峰的由来 主要是还是来自于互联网的业务场景,例如,马上即将开始的春节火车票抢购,大量的用户需要同一时间去抢购:以及大家熟知的阿里双11秒杀, 短时间上亿的用户涌入,瞬间流量巨大(高并发),比如: ...

最新文章

  1. [公告]网站恢复正常运行
  2. oracle sql 艺术,Oracle PL/SQL 从if 到 then的“艺术鉴赏”
  3. ORACLE基础学习-RMAN应用-控制文件恢复
  4. 把对象转换成JSON字符串 第二稿支持移动设备
  5. js 栈(进制转换)
  6. 数据结构算法入门--链表
  7. java 冒泡排序的三种写法_冒泡排序的三种实现(Java)
  8. redis入门——集群篇
  9. TortoiseSVN 加锁,服务器地址更换,切换登录用户
  10. 前段时间是Flash大战HTML5,现在是SliverLight“被遗弃”,我啊羡慕你们的热闹。...
  11. 走进我的交易室07_资金管理公式
  12. Java反射机制获取当前类名
  13. Redis 6.0 源码阅读笔记(2) -- Redis 多线程原理
  14. 【bzoj1050】[HAOI2006]旅行comf 并查集
  15. mac效率工具alfred 4汉化版
  16. python之udp
  17. Z820安装Win7系统出现0X0000007B蓝屏报错无限重启的解决方法与相关问题
  18. springcloud搭建实战<十一>【config配置中心】
  19. react xlsx 数据转换excle 插件
  20. 说说 input 输入框的事件

热门文章

  1. 青岛大学开源OJ平台搭建
  2. 最小生成树Prim算法Java版
  3. 如何轻松的写一个注册网页?
  4. Nacos服务器1.4.1下载篇
  5. 2023年推荐几款开源或免费的web应用防火墙
  6. jquery服务器文件保存到本地,jQuery本地存储
  7. 解决Duplicate entry '……
  8. c# 在word文件指定位置 插入图片
  9. MYSQL ‘S APPLY
  10. 解决操作无法完成,因为其中的文件夹或文件已在另一程序中打开的问题