HTTP Server简介
1. HTTP Server是干什么的?
– 处理http请求,返回数据给浏览器
– 负载均衡/反向代理/健康检查
– 日志(access log)
– URL Rewrite
– gzip
– cache-control(expire,etag,last-modified)
– keep-alive(长连接、短连接)
2. Let’s write a HTTP server
Level1. 先来个最简单的
• 阻塞 L
• 伪代码:
open socket bind one port listen for(;;) { socketN = accept one clients’connection process socketN } |
Level2. 用多线程、多进程
• 让每个连接都拥有独立的线程(或进程),这样任何一个连接的阻塞都不会影响其他的连接。
• 多进程:系统进程数有上限,不适用大量并发连接,使用的资源较多,进程间切换开销较大
多线程:连接数较少,使用系统资源不多,可多个线程共享;系统线程数有上限,不适用大量并发连接,且线程间的需要保护。
• 伪代码:
open socket bind one port listen for(;;) { socketN = accept one clients’connection fork() or pthread_create() { process socketN } } |
Level2.5 非阻塞轮询?
• 非阻塞的接口相比于阻塞型接口的显著差异在于,在被调用之后立即返回,造成了CPU空转,资源的浪费
Level3 事件驱动模型
• 是由系统提供的I/O复用的API来实现的,例如select/poll函数
• Select伪代码:
open socket fd_set bind one port listen for(;;) { 对一组fd_set调用select(),探测其是否变成readable if( listen_fd_set is readable) { socketfd = accept() fork() or pthread_create() { process socketN } } } |
Level 3.5 以epoll为代表高效事件驱动模型
• 与select/poll比为啥好?答案:效率
• select/poll
通过检查存放FD_SET标志位的数据结构来进行下一步处理。这样所带来的缺点是:
1) 单个进程可监视的fd数量被限制,由FD_SETSIZE宏设置。
2 )维护一个存放大量fd的数据结构,使得用户空间和内核空间在传递该结构时复制开销大。
3 )遍历fd列表后没有发现可处理socket,则挂起当前进程,直到被唤醒或者主动超时。这个过程经历了多次无谓的遍历。
• epoll
1)socket数量无限制。
2)使用mmap减少复制开销。
3)把fd列表交给内核,一旦有事件发生,内核通过回调的方式把发生事件的fd列表通知给进程,这样就避免了轮询整个描述符列表。 IO效率不随FD数目增加而线性下降。
综上各种I/O模型可以概括如下:
阻塞式:最普通的I/O模型;原生的read/write系统调用,默认是阻塞模式;导致进程阻塞;
非阻塞:这种方式通过指定系统调用read/write的参数为非阻塞,告知内核fd没就绪时,不阻塞进程,而是返回一个错误码,应用进程死循环轮询,直到fd就绪;
异步非阻塞(I/O复用):linux提供select/poll,进程通过将一个或多个fd传递给select或poll系统调用,阻塞在select;这样select/poll可以帮我们侦测许多fd是否就绪;但是select/poll是顺序扫描fd是否就绪,而且支持的fd数量有限。linux还提供了一个epoll系统调用,epoll是基于事件驱动方式,而不是顺序扫描,当有fd就绪时,立即回调函数rollback;
3. HTTP Server探索
3.1 常见HTTP Server
– Apache
– Lighttpd
– Nginx
常见的HTTP Server都使用的高效的I/O复用模型,其中apache使用poll,nginx使用epoll模型
这里要注意,应用服务器与HTTP Server的区别
应用服务器常见的有 IIS、Tomcat、 Resin、Weblogic、JBoss,这些看做是一个容器,一个引擎,可以提供动态的服务,而HTTP Server只是一个纯粹的静态资源(html,js,css等)的处理能力,扮演着如上所说HTTP Server应该扮演的角色。
3.2 传统的Apache的问题
• Keepalive off使得客户端需要重新连接
• apache是多进程模型,并发进程数不能太高,不能为每个用户hold一个长连续
• 用户提交数据过程可能比较慢,apache的进程是在建立连接后就分配,容易被ddos攻击
• prison通过扫描日志的方法,属于事后行为(防攻击能力不足)
3.3 怎么半?
用nginx、lighttpd等高性能HTTP Server
• apache之前做个模块专门保持与用户的长连接
• 而它与apache保持短连接
• 只有“真正”需要时才占用apache宝贵的进程
他们具有如下特点:
• 分流
对内将不同的请求按照策略发送到后端服务集群,并返回来自这些内部服务器的结果;而它与apache保持短连接
• 长连接、慢连接
只有“真正”需要时才占用apache宝贵的进程
• 防攻击
• Ddos