Linux 服务器模型

当我们用socket进行编程的时候,细节上都是选择一个AF_LOCAL,AF_INET再根据相应的类型填充地址,其实根据通信需求,有几种简单的服务模型可供选用,掌握了这些框架再结合socket高度的抽象,可以为我们编写简单的服务器程序提供指导

循环服务

用户请求服务需要排队,服务器一次只能服务一个客户,服务完才能对下一个客户进行服务。ATM机就是这个1vs1模型。udp服务器也经常使用这个模型

//模型伪代码
main{
    //获得侦听文件描述符
    listenfd=socket();

    //准备地址addr

    //(listenfd,100);

    while(1){将服务器的addr和listenfd绑定
    bind(listenfd,addr)

    //开始侦听,设置缓冲队列长度
    listen(listenfd,100);

    while(1){
        //如果侦听到任务就获取sockfd
        int sockfd = accept(listenfd);  //listenfd默认是阻塞IO,没任务时进程会sleep

        //通信...

        close(sockfd);
    }
}

多进程并发服务

多进程只是放listen到请求的时候,不是在原进程中处理请求,而是在子进程中处理,父进程继续侦听请求。多进程的好处父进程不必等待子进程处理完一个请求才能获取下一个请求,而是只要有请求就fork一个子进程处理,这样就可以实现并发服务器。多进程并发的更实际的方案是使用进程池来实现。

//模型伪代码
main{
    //获得侦听文件描述符
    listenfd=socket();

    //准备地址addr

    //将服务器的addr和listenfd绑定
    bind(listenfd,addr)

    //开始侦听,设/准备地址add置缓冲队列长度
    listen(listenfd,100);

    while(1){
        //如果侦听到任务就获取sockfd
        int sockfd = accept(listenfd);  //listenfd默认是阻塞IO,没任务时进程会sleep
        pid=fork();
        if(0 == pid){
            //子进程一定要首先关闭listenfd,防止和父进程一起侦听
            //也可以在父进程socket(,,SOCK_CLOEXEC);
            close(listenfd);

            while(1){
                ret=read(sockfd);
                if(0 == ret) break;
                //通信...
            }

            exit(0);
        }
    }
}

多线程并发服务

使用多线程实现并发和多进程类似,但是创建一个线程的开销比创建一个进程小得多,需要注意的是使用多线程需要做好对临界资源的保护。实际操作经常使用线程池来实现多线程并发服务。

//模型伪代码
void* communicate(void* arg){
    int sockfd=(int)arg;
    while(1){
        ret=read(sockfd);
        if(0 == ret) break;
        //通信...
    }
}

main{
    //获得侦听文件描述符
    listenfd=socket();

    //准备地址addr

    //将服务器的addr和listenfd绑定
    bind(listenfd,addr)

    //开始侦听,设置缓冲队列长度
    listen(listenfd,100);

    while(1){
        //如果侦听到任务就获取sockfd
        //listenfd默认是阻塞IO,没任务时进程会sleep
        int sockfd = accept(listenfd);  
        pthread_create(tid,communicate,(void*)&sockfd);
        }
    }
}

I/O多路复用并发服务

I/O多路复用实现并发服务我已经在Linux I/O多路复用一文中举出了详细的例子,其实质就是将udp服务器的循环模型用在tcp上。

//模型伪代码
main{
    //获得侦听文件描述符
    listenfd=socket();

    //准备地址addr

    //将服务器的addr和listenfd绑定
    bind(listenfd,addr)

    //开始侦听,设置缓冲队列长度
    listen(listenfd,100);

    //准备侦听对象,和相应的触发事件的集合
    monitor_set_1[i]={fds...}   //监控I/O有数据流入
    monitor_set_2[i]={fds...}   //监控I/O变得可写

    while(1){
        //监控对象,如果有事件发生就返回
        poll(monitor_set_1,monitor_set_2)
        for(n=0;n<maxfd;n++){       //poll返回,说明有(一些)事件被触发,依次处理这些触发了事件的文件描述符
            if(一个fd有数据流入){
                if(是listenfd有数据流入){
                    //获取sockfd
                    int sockfd = accept(listenfd)

                    //将这个sockfd加入监听有数据流入可写的集合
                    add_mem(moniter_set_1,sockfd)
                }else {     //不是listenfd有数据流入,而是之前加入的sockfd有数据流入

                    //读取信息
                    read(fd,&msg)

                    //将其挪入加入监控可写事件的集合
                    add_mem(monitor_set_1,fd)
                }
            }else{  //一个fd变得可写了

                //写入信息
                write(fd,&msg)

                //将其挪入监控可读的集合
                add_mem(monitor_set_1,fd)
            }
        }
    }
}
}

转: http://www.linuxidc.com/Linux/2016-11/137097.htm

