一个WebServer的基本要素(高级篇)

前言

首先我们在上篇中讲了WebServer的最基本的内容,包括调用socket接口让用户和服务器通信,服务器对用户请求的处理,如何解析http请求报文,IO模型等问题,这样就实现了最基本的服务器功能,但是一个优秀的服务器还需要很多其他技术的支持。

数据库连接池

用户在和服务器的交互中可能会需要在服务器中记录数据,如用户的账号密码等信息,需要将这些信息保存起来,并随时提供给用户通过服务器查询,这就需要在服务器中加入数据库模块,用户查询信息需要先建立数据库连接,如果每次用户需要访问数据库中的信息都要新建一个数据库连接,访问结束后释放连接,当用户请求过多时,这种做法会过于低效。类似线程池的做法,我们构建一个数据库连接池,预先生成一些数据库连接放在那里准备给用户使用。
一个数据库连接池的做法是,预先生成多个数据库连接,放在一个链表中,同时维护最大连接数max_conn,当前可用连接数free_conn,已用连接数cur_conn这三个变量,注意在对连接池操作时,需要用到锁机制,因为它被所有线程共享。

单个数据库连接如何生成

  • 使用 mysql_init()初始化
  • 使用mysql_real_connect()建立一个到mysql数据库的连接。
  • 使用mysql_query()执行查询语句
  • 使用res=mysql_store_result(mysql)获取结果集
  • 使用mysql_num_fields(result)查询获取列数,mysql_num_rows(result)查询结果集行数
  • 使用mysql_fetch_row(result)不断获取下一行,循环输出
  • 使用mysql_free_result(result)释放结果集所占内存
  • 使用mysql_close(conn)关闭连接

CGI校验

CGI是通用网关接口,是一个运行在WebServer上的程序,在编译时,将相应的.cpp文件编译成.cgi文件,在主程序中调用即可。CGI通常执行一些信息搜索、存储等任务,而且通常会生成一个动态的HTML页面来响应客户的HTTP请求。CGI的运行通过多进程实现。

通过CGI接口,Web服务器就能够获取客户端提交的信息,转交给服务器端的CGI程序进行处理,最后返回结果给客户端。

生成HTTP响应并返回给用户

通过之前的操作,我们已经对用户的请求做了读取和处理,再对目标文件分析,若目标文件存在、对用户可读且不是目录,则使用mmap将其映射到专用的内存地址m_file_address。告诉调用者获取文件成功。接下来根据读取结果对用户做出响应(process_write),根据之前的读取请求的结果来判断应该给用户什么响应。若请求文件存在,就将响应写入对应用户connfd的写缓存中。
首先将状态行写入,请求的文件已经映射到了专用的地址中,修改用户connfd的可写事件,这样epoll_wait监测到这一事件,使用writev将响应信息和请求文件聚集写到tcp socket的发送缓冲区,交给内核发送给用户。

注:connfd是自己定义的用户连接类。

服务器优化:定时器处理非活动连接

如果有用户连接到服务器,但是长时间不交换数据,一直占用服务器的文件描述符,导致连接资源的浪费。这时应利用定时器把这些超时的非活动连接释放掉,关闭其占用的文件描述符。

可以利用alarm函数周期性触发SIGALRM信号,在信号处理函数中用管道通知主循环,主循环收到信号之后,对升序链表上所有定时器进行处理,若该段时间内没有交换数据,则关闭该连接,释放占用的资源。

服务器优化:日志

日志有服务器自动创建,记录运行状态、错误信息、访问数据的文件。
日志系统是用来存储程序运行中的通知信息、warning、error等。
首要任务就是格式化输出字符串到一个文件,还应当记录消息产生的时间,此系统选择使用按天作为文件名。
以消费者-生产者模式,使用阻塞队列实现线程异步处理Log消息。
还实现了主线程同步处理Log消息。

压测

服务器项目,在本地用浏览器访问测试无异常还不够,需要对服务器进行压测,即服务器并发量测试,压测过了,才说明服务器比较稳定。

我们需要用到一个压测软件叫Webbench。
在解压后的文件目录中打开终端命令:./webbench -c 10001 -t 5 http://127.0.0.1:8888/
其中-c 表示客户端数,-t表示时间。
然后会获得压测结果,有发送响应页面的速度,发送数据的速度,成功和失败的数量。

后记

成大事者不拘小节,谋远计者不图近利。不要因为最近的小事小利打破你长远的计划。

你可能感兴趣的:(服务器,c++)