local skynet = require("skynet")

skynet.start(start_func)

c服务snlua启动后执行的第一个lua文件里面的主逻辑必定是skynet.start(start_func),由此开始运行lua服务的逻辑

start_func是当前lua服务的初始化函数,也是当前服务的第一个协程的函数

之后在收到非response消息时dispatch_message会创建更多的协程来做逻辑

而调用skynet.start(start_func)的主线程会调度上述这些协程(yield)

dispatch_message(...) 

这就是ctx的消息处理函数(skynet_context.skynet_cb, 返回零(假)时释放消息的内存.那么lua层如何控制呢?c.callback(dispatch_message,false)就是释放内存,c.callback(dispatch_message,true)不释放内存,具体参见vim -t _callback.那么lua层如何控制发消息时不做复制呢?我看skynet.send/call/rawcall都不支持对复制的控制,参见vim -t _send. 底层的默认处理是:对于Lua string直接复制,对于lightuserdata不复制,对于其他类型报错)

dispatch_message将是本服务的发动机(消息驱动机),也就是底层工作线程拿到本服ctx.mq中的一个消息后执行的消息处理函数(vim -t _dispatch_message, 底层由worker thread取到消息后调用这个函数而触发lua函数的调用),也就是本lua服的主线程(虽然线程ID不固定)

dispatch_message每处理完mq中的一个消息都要遍历并执行消息处理过程中fork而没运行的新协程(遍历fork_queue并coroutine.resume())

对于收到的每个非response(prototype!=skynet.PTYPE_RESPONSE)消息启动一个新协程X,用该协程来运行协议类型对应的dispatch函数来处理消息

对于收到的每个response消息,根据session从session_id_coroutine取出协程并恢复执行

协程X运行业务逻辑时可能会“对其他服务做请求并等待结果”或者“睡眠几秒”,这时协程X用yield抛出“CALL”/“SLEEP”等返回值并挂起,主线程根据yield抛出的值对协程做不同处理

CALL -> 协程X已对其他服务发出请求并等待回应 -> 主线程把协程X记录到session_id_coroutine中,下次收到对应的response消息(sessionID一致)时唤醒

SLEEP -> 协程X[已调用skynet.sleep(ti)等定时器返回]或[已调skynet.wait()等其他服务返回,这种情况一般需要用skynet.wakeup()来唤醒,否则协程可能永远沉睡下去了] -> 主线程把协程X记录到session_id_coroutine,并记录sleep_session,对于sleep_session需要用skynet.wakeup(co)唤醒 (session_id_coroutine和sleep_session两者怎么维持数据一致,这个细节还需要结合实例再看看 markbyxds )

skynet.newservice(name,...)

创建lua服务 skynet.rawcall(".launcher", "lua" , skynet.pack("LAUNCH", "snlua", name, ...))

其实是skynet_context_new(module_name("snlua"), param("cmaster"))

即,用snlua服跑着一个lua逻辑服(service/cmaster.lua),snlua创造了一个lua环境的沙盒

除了service/launch.lua自身以外,其他lua服务一般都是由service/launch.lua这个lua服负责创建的

当然,launch服最终还是调用的skynet.launch("snlua","xxx")来创建服务

skynet.launch 

创建c服务, lualib-src/lua-skynet.c -> skynet_command(CTX,"LAUNCH",..) -> skynet_context_new(mod,args)

对于skynet.launch("snlua","xxx"),这是创建c服务snlua然后在它上面跑lua服务xxx

skynet.monitor(service, query)    监控服务退出,细节还没仔细看 markbyxds

skynet.uniqueservice(global,...)

