Chinaunix首页 | 论坛 | 博客
  • 博客访问: 62120
  • 博文数量: 15
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 17
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-11 10:52
文章分类
文章存档

2015年(3)

2014年(5)

2013年(7)

我的朋友

分类: LINUX

2014-11-19 15:53:24

            多线程框架需要完成的任务
            (1) 作为一个服务器,它需要负责listen一个或多个端口,当有用户请求过来时,需要accept建立连接,完成连接后,需要监听每个建立好连接的socket是否可读或者可写。如果用户请求的内容没有保存在本地cache上,需要与源服务器建立连接,同样,也需要监听建立的socket是否可读或者可写。
            当trafficserver启动后,有三个进程,traffic_cop,traffic_manager以及traffic_server。其中traffic_manager进程用于listen,traffic_manager通过系统调用fork产生子进程traffic_server,traffic_server创建一组线程用于accpet,同时创建一组线程作为工作线程。
            (2) 高并发产生的c10k问题的解决。在多线程模型下,c10k的i/o策略包含有这么两种:"one OS-level thread handles many clients; each client is controlled by a state machine"以及"one OS-level thread handles many clients; each client is controlled by a continuation"。一个state machine由一组有序的continuation构成,一个continuation完成后,thread会执行下一个continuation。这两种策略的区别在于,对于第一种策略,整个state machine的所有continuation都是由一个thread来完成的,而对于第二种策略,由于thread处理的单位是一个continuation,所以一个state machine可能会由几个thread完成(个人看法)。
            trafficserver采用的是第二种i/o策略,同时,采用event-based的机制来调度线程完成每个continuation。在trafficserver中,类Continuation是所有不同类型的continuation的父类,它提供一个回调函数指针,执行一个continuation就是执行这个回调函数。类Event代表的是一个event,它封装了一个Continuation,类Ethread代表的是一个线程,线程的调度是由类Processor的子类EventProcessor来完成。
            trafficserver创建两种类型的线程,regular与dedicated类型。一个dedicated类型的线程,它在执行完某个continuation后,就消亡了。
            regular类型的线程,在trafficserver启动后,就一直存在着,它的线程执行函数是一个死循环。regular线程维护了一个event pool,当event pool不为空时,线程就从event pool中取出event,同时执行event封装的continuation。当需要调度某个线程执行某个continuation时,通过EventProcessor将一个continuation封装成一个event并将其加入到线程的event pool中。
            (3) 定时器的支持。trafficserver将event分为以下几种类型:立即执行的event,定时执行的event,定期执行的event以及随时执行的event。一个event包含一个timeout时间,一个period时间,timeout是一个非负数,period没有限制。
            1) 当timeout等于0,该event是一个立即event。
            2) 当period等于0,该event是一个定时event,timeout时间到期后event就会执行。
            3) 当period大于0,该event是一个定期执行的event,每隔period就会执行一次。
            4) 如果period小于0,event是一个随时执行的event,当线程执行完其他类型的event后,就会执行这一类event。目前ts只有一种该类型的event,就是epoll,这样在工作线程没有其他任务时就立即执行epoll_wait。
            为了支持定时器,trafficserver将线程的event pool细分为一个外部队列与一个内部队列,以及一个优先级队列。当调度某个线程执行某个event时,EventProcessor将该event加入到线程的外部队列中。线程从外部队列中取出event加入到自己的内部队列处理,同时,将定时或者定期event加入到优先级队列中。优先级队列是一个粗粒度的管理定时event执行的队列,它根据时间段的大小维护了不同的桶,不同时间后执行的event加入到不同的桶中。
            eventsystem核心代码与数据结构
  1. EThread::execute                      //对应线程执行函数,对于regular类型的线程,是一个死循环
  1. //这一组函数,选择类型与EventType参数值相同的那组线程,从该组线程中以round robin方式选出一个线程,
  2. 将event插入到该线程的外部队列中
  3. EventProcessor::schedule_imm          //立即执行event
  4. EventProcessor::schedule_at           //将来某个确定的时间点执行event
  5. EventProcessor::schedule_in           //一段时间以后执行event
  6. EventProcessor::schedule_every        //定期或随时event,根据参数给出的时间是正值还是负值
  1. EThread::schedule_*                   //这一类函数大致与EventProcessor提供的相同
  2. EThread::schedule_*_local             //这一类函数与上面的唯一不同是,将event直接加入内部队列中
  1. Event::schedule_*                     //这一类函数也是将event直接加入到对应线程的内部队列中
  1. //这两个函数其实是专为网络模块设计的,一个线程可能一直阻塞在epoll_wait上,通过引入一个pipe或者eventfd,当调度一个线程执行某个event时,异步通知该线程从epoll_wait解放出来。
  2. EThread::schedule_imm_signal          
  3. EventProcessor::schedule_imm_signal
            使用eventsystem异步执行某个函数的方法
            (1) 首先,定义一个Continuation的子类
  1. class Example : public Continuation
  2. {
  3. public:
  4.     Example();
  5.     ~Example();
  6.     int main_event(int event, Event *e);   //将执行的代码写入该函数
  7. };
            (2) 通过EventProcessor提供的接口异步执行
  1. Example *e = new Example();                         //创建一个对象
  2. SET_CONTINUATION_HANDLER(e, &Example::main_event); //设置异步执行的函数
  3. eventProcessor.schedule_imm(e, ET_CALL);           //异步执行,eventProcessor是ts提供的全局变量
            
          
            
阅读(1492) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~