tars框架

tars-server

双向缓存

tars网络框架基于目前流行的epoll多路复用模型实现,tars在实现自身网络功能时又丰富了很多功能,这里简单说下收发缓存,或叫做队列的东西。

发送大体过程


发送时,放队列,通过notifyFd 通知网络线程进行处理Pipe,实际就是处理发送队列;tars原生代码默认采用ET模式,所以只要mod时只要重新添加一次EPOLLOUT,就能触发notifyfd写事件(当然,这里仅仅是触发事件,并不真正写,而是去处理其他connection的数据);

send 或 writev 触发EAGAIN 或 EINTER时,则把数据放入connection缓存中,后面会自动触发 fd 自身的EPOLLOUT 来发送剩余数据;

关键 fd

  • notifyFd: 属于网络线程,用于通知发送数据,同时添加了:IN 、OUT 、ET
  • closeFd: 同notifyFd,只不过忽略,close事件在已检测到就执行了相关逻辑;
  • fd: 普通客户端fd,连接后同时添加了:IN 、OUT 、ET

二级队列


1:网络线程收发队列;2:connection收发队列

  • 接收-1级队列: 数据先放connection自身缓存;

  • 接收-2级队列: 当接收完,封装成包,放入adapter(协议:端口绑定)的接收队列(链表类),并通知处理

  • 发送-1级队列: 发送包放入络线程发送队列(链表类),通知notifyFd,发送;

  • 发送-2级队列: 若发送不完,将数据memcpy到connection自身缓存, 等待触发EPOLLOUT

tars协程

声明:
因工作中用到tars,且使用到了协程模式,并遇到过一点问题,在工作之余对tars源码进行了研究学习(主要涉及:网络,rpc,超时,clientproxy,多线程,协程等,以及其他内容),这里仅关于tars框架中协程部分的代码阅读,概要整理,仅供参考,若其中有错误不足,欢迎博友们给出建议,协程涉及的proxy部分暂未形成文档;

协程具体执行逻辑,需前后联系,结合网络线程;

协程解决问题:
主要多线程环境下:锁问题、并发问题、cpu利用率问题;属于一个线程(主线程 或其他线程)

4个主要类:
standard_stack_allocator(协程栈分配管理)
CoroutineInfo(支持链表,有自己的ID)
CoroutineScheduler(包含所属servanthandle指针)
Coroutine(继承TC_Thread,包含一个协程调度器)

5中状态:free:刚创初始化时;active:活动的; avail:可用的;inactive:不活动的;timeout:超时的;
5个链表: 5中状态对应各自链表,
1个数组: CoroutineScheduler::CoroutineInfo** _all_coro:所有协程;
2个回调:

一个协程切换后执行:corotineEntry函数,创建协程时,传入:make_fcontext;在协程切换时自动执行;内部调用 jump_fcontext真正切换上线文;
一个业务回调,在创建协程时指定;最终由corotineEntry调用,执行完业务回调,切换到主协程;业务回调实际是Corotine类的函数,这样转到了业务线程;
相关操作:

1:获取协程:若已创建的用完 或 free空了,则再增加一批:每次100个;从free获取,并从free删除,放入avail链表,并设置业务回调函数(每次可能不同);返回其id(对应_all_coro下标);
2:yield:将当前协程id放入needActive链表,协程放入inactive链表,并切换到mainCoro;
3:sleep:将当前协程id放入timeoutMap,协程放入timeout链表,并切换到 mainCoro;
4:事件完成:put( id ):将协程放入活动队列:activeCoroQueue;
5:switchCoro:设置currentCoro = toCoro; jump_fcontext:切换上线文;
6:协程执行:执行协程里指定的业务逻辑函数,并将此协程移到 freelist,切换回mainCoro;
循环调度器:run:(由Corotine->run->handleCoro函数调用):

1:若avail 和 active链表都空,则wait 1秒;
2:顺序的:wakeup:超时map里的协程移到到active链表;needActive的移到avail链表;activeQueue中协程移到active链表;
3:若:active不空,前100个协程,依次调用
4:若:avail不空,将其中所有协程处理完:switchCoro( mainCoro, toCoro);
问题:参考:https://segmentfault.com/a/1190000019154852 0:
相关函数:

1:intptr_t jump_fcontext( fcontext_t * ofc, fcontext_t const* nfc, intptr_t vp, bool preserve_fpu = true);
跳转到 nfc 上线文代表的协程;vp 是传给 nfc 协程入口的参数,preserve_fpu和浮点处理单元有关;
2:fcontext_t * make_fcontext( void * sp, std::size_t size, void (* fn)( intptr_t) );
创建协程上下文,设置协程栈指针,大小,及协程入口函数
其他:
1:指定栈方式:make_fcontext指定给协程分配的栈,同时指定协程切换的跳转地址;
2:栈切换方式:jump_fcontext将当前线程栈保存到当前协程栈,并恢复新协程的栈内容到当前线程栈;
3:栈操作内容:通用寄存器,一个fpu,及媒体指令集:mmx,一个控制字寄存器;

服务端:可开启协程,提高并发
客户端:分同步、异步方式,都可以开启协程;

PS:仅供交流学习,若有错误请指出,感谢支持!

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值