码迷,mamicode.com
首页 > Web开发 > 详细

skynet源码分析:Socket

时间:2018-07-05 14:52:21      阅读:183      评论:0      收藏:0      [点我收藏+]

标签:for   分析   理解   处理   端口   fork   github   com   文件   

skynet 的 C API 采用异步读写,你可以使用 C 调用,监听一个端口,或发起一个 TCP 连接。但具体的操作结果要等待 skynet 的事件回调。skynet 会把结果以 PTYPE_SOCKET 类型的消息发送给发起请求的服务。(参考skynet_socket.h)

在处理实际业务中,这样的 API 很难使用,所以又提供了一组阻塞模式的 lua API 用于 TCP socket 的读写。它是对 C API 的封装。

所谓阻塞模式,实际上是利用了 lua 的 coroutine 机制。当你调用 socket api 时,服务有可能被挂起(时间片被让给其他业务处理),待结果通过 socket 消息返回,coroutine 将延续执行。

 

SocketChannel


请求回应模式是和外部服务交互时所用到的最常用模式之一。通常的协议设计方式有两种。

  1. 每个请求包对应一个回应包,由 TCP 协议保证时序。redis 的协议就是一个典型。每个 redis 请求都必须有一个回应,但不必收到回应才可以发送下一个请求。

  2. 发起每个请求时带一个唯一 session 标识,在发送回应时,带上这个标识。这样设计可以不要求每个请求都一定要有回应,且不必遵循先提出的请求先回应的时序。MongoDB 的通讯协议就是这样设计的。

对于第一种模式,用 skynet 的 Socket API 很容易实现,但如果在一个 coroutine 中读写一个 socket 的话,由于读的过程是阻塞的,这会导致吞吐量下降(前一个回应没有收到时,无法发送下一个请求)。

对于第二种模式,需要用 skynet.fork 开启一个新线程来收取回应包,并自行和请求对应起来,实现比较繁琐。

所以、skynet 提供了一个更高层的封装:socket channel 。

 

关于 socket channel 的具体用法除了阅读 lualib/socketchannel.lua (同时这也是理解 socket 模块的好材料)的实现外,也可以阅读 lualib/redis.lua 和 lualib/mongo.lua 这两个为 skynet 编写的数据库 driver 。

 

mysql

在这个 fork https://github.com/chfg007/skynet 里,实现了 mysql 的 driver (改自 OpenResty)。

主要文件为 lualib/mysql.lua 和 3rd/lua-mysqlaux

local status, err = pcall(mysqldb.query,mysqldb,sqlstr) 记得捕获错误,有可能查询的时候链接已经断开。

 

https://github.com/cloudwu/skynet/wiki/SocketChannel

skynet源码分析:Socket

标签:for   分析   理解   处理   端口   fork   github   com   文件   

原文地址:https://www.cnblogs.com/losophy/p/9267937.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!