十分鐘瞭解Nginx
nginx 入門、安裝、命令、配置、優化
作業系統:CentOS Linux 7
Nginx版本:yum安裝1.12.2 、編譯安裝1.14.2
一、安裝
1. yum安裝
安裝源
[root@localhost ~]# yum list nginx [root@localhost ~]# rm -rf /etc/yum.repos.d/* [root@localhost ~]# curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo [root@localhost ~]# curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo [root@localhost ~]# yum clean all && yum makecache
啟動一個Nginx
[root@localhost ~]# yum install -y nginx [root@localhost ~]# nginx [root@localhost ~]# curl localhost
yum安裝Nginx的目錄結構
[root@localhost ~]# find / -name nginx /etc/logrotate.d/nginx #滾動日誌 /etc/nginx #配置檔案 /usr/lib64/perl5/vendor_perl/auto/nginx #http-perl /usr/lib64/nginx #molules /usr/sbin/nginx #bin檔案 /usr/share/nginx #html/molules /var/lib/nginx #tmp /var/log/nginx #log [root@localhost ~]# yum remove -y nginx [root@localhost ~]# find / -name nginx
2. 編譯安裝
準備環境依賴
[root@localhost ~]# rm -rf /etc/yum.repos.d/* [root@localhost ~]# curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo [root@localhost ~]# curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo [root@localhost ~]# yum install -y gcc gcc-c++ make pcre-devel zlib-devel
編譯安裝Nginx
[root@localhost ~]# curl -o nginx-1.14.2.tar.gz http://nginx.org/download/nginx-1.14.2.tar.gz [root@localhost ~]# tar -xf nginx-1.14.2.tar.gz [root@localhost ~]# cd nginx-1.14.2 [root@localhost nginx-1.14.2]# ./configure [root@localhost nginx-1.14.2]# make && make install [root@localhost nginx-1.14.2]# find / -name nginx /root/nginx-1.14.2/objs/nginx #編譯檔案 /usr/local/nginx #安裝目錄 /usr/local/nginx/sbin/nginx #bin檔案
啟動一個Nginx
[root@localhost sbin]# ./nginx [root@localhost sbin]# curl localhost
3. 編譯安裝進階
3.1. 指定編譯引數
[root@localhost nginx-1.14.2]# ./configure --prefix=$PWD/nginx
3.2. 安裝官方模組
[root@localhost nginx-1.14.2]# ./configure --prefix=$PWD/nginx --with-stream
3.3. 安裝自定義模組
3.3.1 編寫Nginx自定義模組
[root@localhost nginx-1.14.2]# mkdir -p modules/ngx_http_hello_world_module [root@localhost nginx-1.14.2]# cd modules/ngx_http_hello_world_module [root@localhost ngx_http_hello_world_module]# touch ngx_http_hello_world_module.c config
ngx_http_hello_world_module.c
#include "ngx_core.h" #include "ngx_string.h" #include "ngx_buf.h" #include "ngx_module.h" #include "ngx_conf_file.h" #include "ngx_http.h" #include "ngx_http_request.h" #include "ngx_http_config.h" #include "ngx_http_core_module.h" static ngx_int_t ngx_http_hello_world_handler(ngx_http_request_t *r) { if (!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD))) return NGX_HTTP_NOT_ALLOWED; ngx_int_t rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) return rc; ngx_str_t type = ngx_string("text/plain"); ngx_str_t response = ngx_string("Hello World!\n"); r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = response.len; r->headers_out.content_type = type; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) return rc; ngx_buf_t *b; b = ngx_create_temp_buf(r->pool, response.len); if (b == NULL) return NGX_HTTP_INTERNAL_SERVER_ERROR; ngx_memcpy(b->pos, response.data, response.len); b->last = b->pos + response.len; b->last_buf = 1; ngx_chain_t out; out.buf = b; out.next = NULL; return ngx_http_output_filter(r, &out); } static char *ngx_http_hello_world(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_core_loc_conf_t *clcf; clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); clcf->handler = ngx_http_hello_world_handler; return NGX_CONF_OK; } static ngx_command_t ngx_http_hello_world_commands[] = { {ngx_string("hello_world"), NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LMT_CONF | NGX_CONF_NOARGS, ngx_http_hello_world, NGX_HTTP_LOC_CONF_OFFSET, 0, NULL}, ngx_null_command }; static ngx_http_module_t ngx_http_hello_world_module_ctx = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; ngx_module_t ngx_http_hello_world_module = { NGX_MODULE_V1, &ngx_http_hello_world_module_ctx, ngx_http_hello_world_commands, NGX_HTTP_MODULE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NGX_MODULE_V1_PADDING };
config
ngx_addon_name=ngx_http_hello_world_module HTTP_MODULES="$HTTP_MODULES ngx_http_hello_world_module" NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_hello_world_module.c"
3.3.2 編譯自定義模組
[root@localhost nginx-1.14.2]# ./configure --prefix=$PWD/nginx --with-stream --add-module=modules/ngx_http_hello_world_module [root@localhost nginx-1.14.2]# make && make install [root@localhost nginx-1.14.2]# vim nginx/conf/nginx.conf
server { listen80; server_namelocalhost; #charset koi8-r; #access_loglogs/host.access.logmain; location / { # roothtml; # indexindex.html index.htm; hello_world; } }
3.3.3 啟動nginx,測試hello world
[root@localhost nginx-1.14.2]# nginx/sbin/nginx [root@localhost nginx-1.14.2]# curl localhost Hello World!
3.3.4 Nginx開發
Tenginehttp://tengine.taobao.org/
Openrestyhttp://openresty.org/cn/
二、Nginx命令
[root@localhost ~]# nginx -h nginx version: nginx/1.14.2 Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives] Options: -?,-h: this help -v: show version and exit -V: show version and configure options then exit -t: test configuration and exit -T: test configuration, dump it and exit -q: suppress non-error messages during configuration testing -s signal: send signal to a master process: stop, quit, reopen, reload -p prefix: set prefix path (default: /root/nginx-1.14.2/nginx/) -c filename: set configuration file (default: conf/nginx.conf) -g directives : set global directives out of configuration file
[root@localhost ~]# nginx -v nginx version: nginx/1.14.2 [root@localhost ~]# nginx -V nginx version: nginx/1.14.2 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC) configure arguments: --prefix=/root/nginx-1.14.2/nginx --with-stream --add-module=modules/ngx_http_hello_world_module
[root@localhost ~]# nginx -t nginx: the configuration file /root/nginx-1.14.2/nginx/conf/nginx.conf syntax is ok nginx: configuration file /root/nginx-1.14.2/nginx/conf/nginx.conf test is successful
[root@localhost ~]# nginx -s quit [root@localhost ~]# nginx -c /etc/nginx-2.conf [root@localhost ~]# nginx -g 'worker_processes 4;'
三、Nginx配置檔案
#usernobody; #worker使用者 worker_processes1; #worker程序數,cat /proc/cpuinfo | grep "processor" | wc -l #error_loglogs/error.log; #錯誤日誌路徑 #error_loglogs/error.lognotice; #錯誤日誌路徑notice級別 #error_loglogs/error.loginfo; #錯誤日誌路徑info級別 #pidlogs/nginx.pid; #pid路徑 events { #events塊 worker_connections1024; #每個worker最大開啟連線數,ulimit -n } http { #http塊 includemime.types; #引入媒體檔案 default_typeapplication/octet-stream; #預設響應型別 #log_formatmain'$remote_addr - $remote_user [$time_local] "$request" ' #'$status $body_bytes_sent "$http_referer" ' #'"$http_user_agent" "$http_x_forwarded_for"'; # main級別日誌輸出格式 #access_loglogs/access.logmain; #訪問日誌main級別 sendfileon; #開啟sendfile,作為靜態伺服器時效能顯著提高 #tcp_nopushon; #包攢到一定大小再發送,開啟sendfile時生效 #keepalive_timeout0; keepalive_timeout65; #連線超時(秒) #gzipon; #開啟壓縮 server { #server段 listen80; #監聽80埠 server_namelocalhost; #繫結localhost #charset koi8-r; #access_loglogs/host.access.logmain; location / { #匹配uri roothtml; #設定root目錄 indexindex.html index.htm; #預設首頁 } #error_page404/404.html; # redirect server error pages to the static page /50x.html # error_page500 502 503 504/50x.html; #錯誤碼和錯誤頁 location = /50x.html { roothtml; } } }
main/events塊指令集http://nginx.org/en/docs/ngx_core_module.html
http塊指令集http://nginx.org/en/docs/http/ngx_http_core_module.html
四、基本用例
1. 靜態資源伺服器
直接啟動Nginx就是個靜態資源伺服器。
alias和root的區別
location /foo { root /a/b; } # 當請求的uri為/foo/c.html時,實際請求的檔案路徑是/a/b/foo/c.html location /bar { alias /x/y; } # 當請求的uri為/bar/z.html時,實際請求的檔案路徑是/x/y/z.html # alias對末尾的/敏感,alias末尾與uri末尾保持一致
rewrite的用法
location /foo { rewrite /foo/(.*) /bar/$1 break; root /a/b; } # 當請求的uri為/foo/c.html時,將請求改寫為/bar/c.html,實際請求的檔案路徑是/a/b/bar/c.html location /foo { rewrite /foo/(.*) /bar/$1 last; root /a/b; } # 當請求的uri為/foo/c.html時,將請求改寫為/bar/c.html,重新尋找location塊匹配,實際請求的檔案路徑是/x/y/c.html location /foo { rewrite /foo/(.*) /bar/$1 permanent; } # 當請求的uri為/foo/c.html時,將請求改寫為/bar/c.html,直接返回301跳 location /foo { rewrite /foo/(.*) /bar/$1 redirect; } # 當請求的uri為/foo/c.html時,將請求改寫為/bar/c.html,直接返回302跳
break/last是同一個連線的內部處理過程,permanent/redirect是兩次連線;
break不再執行location匹配,last執行多次location匹配,通常在server中使用last,在location中使用break;
301跳會快取,302跳不會;
2. 簡單檔案伺服器
server { listen80 default_server; listen[::]:80 default_server; server_name_; root/usr/share/nginx/html; include /etc/nginx/default.d/*.conf; location / { autoindex on; } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } }
當路徑下存在index.html index.htm 時autoindex不生效
3.代理伺服器
3.1正向代理
正向代理:代理客戶端稱為正向代理,如爬蟲使用的代理伺服器。基本是固定寫法。
server { resolver 8.8.8.8; listen 8888; location / { proxy_pass http://$http_host$request_uri; proxy_set_header HOST $http_host; } }
3.2 反向代理
正向代理:代理服務端稱為反向代理,如通過代理java隱藏埠。基本是固定寫法。
server { listen80; server_name_; location =/index.html { return 200 "index\n"; } } server { listen81; server_name_; location /proxy { proxy_pass http://localhost/; } }
如果不想改變原地址中的uri,proxy_pass中就不要寫uri!
4.負載均衡
利用一定的策略將網路負載分攤到網路叢集的各個服務上,從而減輕伺服器負載並提高使用者體驗。
server { listen80 default_server; server_name_; location / { proxy_pass http://balance; } } upstream balance { server localhost:81; server localhost:82; } server { listen81; server_name_; location / { return 200 "1\n"; } } server { listen82; server_name_; location / { return 200 "2\n"; } }
Nginx負載均衡策略:round robin、weight、ip_hash、least_conn、fair(3)、url_hash(3)
5.TCP/UDP代理
TCP/UDP協議的反向代理。
stream{ upstream mysql{ server localhost:3306; } server{ listen 3307; proxy_pass mysql; } }
需要stream模組支援
五、深度優化
1、安全優化
1.1 隱藏Nginx軟體名和版本號
[root@localhost /]# curl -I localhost HTTP/1.1 200 OK Server: nginx/1.12.2 Date: Tue, 23 Apr 2019 06:23:27 GMT Content-Type: application/octet-stream Content-Length: 2 Connection: keep-alive
- 方案1:修改nginx.conf新增
server_tokens off;
- 方案2:修改$NGINX_HOME/src/core/nginx.h(不推薦 )
#define NGINX_VERSION"1.14.2" #define NGINX_VER"nginx/" NGINX_VERSION // 隨意修改以上兩個欄位(注意這是C程式碼,#不是註釋的意思) #define NGINX_VERSION"7.5.1" #define NGINX_VER"IIS/" NGINX_VERSION
- 方案3:修改$NGINX_HOME/src/core/nginx.h
static u_char ngx_http_server_string[] = "Server: nginx" CRLF; static u_char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF; // 隨意修改以上兩個欄位 static u_char ngx_http_server_string[] = "Server: IIS" CRLF; static u_char ngx_http_server_full_string[] = "Server: " "IIS/7.5.1" CRLF;
- 隱藏40x、50x頁面的軟體名版本號:修改nginx.conf新增
error_page 400 401 402 403 404 405 415 /40x.html; location = /40x.html { return 200 "not found."; } error_page 500 502 503 504 /50x.html; location = /50x.html { return 200 "error."; }
1.2 非法域名解析
server { listen 80 default_server; server_name _; rewrite ^(.*) http//:www.example.com/$1 permanent; }
1.3 黑白名單
location / { allow 127.0.0.1; deny 192.168.1.1; }
1.4 DDOS攻擊
# 訪問頻率限制 limit_req_zone $binary_remote_addr zone=perip:100m rate=1r/s; server { limit_req zone=perip burst=5 nodelay; }
2、效能優化
2.1 優化程序和連線數
worker_processes4; #auto=邏輯核數,高io的可以再調大;如果伺服器有其他負載按需設定; worker_cpu_affinity 0001 0010 0100 1000; #cpu親和性,指定每個執行緒執行在哪個核上; events { use epoll;#顯式指定採用epoll,如果不知道是什麼請讓Nginx自己決定最優方案; worker_connections1024;#每個程序最大可開啟連線數受制於ulimit -n; }
2.2 高效檔案傳輸
# 設定傳輸引數 sendfile on; tcp_nopush on; tcp_nodelay on; server_tokens off; server_names_hash_bucket_size 128; server_names_hash_max_size 512; keepalive_timeout 65; client_header_timeout 15s; client_body_timeout 15s; send_timeout 60s; # 設定壓縮引數 gzip on; gzip_disable "msie6"; gzip_min_length 1k; gzip_vary on; gzip_proxied any; gzip_comp_level 3; gzip_buffers 16 8k; gzip_http_version 1.1; gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript image/jpeg image/gif image/png; # 為靜態資源設定合理的過期時間 expires-1;