`
bollaxu
  • 浏览: 217112 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

一个高并发服务架构

阅读更多

在研究了Nginx以及开发了几个服务器端的软件之后,对于支持高并发的C程序架构总结一下。一般都是多进程或者多线程。对于多线程,因为是一个process space,好处是线程间共享内存,通信方式相对比较丰富,坏处是如果一个线程出了问题,整个进程就会受到影响。个人比较偏好多进程的结构,在这里,梳理一下主要的架构设计,对于所有需要高并发的服务来说都可以套用。

 

主进程:

 

int main()
{
	//initializations
	//...

	//init socket
	listenfd = socket(...);
	bind(listenfd, ...);
	listen(listenfd, ...);

	//fork worker processes
	for(...)
	{
		pid_t pid = fork();
		//child
		if(pid == 0)
		{
			//worker main cycle
			work_process_cycle();
		}
		//parent
		else
		{
			//...
		}
	}
	
	//...
}

 子进程(worker)

void work_process_cycle()
{
	//init epoll
	int epfd = epoll_create(...);

	//...
	
	//add listenfd to epoll
	struct epoll_event ep_ev;
	ep_ev.data.fd = listenfd;
	ep_ev.events = EPOLLIN | EPOLLET;
	epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ep_ev);
	
	while(1)
	{
		//epoll events
		struct epoll_event events[EPOLL_MAX_EVENTS];
		int nfds = epoll_wait(epfd, events, EPOLL_MAX_EVENTS, EPOLL_TIMEOUT);
		
		for(i = 0; i < nfds; i++) 
		{
			//accept connection
			if(events[i].data.fd == listenfd)
			{
				int connfd = accept(listenfd, ...);
				//add read event
				struct epoll_event ep_ev;
				ep_ev.data.fd = connfd;
				ep_ev.events = EPOLLIN | EPOLLET;
				epoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &ep_ev);
			}
			else if(events[i].events & EPOLLIN)
			{
				//deal with read events
				//recv, read, ...
			}
			else if(events[i].events & EPOLLOUT)
			{
				//deal with write events
				//send, write, ...
			}
		}
		
		//other events
		//process events, timed events, etc.
	}
}
 

 

这儿使用了epoll的IO触发机制,也可以用libevent之类的库来做IO事件监听。注意,如果是高并发服务,一个进程必然同时处理N个不同的连接,这样对于进程内的事件机制需要有一个比较好的设计。比如,对于服务中的某个功能,可以设计一系列的回调函数(callback),以及一个结构体来存放具体的上下文信息。每当完成功能中的某一个回调函数之后,更新事件的下一个回调函数,并将其放入事件队列(event queue),然后在下一个iteration进行FIFO的事件处理并调用回调函数。这样对于每个进程的时间分片就可以做到比较公平。事实上,Nginx正是上述架构的一个很好的例子。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics