nginx 入门、安装、命令、配置、优化
操作系统:CentOS 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 {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
# root html;
# index index.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开发
Tengine http://tengine.taobao.org/
Openresty http://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配置文件
#user nobody; #worker用户
worker_processes 1; #worker进程数,cat /proc/cpuinfo | grep "processor" | wc -l
#error_log logs/error.log; #错误日志路径
#error_log logs/error.log notice; #错误日志路径notice级别
#error_log logs/error.log info; #错误日志路径info级别
#pid logs/nginx.pid; #pid路径
events { #events块
worker_connections 1024; #每个worker最大开启连接数,ulimit -n
}
http { #http块
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"';
# main级别日志输出格式
#access_log logs/access.log main; #访问日志main级别
sendfile on; #开启sendfile,作为静态服务器时性能显著提高
#tcp_nopush on; #包攒到一定大小再发送,开启sendfile时生效
#keepalive_timeout 0;
keepalive_timeout 65; #连接超时(秒)
#gzip on; #开启压缩
server { #server段
listen 80; #监听80端口
server_name localhost; #绑定localhost
#charset koi8-r;
#access_log logs/host.access.log main;
location / { #匹配uri
root html; #设置root目录
index index.html index.htm; #默认首页
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html; #错误码和错误页
location = /50x.html {
root html;
}
}
}
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 {
listen 80 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 {
listen 80;
server_name _;
location =/index.html {
return 200 "index\n";
}
}
server {
listen 81;
server_name _;
location /proxy {
proxy_pass http://localhost/;
}
}
如果不想改变原地址中的uri,proxy_pass中就不要写uri!
4.负载均衡
利用一定的策略将网络负载分摊到网络集群的各个服务上,从而减轻服务器负载并提高用户体验。
server {
listen 80 default_server;
server_name _;
location / {
proxy_pass http://balance;
}
}
upstream balance {
server localhost:81;
server localhost:82;
}
server {
listen 81;
server_name _;
location / {
return 200 "1\n";
}
}
server {
listen 82;
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_processes 4; #auto=逻辑核数,高io的可以再调大;如果服务器有其他负载按需设置;
worker_cpu_affinity 0001 0010 0100 1000; #cpu亲和性,指定每个线程运行在哪个核上;
events {
use epoll; #显式指定采用epoll,如果不知道是什么请让Nginx自己决定最优方案;
worker_connections 1024;#每个进程最大可打开连接数受制于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;