Posts p8 Linux高性能服务器编程--高性能服务器框架
Post
Cancel

p8 Linux高性能服务器编程--高性能服务器框架

1. 服务器基本框架

p1

  • IO处理单元 一个专门的接入服务器,他实现负载均衡,从所有的逻辑服务器中选取负荷最小的一台来为新客户服务。

  • 逻辑单元 一个逻辑单元通常是一个进程或者线程,它分析并处理客户数据。

  • 网络存储单元 数据库或者缓存(非必须)

2. IO模型

同步IO想应用程序通知的是IO就绪事件,异步IO向应用程序通的是完成事件,以食堂打饭为例。

  • 阻塞IO 与 非阻塞 IO
    • 阻塞IO 你去食堂打饭,饭还没好,你就在那里一直等。饭好了,你等着阿姨把饭给你打好。
    • 非阻塞IO 你去打饭,饭还没好,你走了。再过十分钟,你又去问,还没好,你又走了。一直循环,直到你一次去问,阿姨告诉你饭好了。你等着阿姨把饭给你打好
  • 同步IO 与 异步IO 阻塞IO,IO复用,信号驱动IO都是同步IO模型 异步IO:你让阿姨把饭打好,放在饭盒里,送到你面前。所有的过程你都不需要等待

3. 两种高效的事件处理模式

这个讲解还是挺好的

1. Reactor(同步IO)

1
非阻塞同步网络模式,感知的是就绪可读写事件。

2. Proactor(异步IO)

1
异步网络模式,感知的是已完成的读写事件。

因此,Reactor 可以理解为「来了事件操作系统通知应用进程,让应用进程来处理」,而 Proactor 可以理解为「来了事件操作系统来处理,处理完再通知应用进程」。这里的「事件」就是有新连接、有数据可读、有数据可写的这些 I/O 事件这里的「处理」包含从驱动读取到内核以及从内核读取到用户空间。

4. 有限状态机

1
主要针对逻辑单元内部处理。其应用如下:有点应用层协议头部包含数据类型字段,每中类型可以映射为逻辑单元的一种执行状态,服务器可以根据它来编写相应的逻辑处理。
  1. 独立状态的有限状态机

每个状态都是独立的。

1
2
3
4
5
6
7
8
9
10
11
STATE_MACHINE(Package _pack){
    PackageType _type = _pack.GetType();
    sticth(_type){
        case type_A:
            process_package_A(_pack);
            break;
        case type_B:
            process_package_B(_pack);
            break;
    }
}
  1. 带状态转移的有限状态机

状态间的转移是需要状态机内部驱动的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
STATE_MACHINE(Package _pack){
    State cur_State = type_A;
    while(cur_State != type_C){
        PackageType _pack = getNewPackage();

    sticth(cur_State){
        case type_A:
            process_package_A(_pack);
            cur_State = type_B;
            break;
        case type_B:
            process_package_B(_pack);
            cur_State = type_C;
            break;
        }
    }
}

5. 状态机 与 http

  1. 本文为了方便,下将称HTTP请求的一行(包括请求行和头部字段)为行。

  2. 状态机的状态说明

    1
    2
    3
    4
    5
    6
    
     //  主状态机的两种状态 正在分析请求行  正在分析头部字段
     enum CHECK_STATE { CHECK_STATE_REQUESTLINE = 0, CHECK_STATE_HEADER };
     // 从状态机的3种状态 1. 读取到一个完整的行 2. 行出错 3. 行数据尚不完整
     enum LINE_STATUS { LINE_OK = 0, LINE_BAD, LINE_OPEN };
     // 服务器处理HTTP请求的结果 1. 请求不完整 2. 获得一个完整的客户请求  3. 请求语法错误 4. 没有访问权限 5. 服务器内部错误 6. 客户端已经关闭连接
     enum HTTP_CODE { NO_REQUEST, GET_REQUEST, BAD_REQUEST, FORBIDDEN_REQUEST, INTERNAL_ERROR, CLOSED_CONNECTION };
    
  3. 几个buffer读取参数

    1
    2
    3
    4
    
     int data_read = 0;
     int read_index = 0;    // 当前已经读取了多少字节的客户数据
     int checked_index = 0;  // 当前已经分析了多少字节的客户数据
     int start_line = 0;     // 行在buffer中的起始位置
    

6.http 服务器代码解析

为了方便阅读逻辑 次为代码精简

main

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    char buffer[ BUFFER_SIZE ];  // 读缓冲区
    int data_read = 0;
    int read_index = 0;    // 当前已经读取了多少字节的客户数据
    int checked_index = 0;  // 当前已经分析了多少字节的客户数据
    int start_line = 0;     // 行在buffer中的起始位置

    CHECK_STATE checkstate = CHECK_STATE_REQUESTLINE; // 设置主状态机的初始状态   正在分析请求行
    while( 1 )  // 循环读取客户数据并分析
    {
        data_read = recv( fd, buffer + read_index, BUFFER_SIZE - read_index, 0 );

        // 分析目前已经获得的客户端数据
        read_index += data_read;
        HTTP_CODE result = parse_content( buffer, checked_index, checkstate, read_index, start_line );
        if( result == NO_REQUEST )
        {
            continue;
        }
        else if( result == GET_REQUEST )
        {
            send( fd, szret[0], strlen( szret[0] ), 0 );
            break;
        }
        else
        {
            send( fd, szret[1], strlen( szret[1] ), 0 );
            break;
        }

主状态机的转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 分析http请求的入口函数
HTTP_CODE parse_content( char* buffer, int& checked_index, CHECK_STATE& checkstate, int& read_index, int& start_line )
{
        switch ( checkstate )
        {
            case CHECK_STATE_REQUESTLINE: // 状态一:分析请求行
            {
                retcode = parse_requestline( szTemp, checkstate );
            }
            case CHECK_STATE_HEADER: // 状态二:分析头部字段
            {
                retcode = parse_headers( szTemp );
            }
            default:
            {
                return INTERNAL_ERROR;
            }
        }
    }
}

7. 提高服务器性能的几点建议

  • 池技术

  • 数据复制

  • 上下文切换

This post is licensed under CC BY 4.0 by the author.

Contents

Trending Tags