【AICon】探索RAG 技术在实际应用中遇到的挑战及应对策略!AICon精华内容已上线73%>>> 了解详情
写点什么

EventMachine:高速可伸缩的事件驱动 I/O 框架

  • 2008-08-02
  • 本文字数:3083 字

    阅读完需:约 10 分钟

EventMachine 是一个基于 Reactor 设计模式的、用于网络编程和并发编程的框架。Reactor 模式描述了一种服务处理器,它接受事件并将其分发给已注册的事件处理。这种模式的好处就是清晰的分离了时间分发和处理事件的应用程序逻辑,而不需引入多线程来把代码复杂化。

EventMachine 提供了一个网络套接字和隐藏底层操作的高层接口。 EventMachine 的目标是

  • 拥有极高的可伸缩性、性能和稳定性,适用于大多数苛刻的生产环境;并且
  • 提供可以消除高性能多线程网络编程的复杂性的 API,使得工程师可以专心于产品逻辑本身

来看一个小例子,一个简单的聊天服务器:

<pre id="dyge20"> require 'eventmachine'<p> module Chat</p><br id="dyge23"></br> <br id="dyge24"></br> # Called after the connection with a client has been established<br id="dyge25"></br>  def post_init <br id="dyge26"></br> # Add ourselves to the list of clients<br id="dyge27"></br>   (@@connections ||= []) << self <br id="dyge28"></br> send_data "Please enter your name: "<br id="dyge29"></br>  end <p>  # Called on new incoming data from the client</p><br id="dyge32"></br>  def receive_data data<br id="dyge33"></br>  # The first message from the user is its name<br id="dyge34"></br>  @name ||= data.strip<br id="dyge35"></br> <br id="dyge36"></br> @@connections.each do |client|<br id="dyge37"></br>   # Send the message from the client to all other clients<br id="dyge38"></br>  client.send_data "#{@name} says: #{data}"<br id="dyge39"></br>  end<br id="dyge40"></br>  end<br id="dyge41"></br> end<p> # Start a server on localhost, using port 8081 and hosting our Chat application</p><br id="dyge44"></br> EventMachine::run do<br id="dyge45"></br>  EventMachine::start_server "localhost", 8081, Chat<br id="dyge46"></br> end我们采访了 EventMachine(EM)的主要开发人员 Francis Cianfrocca。我们询问了他开发 EventMachine 的动机是什么:

最初我启动这个项目是因为我打算写一个高性能的、面向消息的中间件,以便可以在脚本语言(包括 Ruby)下面开发起来更方便。如今已经有很多很多基于 EM 的项目了,但是那个中间件项目却还没搞定呢!我试图寻找一种方法来创建高度可伸缩的、适用于访问策略执行解决方案。并且我还需要一个足够高速的通信框架,而且还内建安全保障。

EventMachine 使用了 Thin (高速而简单 Ruby Web 服务器) Swiftiply (用于网络应用的集群化代理服务器)、 Evented Mongrel (网络流量由 EventMachine 处理的 Mongrel)、 Sparrow (基于 memcache 的轻量级的队列)和 Juggernaut (Ruby on Rails 的插件,服务器可以初始一个连接并将数据推送给客户端)。Francis 同时也编写了自己的 Web 框架:

我的框架叫做 Unicycle,它主要为 REST 化的应用而设计,就是那些对于那些需要通过 Web 请求和其他应用进行交互的网络应用。它也是基于 EM 的,使用的是 EM 内建的 HTTP 服务器。

EventMachine 的 0.12 版最近刚刚发布了:

在 0.12 版中我们作了一些性能的提升并引入了一些小特性,但最主要的是,我们发布了一个二进制的 gem,而它包括了自 0.8 版以来的所有特性。

EventMachine 的核心是 Reactor,最初是由 C++ 实现的,并可以被除了 Ruby 以外的其他语言使用。而且也有一个纯 Ruby 的实现,在下个版本中还有一个 Java 的实现,是用 JRuby 编写的:

待 发布的新特性中最重要的就是对 JRuby 的全面支持。想要这样就要用 Java 完全重写 reactor 核心。其实不但做到了,而且做得不错。Charles Nutter 和他的团队在 JRuby 上硕果累累,而且我认为还有巨大的潜力。我同时对 Rubinius 也颇感兴趣。Rubinius 的有趣之处在于其对纤 程(Fibers)的支持,这会使得 EM 的编程风格更加自然。我已经试用了 Ruby 1.9,但是我在更多的人使用新平台之前还没想好要不要升级 API。EM 的关键设计目标之一便是要保持最大的兼容性。

我们请 Francis 详细的谈谈 EventMachine 的优势:

从 技术上说,使用 EM 的重要原因就是,它引入了一种避免使用线程的编程模型。线程化编程当然早就被大家所熟知,尤其是在网络服务器方面,但是它也存在很多顽 疾。有一类问题是很适合用线程化模型来解决的,网络服务器就是其中之一。因为它通常需要为每个请求创建一个不相交的工作集。但是如果在线程之间有共享状态 的话,那么要让多线程程序 100% 正确运行是相当困难的,又或者它依赖于跨线程的操作顺序的正确性。在 Ruby 中,这种线程化所导致的问题是非常严重的。另外一个使用 EM 的理由就是,我们广泛地支持各种网络协议。我们的目标就是可以提供给开发者们一个庞大、成熟而又高性能的工具集合,可以让他们轻松地在自己的应用中使用。这也是为什么 EM 与其他很多工程的不同之处,它们仅仅是试图去简单地实现一个 reactor 模型而已。

我们也谈到了为什么相比较线程模型而言,事件驱动编程更加易用:

有 种说法是,从理论上说事件驱动编程并不比线程化编程快到哪里去,这是没错。但是在实践当中,我认为如果你想在保持最大可靠性的情况下能够获得最高的可扩展 性和性能的化,事件驱动模型更容易做到。我写的程序可以几个月甚至几年运行正常,没有崩溃,没有内存泄露,没有存在任何性能问题。因此在实践当中,事件驱 动编程更棒。现在,对于事件驱动编程来说还有个问题:那就是你需要“退步地”去编写程序。在线程模型中,程序状态被存在运行时的一个栈的本地变量中(尽管 很低效)。而在 EM 中,你需要自己去做这件事,这对于习惯于线程的程序员来说就很不直观。这也是为什么我对纤程(Fibers)感兴趣的原因,因为它可以 让程序看上去很像是那些喜欢 I/O 阻塞的程序员们写出来的。

更具体一些,拿 HTTP 服务器举例:

试 想一个使用线程的 HTTP 服务器,你只需简单地读取套接字然后阻塞,直到数据从另一端传输过来。如果使用事件的话,你就省去了等待或者调度上的开销,数据 一来你就收到了──但是数据可能是不完整的!在程序中你需要判断对于这个请求你是否收到了完整的数据,如果不是的话你就要存贮中间数据。但是你的程序处理 的下一个事件可能就是另一个连接传来的数据,所以你需要把这些都存下来。线程化抽象使用了一种很重量级的方式来保证工作集独立,因此按理说它也更为直观一 些。但是事件化模型也并不是十分难学。不过,我依然认为这是推广事件驱动编程的最大壁垒。

幸运地是,这正是 EventMachine 的专长:

目 前 EM 做到的一点就是,将基本协议包装起来,将所有这些从程序员面前最大化地隐藏起来。不像那些仅仅提供了一个 reactor 核心的底层库(比如 libev),EM 希望可以提供所有标准网络协议的鲁棒实现,比如 Email 等等。EM 包含了一个精心编写的处理器,SMTP 的客户端和服务器端都支持。 因此 EM 的程序员仅需要为完成 Email 消息相关事件编写代码即可,并不需要接触到底层协议。但是你还可以享用到事件模型的其他优点,比如高速度和高伸缩 性等等。

你可以在 Rubyforge 的官方站点或者 rubyeventmachine.com 上找到更多关于 EventMachine 的信息:

