本文陆续介绍 Nginx 的功能、配置、及一些实用场景(待完善...)。javascript
Nginx,不少工程师喜欢读成'恩基克思'。Nginx 是一款高性能的HTTP和反向代理服务器软件,第一个开源版本诞生于2004年,虽然诞生较晚但通过十多年的发展,已经成为很是流行的 web 服务器软件。其发展速度和流行程度已经远远超过其它同类软件,成为大型网站和高并发网站的首选。php
Nginx 之因此可以脱颖而出,一方面是由于市场每每会选择简单实用的技术,另外一方面是由于web服务器的高并发已经成为趋势,而高并发又要求架构具备健壮性和可伸缩性。Nginx 的特性迎合了市场的这个发展趋势,它是为性能而生,从发布以来一直侧重于高性能,高并发,低 CPU 内存消耗;在功能方面:负载均衡,反向代理,访问控制,热部署,高扩展性等特性又十分适合现代的网络架构。更难得的是配置简单文档丰富,大大下降了学习的门槛。这样稳定,性能强,功能丰富又简单的产品固然会受欢迎了。css
Apache 自1990年发布以来,一直是 web 服务器市场的霸主。Nginx 虽然发布较晚,可是却由于在高并发下卓越的表现而迅速崭露头角。最初,Nginx 只是做为 Apache 在高并发场景下的补充,二者结合辅助使用。而如今,Nginx 随着迭代功能,在极多数场合已经能够抛弃老大哥来独当一面了。html
Nginx 和 Apache 相同点:前端
Nginx 的优点:java
Nginx 的劣势:nginx
Nginx 由内核和一系列模块组成,内核提供 Web Server 的基本功能,如启动网络协议,建立运行环境,接收和分配客户端请求,处理模块之间的交互。Nginx 的各类功能和操做都由模块来实现。
Nignx 的模块从结构上分为:web
这样的设计使 Nginx 方便开发和扩展,也正所以才使得 Nginx 功能如此强大。Nginx 的模块默认编译进 Nginx 中,若是须要增长或删除模块,须要从新编译 Nginx ,这一点不如 Apache 的动态模块加载方便。(若是需动态加载模块,可使用兼容 Nginx 的web服务器 Tengine )缓存
Nginx 使用一个多进程模型来应对外来需求,其中一个 master 进程,多个 worker 进程。master 进程负责管理 Nginx 自己和其余 worker 进程。服务器
全部实际上的业务处理逻辑都在 worker 进程,其内有一个无限循环执行的函数,不断处理来自客户端的请求,并进行处理,直到整个 Nginx 服务中止。
worker 进程中,ngx_worker_process_cycle() 就是这个无线循环的函数。内部对一个请求的简单处理流程以下:
如图展现了 Nginx 模块常规的HTTP请求和响应的过程:
#运行用户 user nobody; #启动进程,一般设置成和cpu的数量相等 worker_processes 1; #全局错误日志及PID文件 #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; #工做模式及链接数上限 events { #单个后台worker process进程的最大并发连接数 worker_connections 1024; } http { #设定mime类型,类型由mime.type文件定义 include mime.types; default_type application/octet-stream; #设定日志格式 log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log logs/access.log main; #sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件, #对于普通应用,必须设为 on, #若是用来进行下载等应用磁盘IO重负载应用,可设置为 off, #以平衡磁盘与网络I/O处理速度,下降系统的uptime. sendfile on; #tcp_nopush on; #链接超时时间 #keepalive_timeout 0; keepalive_timeout 65; #开启gzip压缩 #gzip off; #设定虚拟主机配置 server { #侦听80端口 listen 80; #定义使用 www.nginx.cn访问 server_name www.nginx.cn; #定义服务器的默认网站根目录位置 root html; #设定本虚拟主机的访问日志 access_log logs/nginx.access.log main; #默认请求 location / { #定义首页索引文件的名称 index index.php index.html index.htm; } # 定义错误提示页面 error_page 500 502 503 504 /50x.html; location = /50x.html { } #静态文件,nginx本身处理 location ~ ^/(images|javascript|js|css|flash|media|static)/ { #过时30天,静态文件不怎么更新,过时能够设大一点, #若是频繁更新,则能够设置得小一点。 expires 30d; } #PHP 脚本请求所有转发到 FastCGI处理. 使用FastCGI默认配置. location ~ .php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } #禁止访问 .htxxx 文件 location ~ /.ht { deny all; } } }
不像其余系统软件,Nginx 仅由几个命令行参数
-c </path/to/config> // 为Nginx指定一个配置文件,来代替缺省的 -t // 不运行,仅仅测试配置。 -v // 显示Nginx的版本 -V // 显示Nginx的版本,编译器版本和配置参数。
Nginx 启动、中止、重启命令
// 启动 sudo nginx // 或者 sudo /usr/local/Cellar/nginx/1.12.0_1/bin/nginx // 若是不知道实际路径,能够nginx —V查看 // 中止命令 ps -ef | grep nginx // 查看占用进程 kill -QUIT nginx主进程号 // 从容中止 kill -TERM nginx主进程号 // 快速中止 kill -9 nginx主进程号 // 强制中止 // 或者 kill -QUIT `cat /usr/local/var/run/nginx.pid` // 若是不知道实际路径,能够nginx —V查看 // 重启命令 kill -QUIT `cat /usr/local/var/run/nginx.pid` sudo /usr/local/Cellar/nginx/1.12.0_1/bin/nginx
通常门户网站在访问时,会有 PC 和 H五、Pad 几个适配版本,咱们常会有这样的需求,在网站被访问时候,服务端来识别用户是 PC 设备仍是移动设备,跳转返回相应适配版本的页面。
第一步一般是判断 HTTP 请求头的 User-Agent ,基本原理是经过正则匹配判断,有一套开源的解决方案能够直接使用:http://detectmobilebrowsers.com/,下载 Nginx 配置便可。
第二步就是经过以前对设备的判断,来反向代理到不一样的版本。
location / { proxy_pass http://leju.com if ($mobile_rewrite = perform) { proxy_pass http://m.leju.com/ # 手机版 } }
第三步,由于可能错误判断设备,或者用户就想指定访问某种设备版本,在页面底部,一般会有连接跳转其余版本。
<div class="ll_btn"> <a href="http://www.leju.com#ln=index_fdh">电脑版</a> <a href="http://pad.leju.com/?source=chuping#ln=index_fdh">PAD版</a> <a href="http://m.leju.com/touch/app/app_download.html?source=chupinghp#ln=index_fdh">客户端</a> </div>
同时在 Nginx 中加入判断,若是包含指定 source 参数,则指定进入某个版本。
前端开发中,咱们常常须要在多个环境(开发、内测、外测、预发、正式环境)进行切换。
咱们一般经过切换 host 指向搭配机器绑定不一样域名的方式去实现:好比测试环境是dev.j.esf.sina.com
,正式环境是j.esf.sina.com
,搭配不一样的 host 指向,能够造成多种组合。
而经过反向代理的Nginx,更容易处理这种代理转发的问题:
set $env_id “123.59.190.206”; if( $http_cookie~* "host_id(\S+)(;.*|$)"){ set $env_id $1; } location / { proxy_set_header Host $host; proxy_pass http://$env_id:80; }
...场景待续