协程(纤程,微线程)这个概念早就有之,各家互联网公司也都有研究,但在国内各大论坛和大会热起来,还是今年的事。

最近参与讨论开放平台建设和架构设计过程中,有同事提到了使用协程代替线程,能够很大幅度的提高性能。这引发了我们团队极大的兴趣和激烈的讨论。

首先,说明一下什么是协程。

协程是用户态的线程。传统上线程的切换是由操作系统控制的,并且,每次切换都涉及到上下文的保存切换和用户态与内核态之间切换的过程。而协程的切换是由用户自己控制的,并且每次切换只涉及到上下文的保存与切换(即栈的出栈和入栈的过程)。由于同时可能存在多个线程操作同一个资源的问题,使用线程在必要的情况下需要使用“等待-加锁-释放”这样一套动作。而对于同一个线程中的协程同时操作同一个资源时,则没有这样的问题,因为同一个线程中的所有协程都是串行执行的。当然这样也导致了一个问题:架构在同一个线程中多个协程之上的程序,是无法利用多核资源的。最后,协程还有一个好处,则是协程能够产生更高可读性的代码。

在提出了协程之后,我也提供其他几个可供比较的概念。进程,线程,回调。 
      进程和线程就不多说了。了解一个进程包含一个或者多个线程,一个线程包含一个或者多个协程。在Linux中,创建进程和线程耗费的资源是一致的。
      这里强调一下回调。回调函数相对于协程而言,不会造成上下文的保存和切换,因此切换速度最快,但是也造成了使用回调函数没有上下文的问题。当需要上下文时,只能使用全局变量来保存,不符合大部分程序员的编程习惯。

然后,描述一下是因为什么问题导致了我们发现需要协程的。 
      在高并发应用中,尤其是Web应用,每台服务器都同时会有n多的连接和逻辑处理,每个连接之间没有逻辑关联。传统上对于每个连接请求,都会创建一个进程或者线程来处理该请求(先进一 点的会使用池化技术),这样如果某种类型的请求的处理线程由于各种问题导致处理耗时过长,则由于时间片全部耗费在此线程上导致问题非常严重,会因为一个请 求的问题导致所有请求都变慢或者不可用。
       我们希望当某个请求出现问题时,不会影响到其他的请求。

纯粹的将请求种类强制划分开来,不同线程处理不同的请求是可以解决这个问题的,但是,终归会有部分CPU耗费在处理时间很长的请求上,另外,更换应用的时候,总会有大量配置甚至代码级别的更新,并非完美的解决方案。
      将同步处理过程转化为异步当然也可以解决此问题。但并非所有的同步处理过程都可以异步处理。

 

协程是如何解决这个问题的。

《Windows核心编程 via C/C++》一书说:fiber(Windows中的协程叫做纤程fiber)只是为了使Unix的程序更加容易移植到Windows上来而提供的,建议Windows开发者不要使用fiber。我觉得这其实是不全对的,需要看场景。作者说不要使用fiber,是因为上下文的保存和切换可以由线程来解决而回调函数可以解决在同一线程中内的切换问题,一样不需要锁,并且速度更快。但在高并发应用中,则不一样,面对回调需要使用编程复杂的状态机和令人绝望的调试,fiber的上下文保存和切换则轻松的替换掉这些,并且编程实现上非常干净和漂亮。这是我们选择使用协程的原因。

当然,问题并非协程就可以解决。首先异步IO与之结合是不可避免的。其次对任何一个Web服务器,后端都有非常多的Service的。一个Request,可能会涉及到多个Service。这就需要使用Furture模式,使任何一个Request只需要等待时间最长的一个Service而不用串行等待所有的Service。再次,比较复杂的是,对于协程的调度,我们需要实现一个调度器,使对协程的调用,总是能调度到请求Service完成的协程上,而没有完成的协程,则不会被调度。

结合这些设计元素,一个使用协程的Web服务器就能高效的运作起来。

协程应用场景

http://blog.csdn.net/huyiyang2010/article/details/6042326

