【skynet】skynet阻塞接口的原理剖析

skynet阻塞接口的原理剖析:

假设在lua代码中调用如下接口:

local res, err = socket.open("127.0.0.1", 6379)
if not res then
	print(err)
else
	print("hello")
end

即调用到C代码的driver.connect,然后调用local function connectsuspend函数挂起当前协程,等待connect返回信息。

function socket.open(addr, port)
	local id = driver.connect(addr,port)
	return connect(id)
end
local function connect(id, func)
	local newbuffer
	if func == nil then
		newbuffer = driver.buffer()
	end
	local s = {
		id = id,
		buffer = newbuffer,
		pool = newbuffer and {},
		connected = false,
		connecting = true,
		read_required = false,
		co = false,
		callback = func,
		protocol = "TCP",
	}
	assert(not socket_onclose[id], "socket has onclose callback")
	assert(not socket_pool[id], "socket is not closed")
	socket_pool[id] = s
	suspend(s)
	local err = s.connecting
	s.connecting = nil
	if s.connected then
		return id
	else
		socket_pool[id] = nil
		return nil, err
	end
end

function socket.open(addr, port)
	local id = driver.connect(addr,port)
	return connect(id)
end

connect请求返回后,触发了事件类型TYPE是OPEN,因此调用到如下函数,注意到调用wakeup函数唤醒阻塞的协程

-- SKYNET_SOCKET_TYPE_CONNECT = 2
socket_message[2] = function(id, _ , addr)
	local s = socket_pool[id]
	if s == nil then
		return
	end
	-- log remote addr
	if not s.connected then	-- resume may also post connect message
		s.connected = true
		wakeup(s)
	end
end

最后lua代码就可以继续向下执行了,返回了res, err。

skynet中所有的阻塞接口如skynet.call、skynet.sleep、skynet.read都是利用了这个特性:底层是调用C函数,C函数调用真正的系统API,然后挂起调用skynet阻塞接口的协程。等系统API的请求返回后,通过返回消息的类型,调用不同的socket_message函数处理,最后唤醒协程。

这样做的好处是:

  1. 在lua代码中,使用这些API就像是同步阻塞调用,其实本质上是一个异步回调的过程。使代码看起来比较简单易懂
  2. 在一个工作线程处理服务的消息队列的消息时,如果当前消息调用了阻塞API,那么当前消息对应的协程挂起,工作线程继续处理消息队列的下一条消息,运行另一个协程。这提高了一个工作线程的并发性(如果是线程直接调用系统API阻塞,导致线程切换的开销比协程切换开销大得多)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值