Golang 网络库 evio 一些问题/bug和思考

新博客链接:https://note.mogutou.xyz/articles/2019/08/15/1565876205121.html

Fast event-loop networking for Go

最近翻了 evio 的源码,发现一些问题,主要集中在 linux 平台 epoll 上和读写的处理。

  • 用来唤醒 epoll 的 eventfd 写入数据没有读出
  • listen 的 fd 注册到所有事件循环,epoll 的惊群问题
  • loopWrite 在内核缓冲区满,无法一次写入时,出现写入数据丢失

eventfd 的使用问题

在 internal/internal_linux.go 中封装了 epoll 的使用 API 。

// Poll ...
type Poll struct {
   
	fd    int // epoll fd
	wfd   int // wake fd
	notes noteQueue
}

在 OpenPoll 时,会创建一个 eventfd 并将 fd 赋值给 Poll 的 wfd 成员, 并且注册到 epoll 监听可读事件。

当需要唤醒当前 epoll 时,提供了 Trigger 方法

// Trigger ...
func (p *Poll) Trigger(note interface{
   }) error {
   
	p.notes.Add(note)
	_, err := syscall.Write(p.wfd, []byte{
   0, 0, 0, 0, 0, 0, 0, 1})
	return err
}

这是往刚刚提到的 eventfd 中写入八字节数据,此时 epol l会被唤醒 epoll_wait 函数返回。 但是,evio 并没有去把 8 个字节的数据读取出来,内核缓冲区会不断积压,并且 evio 使用的是 epoll 的LT模式(默认模式),只要缓冲区中有数据,epoll 就会不断唤醒。这应该算是一个 bug 吧。

listen 的 fd 注册到所有事件循环,epoll 的惊群问题

evio 可以指定启动多个事件循环。evio 将 listen fd 注册到每一个事件循环中(epoll)监听可读事件,所以当一个连接到来时,所有的事件循环都会唤醒。

// create loops locally and bind the listeners.
	for i := 0; i < numLoops; i++ {
   
		l := &loop{
   
			idx:     i,
			poll:    internal.OpenPoll(),
			packet:  make([]byte, 0xFFFF),
			fdconns: make(map[int
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值