zoukankan      html  css  js  c++  java
  • skynet的协程

    之前对skynet的印象,主要是来自于我对golang的理解,对gevent开发的经验,以及云风的blog。对于底层的代码,并没有仔细去阅读过。最近在实现业务系统的时候,发现有同事在同一个函数里做了一个互斥的判断,才发现对skynet的理解有误。

    以前,用python的gevent框架实现游戏服务器的时候,会针对每个玩家建立3-5个greenlet(协程),用于处理玩家身上的定时器事件,以及IO操作。然后还有少数几个协程处理全局的定时器事件。当然,战斗是放在独立的进程中实现的,那边基本上每个怪都有1-2个greenlet,一个房间里有几十个greenlet是很正常的。总结起来,就是python+gevent为了规避全局锁,采用了多进程,每个进程多greenlet的实现方式。

    而对于golang,会变成底层是多线程模型,上面跑着多个goroutine,当一个goroutine发起阻塞式IO的时候,底层负责跑这个goroutine的线程,可以随之阻塞等待。系统便随即开一个新的线程,从一堆goroutine里挑一个可以执行的,继续执行。golang就相当于用多线程,取代了以前py的多进程。

    读完云风的blog,我对skynet的理解,就是每个线程来跑一个Lua的VM,一系列的VM组成了一个队列。然后每个VM有自己的消息队列,VM运行时,就从自己的消息队列里,拿出一条消息执行。得益于Lua的沙盒机制,即使某个VM发生traceback,也能得到有效隔离。同时,因为同处一个进程内,VM之间数据交互可以做到相当高效,字符串之类的传递只要传指针即可。

    但是,我之前忽略了Lua协程在其中发挥的作用。原来,一个服务(即一个VM)收到一个包req,就会新建一个协程进行处理。处理过程中,如果产生一个对外的call请求,req包是当成处理完的,当前的协程是会刮起,等待call请求返回来唤醒。这时候服务可以继续建立新的协程来处理新的消息包,而不会阻塞住。也就是说,如果处理一个包的过程中,发生了skynet.call调用,是会造成多个协程并发执行的。如果不注意用锁保护协程间的共享资源,就有可能出现问题。

  • 相关阅读:
    lucene索引合并与增量索引
    Lucene全文搜索 分组,精确查找,模糊查找
    lucene3.6.1 经典案例 入门教程 (包含从文件中读取content)
    lucene特殊字符处理
    http://www.iteye.com/job/topic/1133159
    org.apache.lucene.queryParser.ParseException: Encountered "<EOF>" at line 1, column 0.
    浏览器查看和手动设置cookie的值
    HttpWebRequest 基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系
    SqlServer 行转一列逗号隔开
    大批量delete 优化方案
  • 原文地址:https://www.cnblogs.com/Lifehacker/p/skynet_coroutine.html
Copyright © 2011-2022 走看看