1.1 Nginx WEB入门简介
Nginx ("engine x") 是一个高性能HTTP 和 反向代理 服务器、IMAP、POP3、SMTP 服务器。 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本0.1.0发布于2004年10月4日。其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。
由于Nginx的高性能、轻量级,目前越来越多的互联网企业开始使用Nginx WEB服务器。据Netcraft统计,在2017年4月份,世界上最繁忙的网站中有28.72 %使用Nginx作为其服务器或者代理服务器。
nginx [engine x] is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server, originally written by Igor Sysoev. For a long time, it has been running on many heavily loaded Russian sites including Yandex, Mail.Ru, VK, and Rambler. According to Netcraft, nginx served or proxied 28.72% busiest sites in April 2017. Here are some of the success stories: Netflix,Wordpress.com, FastMail.FM. The sources and documentation are distributed under the 2-clause BSD-like license. Commercial support is available from Nginx, Inc. |
它已经在众多流量很大的俄罗斯网站上使用了很长时间,这些网站包括Yandex、Mail.Ru、VKontakte,以及Rambler。目前互联网主流公司京东、360、百度、新浪、腾讯、阿里都在使用Nginx作为自己的WEB服务器。
Nginx特点是占有内存少,并发能力强,事实上Nginx的并发能力确实在同类型的网页服务器中表现较好。
Nginx相对于Apache优点如下:
q 高并发响应性能非常好,官方Nginx处理静态文件并发5w/s;
q 负载均衡及反向代理性能非常强;
q 系统内存和CPU占用率低;
q 可对后端服务进行健康检查;
q 支持PHP cgi方式和FastCGI方式;
q 可以作为缓存服务器、邮件代理服务器;
q 配置代码简洁且容易上手。
1.2 Nginx工作原理
Nginx WEB服务器最主要就是各种模块的工作,模块从结构上分为核心模块、基础模块和第三方模块,其中三类模块分别如下:
q 核心模块:HTTP模块、EVENT模块和MAIL模块等;
q 基础模块:HTTP Access模块、HTTP FastCGI模块、HTTP Proxy模块和HTTP Rewrite模块;
q 第三方模块:HTTP Upstream Request Hash模块、Notice模块和HTTP Access Key模块、Limit_req模块、Upstream check module等;
Nginx的模块从功能上分为如下三类。
q Handlers(处理器模块):此类模块直接处理请求,并进行输出内容和修改headers信息等操作,Handlers处理器模块一般只能有一个;
q Filters (过滤器模块):此类模块主要对其他处理器模块输出的内容进行修改操作,最后由Nginx输出;
q Proxies (代理类模块):此类模块是Nginx的HTTP Upstream之类的模块,这些模块主要与后端一些服务比如FastCGI等进行交互,实现服务代理和负载均衡等功能。
Nginx由Nginx内核和模块组成,其中内核的设计非常微小和简洁,完成的工作也非常简单,仅仅通过查找配置文件将客户端的请求映射到一个location block,而location是Nginx配置中的一个指令,用于访问的URL匹配,而在这个location中所配置的每个指令将会启动不同的模块去完成相应的工作,如图14-1所示:
图14-1 Nginx WEB工作流程图
Nginx的高并发得益于其采用了epoll模型,与传统的服务器程序架构不同,epoll是Linux内核2.6以后才出现的,Nginx采用epoll模型,异步非阻塞,而apache采用的是select模型:
Select特点:select 选择句柄的时候,是遍历所有句柄,也就是说句柄有事件响应时,select需要遍历所有句柄才能获取到哪些句柄有事件通知,因此效率是非常低。
epoll的特点:epoll对于句柄事件的选择不是遍历的,是事件响应的,就是句柄上事件来就马上选择出来,不需要遍历整个句柄链表,因此效率非常高。
Nginx默认以80端口监听在服务器上,并且启动一个master进程,同时有master进程生成多个工作进程,当浏览器发起一个HTTP连接请求,每个进程都有可能处理这个连接,怎么做到的呢?怎么保证同一时刻一个HTTP请求被一个工作进程处理呢。
首先每个worker进程都是从Master进程fork出来,在Master进程里面,建立好需要listen的socket(listenfd)之后,会fork出多个worker进程。
所有worker进程的listenfd会在新连接到来时变得可读,为保证只有一个进程处理该连接,所有worker进程在注册listenfd读事件前抢accept_mutex,抢到互斥锁的那个进程注册listenfd读事件,在读事件里调用accept接受该连接。
当一个worker进程在accept这个连接之后,就开始读取请求、解析请求、处理请求,产生数据后,再返回给客户端,最后才断开连接,这样形成一个完整的请求流程。如图14-2所示:
图14-2 Nginx Worker进程工作原理
1.3 Nginx安装配置
Nginx WEB安装时可以指定很多的模块,默认需要安装Rewrite模块,也即是需要系统有PCRE库,安装Pcre支持Rewrite功能。如下为安装Nginx WEB服务器方法:
源码的路径,而不是编译后的路径,否则会报错。
#安装PCRE库支持 yum install pcre-devel pcre -y #下载Nginx源码包 cd /usr/src wget -c http://nginx.org/download/nginx-1.12.0.tar.gz #解压Nginx源码包 tar -xzf nginx-1.12.0.tar.gz #进入解压目录,然后sed修改Nginx版本信息为JWS cd nginx-1.12.0 ; sed -i -e 's/1.12.0//g' -e 's/nginx\//JWS/g' -e 's/"NGINX"/"JWS"/g' src/core/nginx.h #预编译Nginx useradd www ;./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module #.configure预编译成功后,执行make命令进行编译 make #make执行成功后,执行make install 正式安装 make install #至此Nginx WEB服务器安装完毕。 |
测试Nginx服务安装是否正确,同时启动Nginx WEB 服务,代码命令如下:
/usr/local/nginx/sbin/nginx -t 检查nginx配置文件是否正确,返回OK即正确。 [root@localhost ~]# /usr/local/nginx/sbin/nginx -t nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful [root@localhost ~]# 然后启动nginx,/usr/local/nginx/sbin/nginx 回车即可。查看进程是否已启动: [root@localhost ~]# ps -ef |grep nginx nobody 5381 30285 0 May16 ? 09:04:31 nginx: worker process root 30285 1 0 2017 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx root 32260 32220 0 12:34 pts/0 00:00:00 grep nginx [root@localhost ~]# |
通过浏览器访问Nginx默认测试页面,如图14-3所示:
图14-3 Nginx WEB浏览器访问
1.4 Nginx管理及升级
Nginx WEB服务器安装完毕,可以执行如下命令对其进管理和维护,命令如下:
#查看nginx进程 ps -ef|grep nginx #平滑启动nginx kill -HUP `cat /var/run/nginx.pid` 或者 nginx -s reload 其中进程文件路径在配置文件nginx.conf中可以找到。 平滑启动的意思是在不停止nginx的情况下,重启nginx,重新加载配置文件,启动新的工作线程,完美停止旧的工作线程。 #完美停止nginx kill -QUIT `cat /var/run/nginx.pid` #快速停止nginx kill -TERM `cat /var/run/nginx.pid` 或者 kill -INT `cat /var/run/nginx.pid` #完美停止工作进程(主要用于平滑升级) kill -WINCH `cat /var/run/nginx.pid` #强制停止nginx pkill -9 nginx #检查对nginx.conf文件的修改是否正确 nginx -t -c /etc/nginx/nginx.conf 或者 nginx -t #停止nginx的命令 nginx -s stop或者pkill nginx #查看nginx的版本信息 nginx -v #查看完整的nginx的配置信息 nginx -V |
Nginx WEB服务器定期更新,如果需要将低版本升级或者将高版本降级,升级或者降级方法如下,分为四个步骤,包括软件下载、预编译、编译、配置,具体方法如下:
wget http://www.nginx.org/download/nginx-1.4.2.tar.gz 获取旧版本nginx的configure选项 /usr/local/nginx/sbin/nginx -V 编译新版本的Nginx tar -xvf nginx-1.4.2.tar.gz cd nginx-1.4.2 ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_stub_status_module --with-http_ssl_module make 备份旧版本的nginx可执行文件,复制新版本的nginx这行文件 mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old cp objs/nginx /usr/local/nginx/sbin/ 测试新版本nginx是否正常 /usr/local/nginx/sbin/nginx -t 平滑重启升级nginx kill -QUIT `cat /usr/local/nginx/log/nginx.oldbin` ##关闭旧版nginx 验证nginx是否升级成功 /usr/local/nginx/sbin/nginx -V显示最新编译的版本信息即可。 |
1.5 Nginx配置文件优化一
学习Nginx服务的难点在于对配置文件的理解和优化,熟练掌握Nginx配置文件参数的含义可以更快的掌握Nginx,如下为Nginx.conf配置文件常用参数详解:
#定义Nginx运行的用户和用户组 user www www; #启动进程,通常设置成和cpu的数量相等 worker_processes 8; worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000; #为每个进程分配cpu,上例中将8个进程分配到8个cpu,当然可以写多个,或者将一个进程分配到多个cpu。 worker_rlimit_nofile 102400; #该指令是当一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(ulimit -n)与nginx进程数相除,但是nginx分配请求并不是那么均匀,所以最好与ulimit -n的值保持一致。 #全局错误日志及PID文件 error_log /usr/local/nginx/logs/error.log info; #错误日志定义等级,[ debug | info | notice | warn | error | crit ] pid /usr/local/nginx/nginx.pid; #工作模式及连接数上限 events { use epoll; #epoll是多路复用IO(I/O Multiplexing)中的一种方式,但是仅用于linux2.6以上内核,可以大大提高nginx的性能。 worker_connections 10000; #单个后台worker process进程的最大并发链接数 (最大连接数=连接数*进程数) multi_accept on; #尽可能多的接受请求. } #设定http服务器,利用它的反向代理功能提供负载均衡支持 http { #设定mime类型,类型由mime.type文件定义 include mime.types; default_type application/octet-stream; #设定日志格式 access_log /usr/local/nginx/log/nginx/access.log; sendfile on; #sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,对于普通应用必须设为 on #如果用来进行下载等应用磁盘IO重负载应用,可设置为 off,以平衡磁盘与网络I/O处理速度,降低系统的uptime。 #autoindex on; #开启目录列表访问,合适下载服务器,默认关闭。 tcp_nopush on; #防止网络阻塞 keepalive_timeout 65; #keepalive超时时间,客户端到服务器端的连接持续有效时间,当出现对服务器的后继请求时,keepalive-timeout功能可避免建立或重新建立连接。(节省服务器资源、CPU、内存、网卡) tcp_nodelay on; #提高数据的实时响应性 #开启gzip压缩 gzip on; gzip_min_length 1k; gzip_buffers 4 16k; gzip_http_version 1.1; gzip_comp_level 2; #压缩级别大小,最大为9,值越小,压缩后比例越小,CPU处理更快。 #值越大,消耗CPU比较高。 gzip_types text/plain application/x-javascript text/css application/xml; gzip_vary on; client_max_body_size 10m; #允许客户端请求的最大单文件字节数 client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数. proxy_connect_timeout 90; #nginx跟后端服务器连接超时时间(代理连接超时) proxy_send_timeout 90; #后端服务器数据回传时间(代理发送超时) proxy_read_timeout 90; #连接成功后,后端服务器响应时间(代理接收超时) proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小 proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置 proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2) #设定请求缓冲 large_client_header_buffers 4 4k; client_header_buffer_size 4k; #客户端请求头部的缓冲区大小,这个可以根据你的系统分页大小来设置,一般一个请求的头部大小不会超过1k #不过由于一般系统分页都要大于1k,所以这里设置为分页大小。分页大小可以用命令getconf PAGESIZE取得。 open_file_cache max=102400 inactive=20s; #这个将为打开文件指定缓存,默认是没有启用的,max指定缓存数量,建议和打开文件数一致,inactive是指经过多长时间文件没被请求后删除缓存。 open_file_cache_valid 30s; #这个是指多长时间检查一次缓存的有效信息。 open_file_cache_min_uses 1; #open_file_cache指令中的inactive参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个文件在inactive #包含其它配置文件,如自定义的虚拟主机 include vhosts.conf; |
1.6 Nginx配置文件优化二
Nginx WEB默认发布静态页面,也可以均衡后端动态网站,用户发起HTTP请求,如果请求静态页面,Nginx直接处理并返回,如果请求的是动态页面,Nginx收到请求之后会进行判断,转到后端服务器去处理。
Nginx实现负载均衡需要基于upstream模块,同时需要设置location proxy_pass转发指令实现。
如下为Ningx应用负载均衡集群配置,根据后端实际情况修改即可,jfedu_www为负载均衡模块的名称,可以任意指定,但必须跟vhosts.conf、Nginx.conf虚拟主机的proxy_pass段保持一致,否则不能将请求转发至后端的服务器,weight表示配置权重,在fail_timeout内检查max_fails次数,失败则剔除均衡。
upstream jfedu_www { #server 127.0.0.1:8080 weight=1 max_fails=2 fail_timeout=15; server 127.0.0.1:8081 weight=1 max_fails=2 fail_timeout=15s; } #虚拟主机配置 server { #侦听80端口 listen 80; #定义使用www.jfedu.net访问 server_name www.jfedu.net; #设定本虚拟主机的访问日志 access_log logs/access.log main; root /data/webapps/www; #定义服务器的默认网站根目录位置 index index.php index.html index.htm; #定义首页索引文件的名称 #默认请求 location ~ /{ root /data/webapps/www; #定义服务器的默认网站根目录位置 index index.php index.html index.htm; #定义首页索引文件的名称 #以下是一些反向代理的配置. proxy_next_upstream http_502 http_504 error timeout invalid_header; #如果后端的服务器返回502、504、执行超时等错误,自动将请求转发到upstream负载均衡池中的另一台服务器,实现故障转移。 proxy_redirect off; #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://jfedu_www; #请求转向后端定义的均衡模块 } # 定义错误提示页面 error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } #配置Nginx动静分离,定义的静态页面直接从Nginx发布目录读取。 location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css)$ { root /data/webapps/www; #expires定义用户浏览器缓存的时间为3天,如果静态页面不常更新,可以设置更长,这样可以节省带宽和缓解服务器的压力,在浏览器保存该类型文件的天数。 expires 3d; } #PHP脚本请求全部转发到 FastCGI处理. 使用FastCGI默认配置. location ~ \.php$ { root /root; FastCGI_pass 127.0.0.1:9000; FastCGI_index index.php; FastCGI_param SCRIPT_FILENAME /data/webapps/www$FastCGI_script_name; include FastCGI_params; } #设定查看Nginx状态的地址 location /NginxStatus { stub_status on; } } } |
通过Expires参数设置,可以使浏览器缓存过期时间,减少与服务器之前的请求和流量。具体Expires定义是给一个资源设定一个过期时间,也就是说无需去服务端验证,直接通过浏览器自身确认是否过期即可,所以不会产生额外的流量。
如果静态文件不常更新,Expires可以设置为30d,表示在这30天之内再次访问该静态文件,浏览器会发送一个HTTP请求,会比对服务器该文件最后更新时间是否有变化,如果没有变化,则不会从服务器抓取,返回HTTP状态码304,如果有修改,则直接从服务器重新下载,返回HTTP状态码200。
1.7 Nginx虚拟主机实战
在真实的企业服务器环境中,为了充分利用服务器的资源,单台Nginx WEB服务器同时会配置N个网站,也可称之为配置N个虚拟域名的主机,即多个域名对应同一个80端口。
在Nginx.conf中加入server代码,Nginx虚拟主机完整代码如下:
worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; #virtual hosts config 2017/5/18 server { listen 80; server_name www.jf1.com; access_log logs/jf1.access.log; location / { root html/jf1; index index.html index.htm; } } server { listen 80; server_name www.jf2.com; access_log logs/jf2.access.log; location / { root html/jf2; index index.html index.htm; } } } |
创建两个不同的目录mkdir -p /usr/local/nginx/html/{jf1,jf2},然后分别在两个目录创建两个不同的index.html网站页面即可。通过Windows客户端配置hosts绑定IP与两个域名的对应关系,在IE浏览器访问测试效果,如图14-4(a)、14-4(b)所示:
图14-4(a) Nginx 虚拟主机www.jf1.com
图14-4(b) Nginx 虚拟主机www.jf2.com
1.8 Nginx Location深入剖析
Nginx由内核和模块组成,其中内核的设计非常微小和简洁,完成的工作也非常简单,仅仅通过查找配置文件将客户端的请求映射到一个location block,而location是Nginx配置中的一个指令,用于访问的URL匹配,而在这个location中所配置的每个指令将会启动不同的模块去完成相应的工作。
默认Nginx.conf配置文件中至少存在一个location /,即表示客户端浏览器请求的URL为:域名+/,如果location /newindex/,则表示客户端浏览器请求的URL为:域名+/newindex/。常见Location匹配URL的方式如下:
= 字面精确匹配; ^~ 最大前缀匹配; / 不带任何前缀:最大前缀匹配; ~ 大小写相关的正则匹配; ~* 大小写无关的正则匹配; @ location内部重定向的变量。 |
其中Location =、^~、/属于普通字符串匹配,Location ~、~*属于正则表达式匹配,Location优先级与其在Nginx.conf配置文件中的先后顺序无关。
Location = 精确匹配会第一个被处理,如果发现精确匹配,Nginx则停止搜索其他任何Location的匹配。
普通字符匹配,正则表达式规则和完整URL规则将被优先和查询匹配,^~为最大前缀匹配,如果匹配到该规则,Nginx则停止搜索其他任何Location的匹配,否则nginx会继续处理其他location指令。
正则匹配"~"和"~*",如果找到相应的匹配,则Nginx停止搜索其他任何Location的匹配;当没有正则表达式或者没有正则表达式被匹配的情况下,那么匹配程度最高的逐字匹配指令会被使用。
Location规则匹配优先级总结如下:
(location =) > (location 完整路径) > (location ^~ 路径) > (location ~|~* 正则顺序) > (location 部分起始路径) > (location /) |
如下为Nginx Location规则案例演示:
location = / { [ configuration L1 ] #只会匹配/,优先级比Location /低。 } location = /index.html { [ configuration L2 ] #只会匹配/index.html,优先级最高。 } location / { [ configuration L3 ] #匹配任何请求,因为所有请求都是以"/"开始; #但是更长字符匹配或者正则表达式匹配会优先匹配,优先级最低。 } location = /images/ { [ configuration L4 ] #匹配任何以/images/开始的请求,并停止匹配其它location; } location ~* \.(html|txt|gif|jpg|jpeg)$ { [ configuration L5] # 匹配以html、txt、gif、jpg、jpeg结尾的URL文件请求; # 但是所有/images/目录的请求将由 [Configuration L4]处理。 } 浏览器发起HTTP Request URI案例与Location规则案例匹配如下: q / ->匹配configuration L3; q /index.html匹配configuration L2; q /images/匹配configuration L4; q /images/logo.png匹配configuration L4; q /img/test.jpg匹配configuration L5。 |
企业生产环境中无需在Nginx.conf配置文件中同时添加五种规则匹配,如下为企业生产环境Nginx Location部分配置代码:
location / { root /var/www/html/; expires 60d; } location ~ .*\.(gif|jpg|jpeg|bmp|png|ico|txt|js|css)$ { root /var/www/html/; expires 60d; } location ~ .*\.(jsp|php|cgi|do)$ { root /var/www/html/; proxy_pass http://linux_web; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location =/newindex.html { root /var/www/newwww/; expires 60d; } |
1.9 企业实战Nginx动静分离架构
Nginx动静分离简单来说就是把动态跟静态请求分开,不能理解成只是单纯的把动态页面和静态页面物理分离。严格意义上说应该是动态请求跟静态请求分开,可以理解成使用Nginx处理静态页面,Tomcat、Resin、PHP、ASP处理动态页面。
动静分离从目前实现角度来讲大致分为两种,一种是纯粹的把静态文件独立成单独的域名,放在独立的服务器上,也是目前主流推崇的方案;另外一种方法就是动态跟静态文件混合在一起发布,通过Nginx来分开。
Nginx线上WEB服务器动静分离及Nginx.conf完整配置文件代码如下:
user www www; worker_processes 8; worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000; pid /usr/local/nginx/nginx.pid; worker_rlimit_nofile 102400; events { use epoll; worker_connections 102400; } http { include mime.types; default_type application/octet-stream; FastCGI_intercept_errors on; charset utf-8; server_names_hash_bucket_size 128; client_header_buffer_size 4k; large_client_header_buffers 4 32k; client_max_body_size 300m; sendfile on; tcp_nopush on; keepalive_timeout 60; tcp_nodelay on; client_body_buffer_size 512k; proxy_connect_timeout 5; proxy_read_timeout 60; proxy_send_timeout 5; proxy_buffer_size 16k; proxy_buffers 4 64k; proxy_busy_buffers_size 128k; proxy_temp_file_write_size 128k; gzip on; gzip_min_length 1k; gzip_buffers 4 16k; gzip_http_version 1.1; gzip_comp_level 2; gzip_types text/plain application/x-javascript text/css application/xml; gzip_vary on; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" $request_time'; upstream jvm_web1 { server 192.168.149.130:8080 weight=1 max_fails=2 fail_timeout=30s; server 192.168.149.130:8081 weight=1 max_fails=2 fail_timeout=30s; } include vhosts.conf; } |
如下为vhosts.conf配置文件中内容:
server { listen 80; server_name www.jf1.com; index index.jsp index.html index.htm; root /data/webapps/www1; location / { proxy_next_upstream http_502 http_504 error timeout invalid_header; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://jvm_web1; } location ~ .*\.(php|jsp|cgi|shtml)?$ { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://jvm_web1; } location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css)$ { root /data/webapps/www1; expires 30d; } access_log /data/logs/jvm_web1/access.log main; error_log /data/logs/jvm_web1/error.log crit; } |
配置文件代码中:location ~ .*\.(php|jsp|cgi|shtml)表示匹配动态页面请求,然后将请求proxy_pass到后端服务器,而location ~ .*\.(html|htm|gif|jpg|jpeg |ico|txt|js|css)表示匹配静态页面请求本地返回。
检查Nginx配置是否正确即可,然后测试动静分离是否成功,在192.168.149.130服务器启动8080、8081 Tomcat服务或者LAMP服务,删除后端Tomcat或者LAMP服务器上的某个静态文件,测试是否能访问该文件,如果可以访问说明静态资源Nginx直接返回了,如果不能访问,则证明动静分离不成功。
1.10 企业实战LNMP高性能服务器
公共网关接口”(Common Gateway Interface,CGI),是HTTP服务器与本机或者其它机器上的程序进行通信的一种工具,其程序须运行在网络服务器上。
CGI可以用任何一种语言编写,只要这种语言具有标准输入、输出和环境变量,如php、perl、tcl等。
FAST-CGI:WEB服务器与处理程序之间通信的一种协议(App server 和Web server 之间的通信协议),是CGI的改进方案。CGI程序反复加载是CGI性能低下的主要原因,如果CGI程序保持在内存中并接受FastCGI进程管理器调度,则可以提供良好的性能、伸缩性、Fail-Over特性等。FastCGI是常驻型的CGI,它可以一直运行,在请求到达时,不会花费时间去fork一个进程来处理。
FastCGI是语言无关的、可伸缩架构的CGI开放扩展,将CGI解释器进程保持在内存中,以此获得较高的性能。FastCGI是一个协议,php-fpm实现了这个协议,php-fpm的FastCGI协议需要有进程池,php-fpm实现的FastCGI进程叫php-cgi,所以php-fpm其实是他自身的FastCGI或php-cgi进程管理器,如图14-5所示:
图14-5 Nginx+FastCGI通信原理图
企业级LNMP(Nginx+PHP(FastCGI)+MySQL)主流架构配置方法如下,分别安装Nginx、MYSQL、PHP服务,步骤如下:
(1) Nginx安装配置
wget -c http://nginx.org/download/nginx-1.12.0.tar.gz tar -xzf nginx-1.12.0.tar.gz cd nginx-1.12.0 useradd www ;./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module make make install |
(2) MYSQL安装配置
yum install cmake ncurses-devel ncurses –y wget http://down1.chinaunix.net/distfiles/mysql-5.5.20.tar.gz tar -xzf mysql-5.5.20.tar.gz cd mysql-5-5.20 cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/mysql55 \ -DMYSQL_UNIX_ADDR=/tmp/mysql.sock \ -DMYSQL_DATADIR=/data/mysql \ -DSYSCONFDIR=/etc \ -DMYSQL_USER=mysql \ -DMYSQL_TCP_PORT=3306 \ -DWITH_XTRADB_STORAGE_ENGINE=1 \ -DWITH_INNOBASE_STORAGE_ENGINE=1 \ -DWITH_PARTITION_STORAGE_ENGINE=1 \ -DWITH_BLACKHOLE_STORAGE_ENGINE=1 \ -DWITH_MYISAM_STORAGE_ENGINE=1 \ -DWITH_READLINE=1 \ -DENABLED_LOCAL_INFILE=1 \ -DWITH_EXTRA_CHARSETS=1 \ -DDEFAULT_CHARSET=utf8 \ -DDEFAULT_COLLATION=utf8_general_ci \ -DEXTRA_CHARSETS=all \ -DWITH_BIG_TABLES=1 \ -DWITH_DEBUG=0 make make install |
(3) PHP安装配置
wget http://museum.php.net/php5/php-5.3.10.tar.gz yum -y install gd curl curl-devel libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel libxml2 libxml2-devel cd php-5.3.10 ./configure --prefix=/usr/local/php5 --enable-fpm --enable-debug --with-gd --with-jpeg-dir --with-png-dir --with-freetype-dir --enable-mbstring --with-curl --with-mysql=/usr/local/mysql55/ --with-mysqli=/usr/local/mysql55/bin/mysql_config --with-config-file-path=/usr/local/php5/etc make make install cp php.ini-development /usr/local/php5/etc/php.ini cp /usr/local/php5/etc/php-fpm.conf.default /usr/local/php5/etc/php-fpm.conf /usr/local/php5/sbin/php-fpm cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm |
(4) Nginx配置文件配置
server { include port.conf; server_name www.jfedu.net jfedu.net; location / { index index.html index.php; root /usr/local/nginx/html; } location ~ \.php$ { root html; FastCGI_pass 127.0.0.1:9000; FastCGI_index index.php; FastCGI_param SCRIPT_FILENAME html$FastCGI_script_name; include FastCGI_params; } } |
(5) 测试LNMP架构测试,创建index.php测试页面,如图14-6所示:
图14-6 LNMP企业实战测试页面
1.11 Nginx Rewrite规则详解一
Rewirte规则也称为规则重写,主要功能是实现浏览器访问HTTP URL的跳转,其正则表达式是基于Perl语言。通常而言,几乎所有的WEB服务器均可以支持URL重写。Rewrite URL规则重写的用途:
q 对搜索引擎优化(Search Engine Optimization,SEO)友好,利于搜索引擎抓取网站页面;
q 隐藏网站URL真实地址,浏览器显示更加美观;
q 网站变更升级,可以基于Rewrite临时重定向到其他页面。
Nginx Rewrite规则使用中有三个概念需要理解,分别是:Rewrite结尾标识符、Rewrite规则常用表达式、Nginx Rewrite变量,如下为三个概念的详解:
(1) Nginx Rewrite结尾标识符,用于Rewrite规则末尾,表示规则的执行属性。
last :相当于Apache里的(L)标记,表示完成rewrite匹配; break:本条规则匹配完成后,终止匹配,不再匹配后面的规则。 redirect:返回302临时重定向,浏览器地址会显示跳转后的URL地址。 permanent:返回301永久重定向,浏览器地址栏会显示跳转后的URL地址。 其中last和break用来实现URL重写时,浏览器地址栏URL地址不变。 |
(2) Nginx Rewrite规则常用表达式,主要用于匹配参数、字符串及过滤设置。
. 匹配任何单字符; [word] 匹配字符串:word; [^word] 不匹配字符串:word; jfedu|jfteach 可选择的字符串:jfedu|jfteach; ? 匹配0到1个字符; * 匹配0到多个字符; + 匹配1到多个字符; ^ 字符串开始标志; $ 字符串结束标志; \n 转义符标志。 |
(3) Nginx Rewrite变量,常用于匹配HTTP请求头信息、浏览器主机名、URL等。
HTTP headers:HTTP_USER_AGENT, HTTP_REFERER, HTTP_COOKIE, HTTP_HOST, HTTP_ACCEPT; connection & request: REMOTE_ADDR, QUERY_STRING; server internals: DOCUMENT_ROOT, SERVER_PORT, SERVER_PROTOCOL; system stuff: TIME_YEAR, TIME_MON, TIME_DAY。 详解如下: HTTP_USER_AGENT 用户使用的代理,例如浏览器; HTTP_REFERER 告知服务器,从哪个页面来访问的; HTTP_COOKIE 客户端缓存,主要用于存储用户名和密码等信息; HTTP_HOST 匹配服务器ServerName域名; HTTP_ACCEPT 客户端的浏览器支持的MIME类型; REMOTE_ADDR 客户端的IP地址 QUERY_STRING URL中访问的字符串; DOCUMENT_ROOT 服务器发布目录; SERVER_PORT 服务器端口; SERVER_PROTOCOL 服务器端协议; TIME_YEAR 年; TIME_MON 月; TIME_DAY 日; |
(4) Nginx Rewrite以下配置均配置在nginx.conf或者vhosts.conf中,企业中常用的Nginx Rewrite案例如下:
- 将jfedu.net跳转至www.jfedu.net。
if ($host = 'jfedu.net' ) { rewrite ^/(.*)$ http://www.jfedu.net/$1 permanent; } |
- 访问www.jfedu.net跳转www.test.com/new.index.html。
rewrite ^/$ http://www.test.com/index01.html permanent; |
- 访问/jfedu/test01/跳转至/newindex.html,浏览器地址不变。
rewrite ^/jfedu/test01/$ /newindex.html last; |
- 多域名跳转到www.jfedu.net。
if ($host != ‘www.jfedu.net’ ) { rewrite ^/(.*)$ http://www.jfedu.net/$1 permanent; } |
- 访问文件和目录不存在跳转至index.php。
if ( ! -e $request_filename ) |
- 目录对换 /xxxx/123456 ====> /xxxx?id=123456。
rewrite ^/(.+)/(\d+) /$1?id=$2 last; |
- 判断浏览器User Agent跳转。
if( $http_user_agent ~ MSIE) |
- 禁止访问以.sh,.flv,.mp3为文件后缀名的文件。
location ~ .*\.(sh|flv|mp3)$ |
- 将移动用户访问跳转至移动端。
if ( $http_user_agent ~* "(Android)|(iPhone)|(Mobile)|(WAP)|(UCWEB)" ) { rewrite ^/$ http://m.jfedu.net/ permanent; } |
- 匹配URL访问字符串跳转。
if ($args ~* tid=13){ return 404; } |
- 访问/10690/jfedu/123跳转至/index.php?tid/10690/items=123,[0-9]表示任意一个数字,+表示多个,(.+)表示任何多个字符。
rewrite ^/([0-9]+)/jfedu/(.+)$ /index.php?tid/$1/items=$2 last; |
1.12 Nginx WEB日志分析
在企业服务器运维中,当Nginx服务器正常运行后,SA会经常密切关注Nginx的访问日志,发现有异常的日志信息需要进行及时处理。
Nginx默认日志路径/usr/local/nginx/logs/,其中包含访问日志access.log 和错误记录日志error.log,如图查看nginx访问日志:cat /usr/local/nginx/logs/access.log |more,如图14-7所示:
图14-7 Nginx访问日志信息
Nginx访问日志打印的格式可以自定义,例如Nginx日志打印格式配置如下,Log_format 用来设置日志格式,Name(模块名) Type(日志类型),可以配置多个日志模块,分别供不同的虚拟主机日志记录所调用:
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" $request_time'; |
Nginx日志格式内部变量及函数参数说明:
$remote_addr 记录客户端IP地址; $server_name 虚拟主机名称; $http_x_forwarded_for HTTP的请求端真实的IP; $remote_user 记录客户端用户名称; $request 记录请求的URL和HTTP协议; $status 记录返回HTTP请求的状态; $uptream_status upstream的状态; $ssl_protocol SSL协议版本; $body_bytes_sent 发送给客户端的字节数,不包括响应头的大小; $bytes_sent 发送给客户端的总字节数; $connection_requests 当前通过一个连接获得的请求数量; $http_referer 记录从哪个页面链接访问过来的; $http_user_agent 记录客户端浏览器相关信息; $request_length 请求的长度,包括请求行,请求头和请求正文; $msec 日志写入时间; $request_time 请求处理时间,单位为秒,精度毫秒,Nginx接受用户请求的第一个字节到发送完响应数据的时间,包括:接收请求数据时间、程序响应时间、输出、响应数据时间。 $upstream_response_time 应用程序响应时间,Nginx向后端服务建立连接开始到接受完数据然后关闭连接为止的总时间。 |
通过Nginx日志,可以简单分析WEB网站的运行状态、数据报表、IP、UV(unique visitor)、PV(page view)访问量等需求,如下为常用需求分析:
(1) 统计Nginx服务器独立IP数。
awk '{print $1}' access.log |sort -r|uniq -c | wc -l |
(2) 统计Nginx服务器总PV量。
awk '{print $7}' access.log |wc -l |
(3) 统计Nginx服务器UV统计。
awk '{print $11}' access.log |sort -r|uniq -c |wc -l |
(4) 分析Nginx访问日志截止目前为止访问量前20的IP列表。
awk '{print $1}' access.log|sort |uniq -c |sort -nr |head -20 |
(5) 分析Nginx访问日志早上9点至中午12点的总请求量。
sed -n "/2016:09:00/,/2016:12:00/"p access.log awk '/2017:09:00/,/2017:12:00/' access.log|wc –l |
(6) 分析Nginx访问日志总的独立IP数。
awk '{print $1}' access.log |sort |uniq -c|wc -l |
(7) 分析Nginx访问日志截止目前为止访问量前20的IP列表。
awk '{print $1}' access.log|sort |uniq -c |sort -nr |head -20 |
(8) 分析Nginx访问日志截止目前为止访问量前20的IP列表。
awk '{print $1}' access.log|sort |uniq -c |sort -nr |head -20 |
(9) 分析Nginx访问日志状态码404、502、503、500、499等错误信息页面,打印错误出现次数大于20的IP地址。
awk '{if ($9~/502|499|500|503|404/) print $1,$9}' access.log|sort|uniq –c|sort –nr | awk '{if($1>20) print $2}' |
(10) 分析Nginx访问日志访问最多的页面。
awk '{print $7}' access.log |sort |uniq -c|sort -nr|head -20 |
(11) 分析Nginx访问日志请求处理时间大于5秒的URL,并打印出时间、URL、访客IP。
awk '{if ($NF>5) print $NF,$7,$1}' access.log|sort -nr|more |
1.13 Nginx日志切割案例
Nginx WEB服务器每天会产生大量的访问日志,而且不会自动地进行切割,如果持续天数访问,将会导致该access.log日志文件容量非常大,不便于SA查看相关的网站异常日志。
可以基于Shell 脚本结合Crontab计划任务对Nginx日志进行自动、快速的切割,其切割的方法使用mv命令即可,如图14-8所示。
#!/bin/bash #auto mv nginx log shell #by author jfedu.net S_LOG=/usr/local/nginx/logs/access.log D_LOG=/data/backup/`date +%Y%m%d` echo -e "\033[32mPlease wait start cut shell scripts...\033[1m" sleep 2 if [ ! -d $D_LOG ];then mkdir -p $D_LOG fi mv $S_LOG $D_LOG kill -USR1 `cat /usr/local/nginx/logs/nginx.pid` echo "-------------------------------------------" echo "The Nginx log Cutting Successfully!" echo "You can access backup nginx log $D_LOG/access.log files." |
图14-8 Nginx日志切割
将如上脚本内容写入auto_nginx_log.sh文件,crontab /var/spool/cron/root文件中添加如下代码,每天凌晨自动切割日志:
0 0 * * * /bin/sh /data/sh/auto_nginx_log.sh >>/tmp/nginx_cut.log 2>&1 |
1.14 Nginx防盗链配置案例配置
防盗链的含义是网站内容本身不在自己公司的服务器上,而通过技术手段,直接在调用其他公司的服务器网站数据,而向最终用户提供此内容。一些小网站盗链高访问量网站的音乐、图片、软件的链接,然后放置在自己的网站中,通过这种方法盗取高访问量网站的空间和流量。
网站每天访问量很大,而且占用了很多不必要的带宽,浪费资源,所以必须采取一些限制措施。防盗链其实就是采用服务器端编程技术,通过URL过滤、主机名等实现的防止盗链的软件。
例如http://www.jfedu.net/linux/页面,如果没有配置防盗链,别人就能轻而易举的在其的网站上引用该页面。Nginx防盗链配置代码如下:
server { listen 80; server_name jfedu.net www.jfedu.net; location / { root html/b; index index.html index.htm; } location ~* \.(gif|jpg|png|swf|flv)$ { valid_referers none blocked jfedu.net *.jfedu.net; root html/b; if ($invalid_referer) { #rewrite ^/ http://www.jfedu.net/403.html; return 403; } } } |
Nginx防盗链参数详解:
valid_referers表示可用的referers设置 none 表示没有referers,直接通过浏览器或者其他工具访问。 blocked表示有referers,但是被代理服务器或者防火墙隐藏; jfedu.net 表示通过jfedu.net访问的referers; *.jfedu.net 表示通过*.jfedu.net访问的referers,*表示任意host主机。 |
除了以上方法,按照如下方法设置也可以实现防盗链:
location ~* \.(gif|jpg|png|swf|flv)$ if ($host !=’*.jfedu.net’) { return 403; } |
防盗链测试,找另外一台测试服务器,基于Nginx发布如下test.html页面,代码如下,去调用www.jfedu.net官网的test.png图片,由于www.jfedu.net官网设置了防盗链,所以无法访问该图片。
<html> <h1>TEST Nginx PNG</h1> <img src="http://www.jfedu.net/test.png"> </html> |
默认没有配置Nginx防盗链,网站正常调用www.jfedu.net的logo图片,访问如图14-9所示:
图14-9 Nginx无防盗链正常调用图片
配置Nginx防盗链,网站无法正常调用www.jfedu.net的logo图片,访问如图14-10所示:
图14-10 Nginx防盗链403禁止访问
第2章 HTTP协议详解
超文本传输协议(Hyper Text Transfer Protocol,HTTP)是互联网上应用最为广泛的一种网络协议。所有的WWW服务器都基于该协议。HTTP设计最初的目的是为了提供一种发布WEB页面和接收WEB页面的方法。
本章向读者介绍TCP、HTTP协议、HTTP资源定位、HTTP请求及响应头详细信息、HTTP状态码及MIME类型详解等。
2.1 TCP协议与HTTP协议
1960年美国人Ted Nelson构思了一种通过计算机处理文本信息的方法,并称之为超文本(hyper text),为HTTP超文本传输协议标准架构的发展奠定了根基。Ted Nelson组织协调万维网协会(World Wide Web Consortium)和互联网工程工作小组(Internet Engineering Task Force )共同合作研究,最终发布了一系列的RFC,其中著名的RFC 2616定义了HTTP 1.1。
很多读者对TCP协议与HTTP协议存在疑问,这两者有什么区别呢,从应用领域来说,TCP协议主要用于数据传输控制,而HTTP协议主要用于应用层面的数据交互,本质上两者没有可比性。
HTTP协议属于应用层协议,是建立在TCP协议基础之上,HTTP协议以客户端请求和服务器端应答为标准,浏览器通常称为客户端,而WEB服务器称之为服务器端。客户端打开任意一个端口向服务端的指定端口(默认为80)发起HTTP请求,首先会发起TCP三次握手,TCP三次握手的目的是建立可靠的数据连接通道,TCP三次握手通道建立完毕,进行HTTP数据交互,如图9-1(a)、9-1(b)所示:
图9-1(a) HTTP与TCP关系结构图
图9-1(b) HTTP客户端与服务器
当客户端请求的数据接收完毕后,HTTP服务器端会断开TCP连接,整个HTTP连接过程非常短。HTTP连接也称为无状态的连接,无状态连接是指客户端每次向服务器发起HTTP请求时,每次请求都会建立一个新的HTTP连接,而不是在一个HTTP请求基础上进行所有数据的交互。
2.2 资源定位标识符
发起HTTP请求的内容资源由统一资源标示符(Uniform Resource Identifiers,URI)来标识,关于资源定位及标识有三种:URI、URN、URL,三种资源定位详解如下:
q 统一资源标识符(uniform resource identifier,URI),用来唯一标识一个资源;
q 统一资源定位器(uniform resource locator,URL),是一种具体的URI。URL可以用来标识一个资源,而且访问或者获取该资源;
q 统一资源命名(uniform resource name,URN),通过名字来标识或识别资源。
如图9-2所示,可以直观区分URI、URN、URL的区别:
图9-2 URI、URN、URL关联与区别
三种资源标识,其中URL资源标识方式使用最为广泛,完整的URL标识格式如下:
protocol://host[:port]/path/.../[?query-string][#anchor] protocol 基于某种协议,常见协议:http、https、ftp、rsync等; host 服务器的IP地址或者域名; port 服务器的端口号,如果是HTTP 80端口,默认可以省略。 path 访问资源在服务器的路径; query-string 传递给服务器的参数及字符串; anchor- 锚定结束; |
Http URL案例演示如下:
http://www.jfedu.net/newindex/plus/list.php?tid=2#jfedu protocol: http协议; host: www.jfedu.net; path: /newindex/plus/list.php Query String: tid=2 Anchor: jfedu |
2.3 HTTP与端口通信
HTTP WEB服务器默认在本机会监听80端口,不仅HTTP会开启监听端口,其实每个软件程序在Linux系统中运行,会以进程的方式启动,程序就会启动并监听本地接口的端口,为什么会引入端口这个概念呢?
端口是TCP/IP协议中应用层进程与传输层协议实体间的通信接口,端口是操作系统可分配的一种资源,应用程序通过系统调用与某个端口绑定后,传输层传给该端口的数据会被该进程接收,相应进程发给传输层的数据都通过该端口输出。
在网络通信过程中,需要唯一识别通信两端设备的端点,就是使用端口识别运行于某主机中的应用程序。如果没有引入端口,则只能通过PID进程号进行识别,而PID进程号是系统动态分配的,不同的系统会使用不同的进程标识符,应用程序在运行之前没有明确的进程号,如果需要运行后再广播进程号则很难保证通信的顺利进行。
而引入端口后,就可以利用端口号识别应用程序,同时通过固定端口号来识别和使用某些公共服务,例如如HTTP默认使用80端口,而FTP使用21、20端口,MYSQL则使用3306端口。
使用端口还有一个原因是随着计算机网络技术的发展,物理机器上的硬件接口已不能满足网络通信的要求,而TCP/IP协议模型作为网络通信的标准就解决了这个通信难题。
TCP/IP协议中引入了一种被称为套接字(Socket)的应用程序接口。基于Socket接口技术,一台计算机就可以与任何一台具有Socket接口的计算机进行通信,而监听的端口在服务器端也称之为Socket接口。
2.4 HTTP Request与Response详解
客户端浏览器向WEB服务器发起Request, Web服务器接到Request后进行处理,会生成相应的Response信息返给浏览器,客户端浏览器收到服务器返回的Response信息,会对信息进行解析处理,最终用户看到浏览器展示WEB服务器的网页内容。
客户端发起Request,Request消息分为三个部分,分别包括:Request line、Request header、Body,如图9-3所示:
图9-3 HTTP Request Message组成
Unix/Linux系统中执行CURL -v命令可以打印访问WEB服务器的Request及Response详细处理流程,如图9-4所示:
curl -v http://192.168.111.131/index.html |
图9-4 Request及Response请求回应流程
(1) Request信息详解如表9-1所示:
GET /index.html HTTP/1.1 |
请求行 |
Request Message |
User-Agent: curl/7.19.7 Host: 192.168.111.131 Accept: */* …… |
请求头部 |
|
> |
空行 |
|
> |
请求Body |
|
第一部分:请求行,指定请求类型,访问的资源及使用的HTTP协议版本。 GET表示Request请求类型为GET;/index.html表示访问的资源;HTTP/1.1表示协议版本。 第二部分:请求头部,请求行下一行起,指定服务器要使用的附加信息; User-Agent 表示用户使用的代理软件,常指浏览器;HOST表示请求的目的主机。 第三部分:空行,请求头部后面的空行表示请求头发送完毕。 第四部分:请求数据也叫Body,可以添加任意的数据,Get请求的Body内容默认为空。 |
表9-1 Request请求头详解
(2) Response信息详解如表9-2所示:
HTTP/1.1 200 OK |
响应行 |
Response Message |
Server: nginx/1.10.1 Date: Thu, 11 May 2017 Content-Type: text/html …… |
响应头部 |
|
> |
空行 |
|
<h1>www.jf1.com Pages</h1> |
响应Body |
第一部分:响应状态行,包括HTTP协议版本号、状态码、状态消息。 HTTP/1.1表示HTTP协议版本号;200表示返回状态码;OK表示状态消息。 第二部分:消息报头,响应头部附加信息。 Date表示生成响应的日期和时间,Content-Type表示指定MIME类型的HTML(text/html),编码类型是UTF-8,记录文件资源的Last-Modified时间。 第三部分:空行,表示消息报头响应完毕。 第四部分:响应正文,服务器返回给客户端的文本信息。 |
表9-2 Request请求头详解
(3) Request请求方法根据请求的资源不同,有如下请求方法:
GET方法,向特定的资源发出请求,获取服务器端数据; POST方法,向WEB服务器提交数据进行处理请求,常指提交新数据; PUT方法,向WEB服务器提交上传最新内容,常指更新数据; DELETE方法,请求删除Request-URL所标识的服务器资源; TRACE方法,回显服务器收到的请求,主要用于测试或诊断; CONNECT方法,HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器; OPTIONS方法,返回服务器针对特定资源所支持的HTTP请求方法; HEAD方法,HEAD方法跟GET方法相同,只不过服务器响应时不会返回消息体。 |
2.5 HTTP 1.0/1.1协议区别
HTTP 协议定义服务器端和客户端之间文件传输的沟通方式HTTP1.0运行方式,如图9-5所示:
图9-5 HTTP1.0 客户端、服务器传输模式
q 基于HTTP协议的客户/服务器模式的信息交换过程,如图所示,它分四个过程,建立连接、发送请求信息、发送响应信息、关闭连接;
q 浏览器与WEB服务器的连接过程是短暂的,每次连接只处理一个请求和响应。对每一个页面的访问,浏览器与WEB服务器都要建立一次单独的连接;
q 浏览器到WEB服务器之间的所有通讯都是完全独立分开的请求和响应。
HTTP1.1运行方式,如图9-6所示:
图9-6 HTTP1.1 客户端、服务器传输模式
q 在一个TCP连接上可以传送多个HTTP请求和响应;
q 多个请求和响应过程可以重叠;
q 增加了更多的请求头和响应头,比如Host、If-Unmodified-Since请求头等。
2.6 HTTP状态码详解
HTTP状态码(HTTP Status Code)是用来表示WEB服务器HTTP Response状态的3位数字代码,常见的状态码范围分类:
100-199 用于指定客户端应相应的某些动作; 200-299 用于表示请求成功; 300-399 已移动的文件且被包含在定位头信息中指定新的地址信息; 400-499 用于指出客户端的错误; 500-599 用于支持服务器错误。 |
HTTP协议Response常用状态码详解表9-3所示:
HTTP状态码 |
状态码英文含义 |
状态码中文含义 |
100 |
Continue |
HTTP/1.1新增状态码,表示继续,客户端继续请求HTTP服务器; |
101 |
Switching Protocols |
服务器根据客户端的请求切换协议,切换到HTTP的新版本协议; |
200 |
OK |
HTTP请求完成,常用于GET、POST请求中; |
301 |
Moved Permanently |
永久移动,请求的资源已被永久的移动到新URI; |
302 |
Found |
临时移动,资源临时被移动,客户端应继续使用原有URI; |
304 |
Not Modified |
文件未修改,请求的资源未修改,服务器返回此状态码时,常用于缓存; |
400 |
Bad Request |
客户端请求的语法错误,服务器无法解析或者访问; |
401 |
Unauthorized |
请求要求用户的身份认证; |
402 |
Payment Required |
此状态码保留,为以后使用; |
403 |
Forbidden |
服务器理解请求客户端的请求,但是拒绝执行此请求; |
404 |
Not Found |
服务器没有该资源,请求的文件找不到; |
405 |
Method Not Allowed |
客户端请求中的方法被禁止; |
406 |
Not Acceptable |
服务器无法根据客户端请求的内容特性完成请求; |
499 |
Client has closed connection |
服务器端处理的时间过长; |
500 |
Internal Server Error |
服务器内部错误,无法完成请求; |
502 |
Bad Gateway |
服务器返回错误代码或者代理服务器错误的网关; |
503 |
Service Unavailable |
服务器无法响应客户端请求,或者后端服务器异常; |
504 |
Gateway Time-out |
网关超时或者代理服务器超时; |
505 |
HTTP Version not supported |
服务器不支持请求的HTTP协议的版本,无法完成处理。 |
表9-3 HTTP常用状态码
2.7 HTTP MIME 类型支持
浏览器接收到WEB服务器的Response信息,浏览器会进行解析,在解析页面之前,浏览器必须启动本地相应的应用程序来处理获取到的文件类型。
基于多用途互联网邮件扩展类型 (Multipurpose Internet Mail Extensions,MIME),可以明确某种文件在客户端用某种应用程序来打开,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开,设计之初是为了在发送电子邮件时附加多媒体数据,让邮件客户程序能根据其类型进行处理。然而当它被HTTP协议支持之后,它使得HTTP传输的不仅是普通的文本,可以支持更多文件类型、多媒体音、视频等。
在HTTP协议中,HTTP Response消息,MIME类型被定义在Content-Type header中,例如:Content-Type: text/html,表示默认指定该文件为html类型,在浏览器端会以HTML格式来处理。
在最早的HTTP协议中,并没有附加的数据类型信息,所有传送的数据都被客户程序解释为超文本标记语言HTML文档,为了支持多媒体数据类型,新版HTTP协议中就使用了附加在文档之前的MIME数据类型信息来标识数据类型,如表9-4所示:
Mime-Types(MIME类型) |
Dateiendung (扩展名) |
Bedeutung |
application/msexcel |
*.xls *.xla |
Microsoft Excel Dateien |
application/mshelp |
*.hlp *.chm |
Microsoft Windows Hilfe Dateien |
application/mspowerpoint |
*.ppt *.ppz *.pps *.pot |
Microsoft Powerpoint Dateien |
application/msword |
*.doc *.dot |
Microsoft Word Dateien |
application/octet-stream |
*.exe |
exe |
application/pdf |
|
Adobe PDF-Dateien |
application/post****** |
*.ai *.eps *.ps |
Adobe Post******-Dateien |
application/rtf |
*.rtf |
Microsoft RTF-Dateien |
application/x-httpd-php |
*.php *.phtml |
PHP-Dateien |
application/x-java****** |
*.js |
serverseitige Java******-Dateien |
application/x-shockwave-flash |
*.swf *.cab |
Flash Shockwave-Dateien |
application/zip |
*.zip |
ZIP-Archivdateien |
audio/basic |
*.au *.snd |
Sound-Dateien |
audio/mpeg |
*.mp3 |
MPEG-Dateien |
audio/x-midi |
*.mid *.midi |
MIDI-Dateien |
audio/x-mpeg |
*.mp2 |
MPEG-Dateien |
audio/x-wav |
*.wav |
Wav-Dateien |
image/gif |
*.gif |
GIF-Dateien |
image/jpeg |
*.jpeg *.jpg *.jpe |
JPEG-Dateien |
image/x-windowdump |
*.xwd |
X-Windows Dump |
text/css |
*.css |
CSS Stylesheet-Dateien |
text/html |
*.htm *.html *.shtml |
-Dateien |
text/java****** |
*.js |
Java******-Dateien |
text/plain |
*.txt |
reine Textdateien |
video/mpeg |
*.mpeg *.mpg *.mpe |
MPEG-Dateien |
video/vnd.rn-realvideo |
*.rmvb |
realplay-Dateien |
video/quicktime |
*.qt *.mov |
Quicktime-Dateien |
video/vnd.vivo |
*viv *.vivo |
Vivo-Dateien |
表9-4 HTTP MIME类型详解