美文网首页
基于事件驱动的异步IO (ruby) 系列一

基于事件驱动的异步IO (ruby) 系列一

作者: 这哥们没昵称 | 来源:发表于2017-01-04 19:45 被阅读287次

最近翻了下电脑里几年前记得一些东西, 想把关于 ruby 事件驱动编程的一些知识重新整理下并分享出来

为什么需要事件驱动编程

  • 关于阻塞

服务器程序开发的时候, 通常和一些外部服务做通信, 比如 数据库服务器 外部接口的请求.
在常规的编程模式下, 比如程序做一次数据库查询的时候, 先需要向数据库发起查询请求, 通常要等待一段数据库执行sql时间, 只有执行结果返回给程序之后, 程序才能执行接下来的任务.
而这段等待的时间里, 程序啥也做不了, 只能干等着; 那这段时间, 服务器的cpu资源就闲置了. 这就是程序被阻塞了.
而大部分的 web 程序, 在处理一次 web 请求中, 通常会被很多外部服务的 IO 操作所阻塞. 很有可能程序处理一次请求的时间是100ms, 但是99%的时间, 程序都在等待 sql 服务器返回结果, 或者是等待外部接口请求返回结果.

  • 阻塞的解决办法

那怎么让 cpu 在程序被阻塞的时候有事可干呢
通常有三种办法:

  1. 多进程: 最简单粗暴的一种方法, 多开一些进程, 每个进程一次只处理一个请求, 可以使用unicorn做多进程服务器
    • 优点是实现简单( 只需要web 程序多开一些进程, 不需要再做其他的开发工作), 安全可靠.
    • 缺点是内存占用高(每个进程之间内存不共享), 效率低(每个进程的执行权需要靠系统来分配, 进程切换的占用的资源开销大).
  2. 多线程: 和多进程类似, 进程变为线程, 最近比较火的puma就是多线程服务器
    • 优点: 相比多进程, 内存占用低(线程之间可以共享内存), 效率比多进程要高, 线程切换效率比进程高
    • 缺点: 所有代码都需要考虑线程安全问题, 出bug 很难调试, 很难保证所有引入的库都是线程安全
  3. 基于事件驱动的异步IO模式
    在高并发, 对性能要求非常高的情况下, 多进程
    /线程的效率都不够高, 需要在代码层来控制阻塞时cpu的切换, 这时候就需要引入新的模式: 异步编程模式.

同步与异步

拿一段常见的 Rails 代码做实例:

  def show
    @post = Post.find(params[:id]) #数据库查询post
    @post.update(last_view_time: Time.now) #更新post
     ...
  end

在执行 Post.find(params[:id]) 时, 程序其实是被阻塞了, 在查询完成之后才会执行后面的代码, 这就是常规的同步模式.

异步模式: 当程序处理请求遇到阻塞的操作时(比如数据库查询), 把后面需要执行的代码放到callback中, 然后直接去处理下一个请求, 直到数据查询完成之后, 再去执行之前的callback代码. 以下是一段ruby异步模式的代码

require "em-synchrony"
require "em-synchrony/em-http"
EM.synchrony do
   concurrency = 2 
   urls = ['http://url.1.com', 'http://url2.com']
   results = EM::Synchrony::Iterator.new(urls, concurrency).map do |url, iter|
       http = EventMachine::HttpRequest.new(url).aget
       http.callback { iter.return(http) } 
       http.errback { iter.return(http) } 
   end 
   p results
   EventMachine.stop
end  

EventMachine::HttpRequest.new(url).aget 是执行异步的http请求, 请求完成后的代码放到了callback中, 程序不会等待 http 请求完成, 而是直接去执行迭代器Iterator中的下个任务. 等http请求完成时才会去执行callback中的代码.

相关文章

  • 基于事件驱动的异步IO (ruby) 系列一

    最近翻了下电脑里几年前记得一些东西, 想把关于 ruby 事件驱动编程的一些知识重新整理下并分享出来 为什么需要...

  • netty

    netty 高性能,异步,事件驱动库 Unix io模型 阻塞io 非阻塞io,netty主要就是基于epoll的...

  • netty 入门杂谈

    java io 模型一共分为4种 传统IO 伪异步IO NIO AIO 介绍 netty是一个高性能,异步事件驱动...

  • 整理一些遇到的问题

    常见的IO模型 单线程阻塞 多线程阻塞 多进程阻塞 非阻塞轮询 事件驱动IO 信号驱动式IO 异步IO(指的是使用...

  • Java8并发编程(使用CompletableFuture)

    java8异步处理 非阻塞IO/异步/并行 使用场景 scala事件驱动 Java CompletableFutu...

  • netty笔记

    Netty是一个高性能事件驱动的异步的非堵塞的IO(NIO)框架,用于建立TCP等底层的连接,基于Netty可以建...

  • Netty初探

    Netty是一个高性能事件驱动的异步的非阻塞的IO(NIO)框架,用于建立TCP等底层的连接,基于Netty可以建...

  • Netty学习(1):IO模型之BIO

    概述 Netty其实就是一个异步的、基于事件驱动的框架,其作用是用来开发高性能、高可靠的IO程序。 因此下面就让我...

  • 【动画详解原理系列】3.事件驱动和异步

    【动画详解原理系列】3.事件驱动和异步

  • Node.js

    一,了解Node.js 1.简介: 基于事件驱动,可以实现异步,非阻塞IO由于早期的网景公司和IE发布的浏览器都采...

网友评论

      本文标题:基于事件驱动的异步IO (ruby) 系列一

      本文链接:https://www.haomeiwen.com/subject/ozeovttx.html