创建一个唯一的服务,调用多次service/***.lua也只启一个实例,比如clusterd和multicastd

global=true时,在所有节点之间是唯一的

其实是用skynet.call(异步变同步)的方式让service_mgr服务创建目标服务(类似于通知launch服创建服务一样)

service_mgr这边如已创建则直接返回服务地址;如没则创建;如正在创建则等结果

skynet.queryservice(global,...) global=true时

如果还没有创建过目标服务则一直等下去,直到目标服务被(其他服务触发而)创建

skynet.rawcall 

向目标服发送无协议的消息并返回response,协程挂起等返回,用同步代码的样式实现异步逻辑

当 A call B 时,如果 B 在回应前就退出了,A 会收到一条异常,并正确的传播到 A 里的 call 调用处;

当 A call B ,而 B 在回应前,A 自己退出了,B 也会收到一条异常,提示 A 已经不在了。但不会影响 B 的执行流程,只是让框架回收一些必要的相关资源。

skynet.call 跟skynet.rawcall的区别是向目标服发送指定协议的消息

skynet.send 跟skynet.call的区别是仅仅发消息而已,不关心返回值也不会让当前协程挂起(非request-response模式)

skynet.wait() 

把当前协程挂起放入session_id_coroutine/sleep_session

当收到等待的消息(会把消息对应的正在等待session放入wakeup_session中)后该协程恢复执行

skynet.sleep(ti) 

类似于skynet.wait(),只是要事先通知底层定时器

等定时器(在ti时间达到后)发来消息时该协程恢复执行

skynet.wakeup(co) 

如果协程co正处于挂起等待的状态(在sleep_session中)则把它加入wakeup_session

本服务的主协程会在调度过程中把wakeup_session中的协程唤醒执行

skynet.ret 在当前协程(为处理请求方消息而产生的协程)中给请求方(消息来源)的消息做回应

skynet.retpack 跟skynet.ret的区别是向请求方作回应时要用skynet.pack打包

skynet.register_protocol 

注册协议:

协议名(name)

协议ID(id)

发送消息的打包函数(pack)

接收消息的拆包函数(unpack)

接收消息的(分发)处理函数(dispatch)

已注册的协议记录在lualib/skynet.lua:proto这个数据结构上

每个服务会默认初始化lua/response/error这几种协议

skynet.dispatch(typename, func) 

修改以typename为协议名的协议:用func这个函数来作为协议的dispatch函数(默认的lua协议没提供dispatch,需要使用者根据业务需要写)

skynet.fork 

创建一个新的协程

这里有做协程对象池来加速,类似于我们项目中的线程池,创建一堆协程并挂起,接到业务后拿协程跑业务逻辑

skynet.register(name)

注册当前服务的名字(默认用:%x作为name,本地服务的自定义名以.打头)

把<handleId + name>记录到handle_storage->name,参数必须符合本地服务的命名规范

skynet.self() 返回当前服务的handleID,如果还没注册就先注册(类似于skynet.register)

skynet.harbor(addr) return “addr(ctx的handleID)对应的harborID",boolean(是否远端节点)

skynet.address(addr) return "addr(ctx的handleID或者name)对应的name(string,:%x或者自定义名)"

skynet newservice API参考的更多相关文章

  1. Google地图接口API之Google地图 API 参考手册(七)

    Google 地图API 参考手册 地图 构造函数/对象 描述 Map() 在指定的 HTML 容器中创建新的地图,该容器通常是一个DIV元素. 叠加层 构造函数/对象 描述 Marker 创建一个标 ...

  2. Google Chart API 参考 中文版

    Google Chart API 参考 中文版 文档信息 翻译: Cloudream ,最后修改:02/22/2008 06:11:08 英文版版权归 Google , 转载此中文版必须以链接形式注明 ...

  3. Zepto Api参考

    zepto API参考 简介 Zepto是一个轻量级的针对现代高级浏览器的JavaScript库, 它与jquery有着类似的api. 如果你会用jquery,那么你也会用zepto. 设计目的 ze ...

  4. PJSUA2开发文档--第十二章 PJSUA2 API 参考手册

    12 PJSUA2 API 参考手册 12.1 endpoint.hpp PJSUA2基本代理操作.  namespace pj PJSUA2 API在pj命名空间内. 12.1.1 class En ...

  5. Dubbo -- 系统学习 笔记 -- API参考手册

    Dubbo -- 系统学习 笔记 -- 目录 API参考手册 配置API 注解API 模型API 上下文API 服务API API参考手册 Dubbo的常规功能,都保持零侵入,但有些功能不得不用API ...

  6. nvGRAPH API参考分析(二)

    nvGRAPH API参考分析(二) nvGRAPH Code Examples 本文提供了简单的示例. 1. nvGRAPH convert topology example void check( ...

  7. nvGRAPH API参考分析(一)

    nvGRAPH API参考分析(一) 本文通过描述nvGRAPH库函数的输入/输出参数,数据类型和错误代码来指定其行为. 1.    返回值nvgraphStatus_t 除以下内容外,所有nvGRA ...

  8. Django,数据模型创建之数据库API参考(转载)

    一旦 数据模型 创建完毕, 自然会有存取数据的需要.本文档介绍了由 models 衍生而来的数据库抽象API,及如何创建,得到及更新对象. 贯穿本参考, 我们都会引用下面的民意测验(Poll)应用程序 ...

  9. 阿里云API网关(7)开发指南-API参考

    网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...

随机推荐

  1. delphi按钮控件的default属性

    delphi按钮控件的default属性用于设置默认命令按钮,.设置为true时,按[Enter键]相当于用鼠标单击了该按钮 .窗口中如果有多个按钮的default是true的话,就根据tabinde ...

  2. AngularJS之Factory vs Service vs Provider

    原文  http://www.linuxeden.com/html/news/20140509/151538.html 当你初试 Angular 时,很自然地就会往 controller 和 scop ...

  3. 纯css改变下拉列表select框的默认样式

    下列CSS就可以解决,原理是将浏览器默认的下拉框样式清除,然后应用上自己的,再附一张向右对齐小箭头的图片即可. select { /*Chrome和Firefox里面的边框是不一样的,所以复写了一下* ...

  4. %hd %d %ld %u ......

    %d 有符号10进制整数 %ld 长整型 %hd短整型%md,m指定的是输出字段的宽度,默认左补空格, 如果数据的位数小于m,则左端补以空格,若大于m,则 按实际位数输出,如: printf(&quo ...

  5. 资源回收 left

    select DISTINCT human.tid,log_pv_change.systafftid from human left join human_user on human.tid=huma ...

  6. python学习day12

    目录 html结构与标签 css样式   html结构之head <head> 标签用于定义文档的头部,它是所有头部元素的容器.<head> 中的元素可以引用脚本.指示浏览器在 ...

  7. 一个失误导致微信下载图片接口Token失效

    公司的应用调了一个微信上传下载图片的接口,本来在线上跑的好好的,什么问题没有,但是这两天总是不定时的出现下载下来的图片损坏,拿着Token和serverid去接口测试网页验证,返回的是Token失效了 ...

  8. MySQL 5.6 中 TIMESTAMP 的变化

    http://www.williamsang.com/archives/818.html

  9. 开源日志库log4cplus+VS2008使用

    一.简介     log4cplus是C++编写的开源的日志系统,功能非常全面.本文介绍如何在Windows+VS2008中使用该日志库.   二.下载     可从网站[url]http://log ...

  10. C# 线程池异步调用

    许多应用程序使用多个线程,但这些线程经常在休眠状态中耗费大量的时间来等待事件发生.其他线程可能进入休眠状态,并且仅定期被唤醒以轮询更改或更新状态信息,然后再次进入休眠状态.为了简化对这些线程的管理,. ...