<think>好的,我现在需要回答用户关于Linux服务器模型或架构的问题。首先,用户希望了解相关模型或架构,所以我得先回顾一下自己掌握的知识,并确保准确无误。 首先,Linux服务器常用的架构模型有哪些呢?我记得常见的有多进程模型、多线程模型、事件驱动模型,还有结合多线程和事件驱动的混合模型。比如,Apache服务器早期用的是多进程模型,而Nginx则是事件驱动模型的代表。这些模型各有优缺点,需要详细说明一下。 然后,用户提到了高性能服务器框架,引用中的资料可能有帮助。根据引用[3],高性能服务器框架涉及事件处理、并发模式、高效数据结构等。事件处理方面,Reactor和Proactor模式是重点。Reactor是同步I/O多路复用,而Proactor是异步I/O,需要区分清楚。并发模式方面,半同步/半异步和领导者/追随者模式也是常见的设计,需要解释它们的区别和应用场景。 另外,用户提供的引用[2]提到了NUMA架构和内存分配机制,这可能与服务器性能优化相关。虽然用户的问题主要关于模型,但可能也需要简要提到NUMA优化,比如内存的局部性配置和动态内存分配策略,这对高性能服务器很重要。 接下来,我需要组织这些信息,确保结构清晰。可以按模型分类展开,每个模型说明其原理、优缺点和典型应用,然后讨论高性能框架的关键技术,如事件处理模式和并发模式。最后提到NUMA架构的优化作为补充,这样用户能有一个全面的了解。 需要注意的是,用户可能对技术细节不太熟悉,所以解释时要尽量简明,避免过于晦涩。同时,引用中的资料要正确标注,比如引用[3]提到的高性能服务器框架部分,需要在相关段落末尾添加引用标识。 最后,生成相关问题。根据用户提供的示例,问题应该围绕Linux服务器架构的扩展,比如模型对比、优化方法、应用场景等。需要确保问题有针对性,帮助用户进一步深入学习。 现在,整理思路后开始撰写回答,确保每个部分符合要求,使用正确的中文表达和LaTeX格式,如独立公式用$$...$$,行内公式用$...$,并检查引用标注的位置是否自然。</think>### Linux服务器模型与架构解析 Linux服务器的高性能实现依赖于多种模型与架构设计,以下是关键技术的详细说明: --- #### 一、核心服务器模型 1. **多进程模型** - **原理**:主进程监听端口,接收连接后`fork()`子进程处理请求(如Apache prefork模式)。 - **优点**:进程间隔离性强,稳定性高。 - **缺点**:资源消耗大,上下文切换成本高。 - **公式示例**:进程创建开销可建模为 $$C = n \cdot (T_{\text{fork}} + T_{\text{ctx\_switch}})$$,其中$n$为并发数。 2. **多线程模型** - **原理**:主线程分配连接,工作线程通过共享内存处理请求(如MySQL线程池)。 - **优点**:资源占用少于多进程,数据共享方便。 - **挑战**:需处理线程同步问题(如互斥锁、信号量)[^3]。 3. **事件驱动模型(Reactor模式)** - **核心机制**:通过`epoll`/`kqueue`实现I/O多路复用,单线程处理所有事件(如Nginx、Redis)。 - **性能优势**:高并发下延迟低,C10K问题解决方案。 - **代码逻辑**: ```c while (1) { n = epoll_wait(epfd, events, MAX_EVENTS, -1); for (i = 0; i < n; i++) { if (events[i].data.fd == listen_fd) accept_conn(); else handle_request(events[i].data.fd); } } ``` 4. **混合模型(多线程+事件驱动)** - **设计**:主线程负责I/O多路复用,工作线程处理业务逻辑(如Memcached)。 - **平衡点**:兼顾高并发与计算密集型任务。 --- #### 二、高性能架构关键技术 1. **事件处理模式** - **Reactor**:同步非阻塞I/O,核心为“事件就绪时通知处理”[^3]。 - **Proactor**:异步I/O,内核完成操作后回调(Windows IOCP常见,Linux需模拟)。 2. **并发模式** - **半同步/半异步(HSHA)**:异步层处理I/O,同步线程池处理逻辑。 - **领导者/追随者(Leader/Followers)**:线程轮流监听事件并处理,避免锁竞争。 3. **NUMA架构优化** - **内存分配策略**:通过`numactl`设置`Interleave`模式平衡内存访问延迟[^2]。 - **Page Replication**:避免跨节点访问,提升缓存命中率。 --- #### 三、典型应用场景 | 模型 | 适用场景 | 代表软件 | |---------------|---------------------------|------------------| | 多进程 | 需高隔离性的服务 | Apache prefork | | 事件驱动 | 高并发I/O密集型 | Nginx, Redis | | 多线程 | 计算与I/O均衡的任务 | MySQL线程池 | | 混合模型 | 需兼顾吞吐量与计算 | Memcached | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值