协程在Web服务器中的应用(配的图还不错)的更多相关文章

  1. 简单介绍什么是协程及其在ES6中的实现方式

    协程,英文名coroutine,是一种执行过程可以被暂停和恢复的方法.各个协程之间相互协作完成一个任务. 让我们来看一个关于发挥协程作用的例子.假定我们有一个生产者和消费者的关系,生产者创建物品并将物 ...

  2. 您的请求在Web服务器中没有找到对应的站点”这是什么原因?出现这个界面说明域名解析已经正确并生效,这是由于域名没有绑定好,

    宝塔出现 您的请求在Web服务器中没有找到对应的站点"这是什么原因?出现这个界面说明域名解析已经正确并生效,这是由于域名没有绑定好 , 本人经过测试使用如下方法解决.允话空HTTP_REFE ...

  3. python day 20: 线程池与协程,多进程TCP服务器

    目录 python day 20: 线程池与协程 2. 线程 3. 进程 4. 协程:gevent模块,又叫微线程 5. 扩展 6. 自定义线程池 7. 实现多进程TCP服务器 8. 实现多线程TCP ...

  4. php在web服务器中的工作原理

    1.web工作原理 我是学习PHP网站建设的,那么网站在客户端和服务端的运行是网站运行的根本所在,那个这个运行过程是怎样的呢?我们一探就将! Web:终端 服务器web:我们把提供(响应)服务的计算机 ...

  5. web服务-2、四种方法实现并发服务器-多线程,多进程,协程,(单进程-单线程-非堵塞)

    知识点:1.使用多线程,多进程,协程完成web并发服务器 2.单进程-单线程-非堵塞也可以实现并发服务器 1.多进程和协程的代码在下面注释掉的部分,我把三种写在一起了 import socket im ...

  6. 用python实现自己的http服务器——多进程、多线程、协程、单进程非堵塞版、epoll版

    了解http协议 http请求头 GET / HTTP/1.1 Host: www.baidu.com Connection: keep-alive Pragma: no-cache Cache-Co ...

  7. Python中异步协程的使用方法介绍

    1. 前言 在执行一些 IO 密集型任务的时候,程序常常会因为等待 IO 而阻塞.比如在网络爬虫中,如果我们使用 requests 库来进行请求的话,如果网站响应速度过慢,程序一直在等待网站响应,最后 ...

  8. C#中使用Socket实现简单Web服务器

    上一篇博客中介绍了怎样使用socket访问web服务器.关键有两个: 熟悉Socket编程: 熟悉HTTP协议. 上一篇主要是通过socket来模拟浏览器向(任何)Web服务器发送(HTTP)请求,重 ...

  9. Unity中的协程(一)

    这篇文章很不错的问题,推荐阅读英文原版: Introduction to Coroutines Scripting with Coroutines   这篇文章转自:http://blog.csdn. ...

随机推荐

  1. 【cocos2dx 3.2】瓦片地图制作

    使用Tiled编辑地图 每个图层仅仅能放一种瓦片 瓦片的大小最好是32*32的倍数 对象层里面设置路径的坐标 主程序中获取对象层中的坐标,做对应的操作 设置口袋精灵类: Monster.h #incl ...

  2. Objective-C基础笔记(8)Foundation经常使用类NSString

    一.创建字符串的方法 void stringCreate(){ //方法1 NSString *str1 = @"A String!"; //方法2 NSString *str2 ...

  3. 【转】dbx用法讲解

    http://blog.chinaunix.net/uid-25544300-id-328735.html dbx 命令 用途 提供了一个调试和运行程序的环境. 语法 dbx [ -a Process ...

  4. 从Handler+Message+Looper源代码带你分析Android系统的消息处理机制

    PS一句:不得不说CSDN同步做的非常烂.还得我花了近1个小时恢复这篇博客. 引言 [转载请注明出处:http://blog.csdn.net/feiduclear_up CSDN 废墟的树] 作为A ...

  5. <a href='javacript:' title='{$str}'>是什么意思(多看学习视频)

    <a href='javacript:' title='{$str}'>是什么意思(多看学习视频) 一.总结 一句话总结: 1.javascript:是什么? 伪协议,后面接javascr ...

  6. nopCommerce 3.9 接口笔记

    接口笔记 Nop.Services.Configuration ISettingService : 配置接口(查看) Nop.Services.Localization ILocalizationSe ...

  7. 数组[0]和[firstobject]的区别

    数组[0]和[firstobject]的区别   [0]:数组为空时回报错 [firstobject]:数组为空时回返回nil

  8. 递归(c++)(转)

    1.什么是递归函数(recursive function) 递归函数即自调用函数,在函数体内部直接或间接地自己调用自己,即函数的嵌套调用是函数本身. 例如,下面的程序为求n!: long fact(i ...

  9. 最新版Butterknife plugin支持butterknife7.0.1和兼容butterknife 6.1.0及下面

    JakeWharton 的butterknife帮我们有效的攻克了findViewById及各种view的监听事件泛滥的问题,极大的简化了代码,假设使用了android Studio开发的配上avas ...

  10. React Native细节记录

    1.环境搭建部分 安装完node后建议设置npm镜像以加速后面的过程(或使用***工具).注意:不要使用cnpm!cnpm安装的模块路径比较奇怪,packager不能正常识别! npm config ...