我们最近刚刚开通了社区网站 rubyeventmachine.com , 这是个 Trac 系统,由 Jason Roelofs 搭建。还有 EventMachine 的 IRC 频道。包括 Kirk Haines、James Tucker(raggi)和 Aman Gupta(tmm1)在内的很多人都对 EM 贡献甚多。Thin 的贡献者 Marc-André Cournoyer 也提供了很多想法。

查看英文原文: EventMachine: Fast and Scalable Event-Driven I/O Framework

2008-08-02 22:527247
用户头像

发布了 80 篇内容, 共 19.1 次阅读, 收获喜欢 5 次。

关注

评论

发布
暂无评论
发现更多内容

重庆区块链公共服务平台—“渝快链”2.0正式发布

浪潮云

六一特辑丨8岁小程序员献礼儿童节:我DIY了聊天机器人,做3D printer,还想和外星人对话!

华为云开发者联盟

编程 程序员 开发者 代码 机器人

架构之:并发和并行

程序那些事

架构 软件架构 架构师 程序那些事

☕【JVM 技术之旅】深入JVM回收器之Parallel Scavenge(上篇)

洛神灬殇

JVM GC 垃圾收集 5月日更 Parallel Scavenge

设计微博系统中”微博评论“的高性能高可用计算架构

9527

Nginx利用resolver实现动态upstream

运维研习社

nginx 运维 5月日更 动态负载均衡

Spring XML Schema扩展机制源码解读

Hex

Java spring 后端 Java EE

带你看懂MySQL执行计划

Simon

MySQL 执行计划

【Flutter 专题】117 图解 Dismissible 滑动清除 Widget

阿策小和尚

5月日更 Flutter 小菜 0 基础学习 Flutter Android 小菜鸟

如何成为一名拖垮整个团队的产品经理?

冰河

深度思考 产品经理 自我思考 产品经历 技能提升

架构师实战营 模块五总结

代廉洁

架构实战营

架构实战-模块5作业

大师兄

Dubbo Admin 部署

青年IT男

dubbo

JWT(auth0):RS256非对称加密算法实现Token的签发、验证

西门阿杰

Java Token RS256

使用 Quarkus 和 MicroProfile 实现微服务特性

张晓辉

Kubernetes 云原生 Quarkus Microprofile

开箱即用的 Prometheus 告警规则集

张晓辉

监控 Prometheus 告警

网络攻防学习笔记 Day30

穿过生命散发芬芳

5月日更 网络攻防

🔎【Java源码探索】深入浅出的分析 ThreadPoolExecutor

洛神灬殇

Java 线程池工作原理 ThreadPoolExecutor 5月日更 Worker

When others give us advice

escray

学习 极客时间 5月日更

一文带你搞懂RPC到底是个啥

万俊峰Kevin

c++ 微服务 RPC RPC 协议实现原理 srp

走近设计模式:写代码一定要用设计模式吗?

华为云开发者联盟

设计模式 代码 软件设计 面向对象软件 GoF设计模式

软件研发中的错误假设

赫杰辉

设计 低代码 研发工具 x-series

架构师实战营 模块五作业(设计微博评论的高性能高可用计算架构)

代廉洁

架构实战营

大型系统中的证书管理

张俭

微服务 TLS PaaS

业务架构训练营,模块5作业,微博评论高性能架构

好吃不贵

业务架构

初探可编程网关 Pipy

张晓辉

代理 网关 服务网格

从一个HTTP请求来看网络分层原理

IT视界

计算机网络 网络协议 HTTP 网络层

react源码解析1.开篇介绍和面试题

全栈潇晨

React React Hooks react源码

交叉验证

Qien Z.

5月日更 交叉验证

java.net.BindException: Address already in use: JVM_Bind解决方案

咿呀呀

IDEA javaWeb

Java 面试基础:Java 语言的特点

三掌柜

5月日更

EventMachine:高速可伸缩的事件驱动I/O框架_Ruby_Mirko Stocker_InfoQ精选文章