Nginx服务器的学习和配置

后台服务器搭起来

2016-02-01 | 阅读

Nginx命令

  • 启动 : nginx
  • 停止 : nginx -s stop
  • 重载 : nginx -s reload

Nginx服务器配置

Nginx配置文件nginx.conf(位于/etc/nginx/nginx.conf)分成四个部分,配置完成后,使用nginx -t来测试配置是否正确,使用nginx -s reload重载:

  • main : 全局设置,影响全局
  • server : 主机设置,用于指定虚拟主机域名 IP 和端口
  • upstream : 上游服务器设置,主要为反向代理 负载均衡相关配置
  • location : URL匹配特定位置后的设置

server继承main,location继承server;upstream既不会继承指令也不会被继承. 即最外层是main,然后是server ,server里面还有location 的配置,而upstream不与三者有关系.

nginx配置文件的匹配规则

  • = 表示精确匹配,如location = / ,表示只有域名的情况
  • ^~ 表示已某常规字符串开头,不是正则表达式
  • ~ 表示区分大小写的正则匹配
  • ~* 表示不区分大小写的正则匹配
  • / 表示通用匹配

匹配是有优先级的,表示看顺序,而是看匹配规则的优先级,依次是

=表示的精确匹配 > 完整路径 > ^~ > ~~* > 部分路径 > 通用匹配/

全局变量

  • $args : #这个变量等于请求行中的参数,同$query_string
  • $content_length : 请求头中的Content-length字段。
  • $content_type : 请求头中的Content-Type字段。
  • $document_root : 当前请求在root指令中指定的值。
  • $host : 请求主机头字段,否则为服务器名称。
  • $http_user_agent : 客户端agent信息
  • $http_cookie : 客户端cookie信息
  • $limit_rate : 这个变量可以限制连接速率。
  • $request_method : 客户端请求的动作,通常为GET或POST。
  • $remote_addr : 客户端的IP地址。
  • $remote_port : 客户端的端口。
  • $remote_user : 已经经过Auth Basic Module验证的用户名。
  • $request_filename : 当前请求的文件路径,由root或alias指令与URI请求生成。
  • $scheme : HTTP方法(如http,https)。
  • $server_protocol : 请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
  • $server_addr : 服务器地址,在完成一次系统调用后可以确定这个值。
  • $server_name : 服务器名称。
  • $server_port : 请求到达服务器的端口号。
  • $request_uri : 包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。
  • $uri : 不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。
  • $document_uri : 与$uri相同。

main全局配置

  • user www www

    用户名用户组设定

  • woker_processes 1

    nginx进程数,建议设置为CPU核心数

  • worker_cpu_affinity

    在高并发情况下,通过设置cpu粘性来降低由于多CPU核切换造成的寄存器等现场重建带来的性能损耗

  • error_log /var/log/nginx/error.log info;

    全局错误日志定义类型,[debug info notice warn error crit ]
  • pid /run/nginx.pid;

    进程文件.

  • worker_rlimit_nofile 65535;

    一个nginx进程打开的最多文件描述符数目,理论上是系统最多打开文件数与nginx进程数相除,但nginx分配请求不均匀,所以直接与这个系统最大数量一样就可以了.

http访问设定

#设定http服务器
http
{
	include mime.types; #文件扩展名与文件类型映射表
	default_type application/octet-stream; #默认文件类型
	#charset utf-8; #默认编码
	server_names_hash_bucket_size 128; #服务器名字的hash表大小
	client_header_buffer_size 32k; #上传文件大小限制
	large_client_header_buffers 4 64k; #设定请求缓冲大小
	client_max_body_size 8m; #设定请求缓冲大小
	sendfile on; #开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。
	autoindex on; #开启目录列表访问,合适下载服务器,默认关闭。
	tcp_nopush on; #防止网络阻塞
	tcp_nodelay on; #防止网络阻塞
	keepalive_timeout 120; #长连接超时时间,单位是秒
	
	#FastCGI相关参数是为了改善网站的性能:减少资源占用,提高访问速度。
	fastcgi_connect_timeout 300;
	fastcgi_send_timeout 300;
	fastcgi_read_timeout 300;
	fastcgi_buffer_size 64k;
	fastcgi_buffers 4 64k;
	fastcgi_busy_buffers_size 128k;
	fastcgi_temp_file_write_size 128k;
	
	#gzip模块设置
	gzip on; #开启gzip压缩输出
	gzip_min_length 1k; #最小压缩文件大小
	gzip_buffers 4 16k; #压缩缓冲区
	gzip_http_version 1.0; #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
	gzip_comp_level 2; #压缩等级
	gzip_types text/plain application/x-javascript text/css application/xml;
	#压缩类型,默认就已经包含text/html,所以下面就不用再写了,写上去也不会有问题,但是会有一个warn。
	gzip_vary on;
	#limit_zone crawler $binary_remote_addr 10m; #开启限制IP连接数的时候需要使用
	
	upstream blog.ha97.com {
	#upstream的负载均衡,weight是权重,可以根据机器配置定义权重。weigth参数表示权值,权值越高被分配到的几率越大。
	server 192.168.80.121:80 weight=3;
	server 192.168.80.122:80 weight=2;
	server 192.168.80.123:80 weight=3;
	}
	
	#日志格式设定
	log_format access '$remote_addr - $remote_user [$time_local] "$request" '
	'$status $body_bytes_sent "$http_referer" '
	'"$http_user_agent" $http_x_forwarded_for';
	#定义本虚拟主机的访问日志
	access_log /var/log/nginx/ha97access.log access;
}

server主机设置

server{
	listen 80; #监听80端口
	#域名,可以多个,用空格隔开,也可以使用正则表达式.对于匹配到域名的请求,则使用该server定义的内容来进行响应
	server_name www.baidu.com baidu.com;
	# 作为主页的文件
	index index.html index.php;
	# 首页位置
	root /usr/share/nginx/html/Blog/_site;
	# 所有的正则表达式,都以~开始.
	location ~.*\.(php|php5)?${
		#使用fastcgi将域名请求转发到php服务器.
		fastcgi_pass 127.0.0.1:9000;
		fastcgi_index index.php;
		include fastcgi.conf;
	}
	#图片缓存时间设置
	location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
	{
		expires 10d;
	}
	#JS和CSS缓存时间设置
	location ~ .*\.(js|css)?$
	{
		expires 1h;
	}
	
	# 反向代理的详细学习
	location /{
		proxy_pass http://127.0.0.1:8080;
		# 重定向关闭.
		proxy_redirect off;
		# 反向代理设置头信息,客户端ip
		proxy_set_header X-Real-IP $remote_addr;
		#后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	 	proxy_set_header Host $host;
	 	
		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)
		proxy_temp_file_write_size 64k;#设定缓存文件夹大小,大于这个值,将从upstream服务器传
	}
	

	
}

反向代理

常见的动静分离反向代理配置

	#所有jsp的页面均交由tomcat处理
	location ~ .(jsp|jspx|do)?$ {
		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://127.0.0.1:8080;
	}
	#所有静态文件由nginx直接读取不经过tomcat
	location ~ .*.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$
	{ expires 15d; }
	location ~ .*.(js|css)?$
	{ expires 1h; }

反向代理的路径问题

反向代理的路径后加不加 /,会导致最终的路径有很大区别 , 有以下4种情况:

location /proxy/ {
		proxy_pass http://127.0.0.1/;
}

代理到URL:http://127.0.0.1/test.html

location /proxy/ {
		proxy_pass http://127.0.0.1;
}

代理到URL:http://127.0.0.1/proxy/test.html

location /proxy/ {
		proxy_pass http://127.0.0.1/aaa/;
}

代理到URL:http://127.0.0.1/aaa/test.html

location /proxy/ {
		proxy_pass http://127.0.0.1/aaa;
}

代理到URL:http://127.0.0.1/aaatest.html

Rewrite规则

rewrite使用nginx并结合正则表达式或标志位来实现url的重写.可以放在server locationif{}中,只能对域名后出去参数外的字符串起作用.基本语法rewrite regex replacement [flag].

进行重写时,正则表达式匹配中用()小括号之间对应的匹配内容用$1来引用,第二个小括号内的内容用$2来表示.

重写后,会重新加载并重新进行匹配.

举例:

rewrite '^/images/([a-z]*)/([a-z0-9]*)/(.*)\.(png|jpg|gif)$' /data?file=$3.$4;

将图片/images/agagasg/wagawgawg2515/img.png重写成/data?file=img.png

配置https

配置https,要在安装时,添加配置参数 --with-http_ssl_module,.使用这个参数需要安装好openssl-devel.而对于已有的nginx,如果不想重新安装,首先可以用nginx -V来查看原来编译时带了哪些参数,然后直接编译,替换二进制文件就可以直接更换配置,而不用改当前已经安装和配置好的网站

啊,然而已经卸载了之前的nginx了.

./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-file-aio --with-http_realip_module
//重新安装好后,会遇到一些配置问题,其中一个问题是 invalid PID number,需要执行以下代码.
sudo nginx -c /usr/local/nginx/conf/nginx.conf

制作CA证书 :

#ca.key CA私钥:
openssl genrsa -des3 -out ca.key 2048
#制作解密后的CA私钥:
openssl rsa -in ca.key -out ca_decrypted.key
#ca.crt CA根证书(公钥):
openssl req -new -x509 -days 7305 -key ca.key -out ca.crt

制作网站的证书,并用CA签名认证

#生成证书私钥
openssl genrsa -des3 -out blog.luoxianming.cn.pem 1024
# 生成解密后的证书私钥
openssl rsa -in blog.luoxianming.cn.pem -out blog.luoxianming.cn.key
# 生成签名请求:
openssl req -new -key blog.luoxianming.cn.pem -out blog.luoxianming.cn.csr
# 在common name中填入网站域名,如blog.luoxianming.cn即可生成改站点的证书,同时也可以使用泛域名如*.luoxianming.cn来生成所有二级域名可用的网站证书。
用CA进行签名:
openssl ca -policy policy_anything -days 1460 -cert ca.crt -keyfile ca.key -in blog.luoxianming.cn.csr -out blog.luoxianming.cn.crt

这一步的时候会出一些错误/etc/pki/CA/index.txt: No such file or directory,因为openssl没有配置好,简单的解决方法如下:

touch /etc/pki/CA/index.txt
touch /etc/pki/CA/serial
echo 00 > /etc/pki/CA/serial

然后配置好了,运行nginx,结果发现https服务器还是访问不了,最后发现原因是因为防火墙没开放443端口.这里可以看出来https是让用户直接访问443端口,与反向代理还是有很大区别的,反向代理是nginx来访问相关的端口,并返回数据,做一个代理.

对于https的优化,在http{}中加入:

# https的session缓存,1m可以放4000个session
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

在配置https的虚拟主机server{}中加入:

keepalive_timeout 70;

TCP的三次握手,是在发送报文,在TCP中没有请求的概念,而HTTP的请求会被封装成多个报文分发,TCP建立连接后,发送和接受完一次请求后,不立即断开连接,这个延迟时间,也就是这个keepalive_timeout,由于https连接的建立需要验证和加密,所以比正常的HTTP的TCP连接建立还要耗时,所以更应该设置这样一个超时时间,这里是70S.

使用nginx简单搭建一个https服务器.

mac下安装nginx,不能使用brew,因为要加载https模块,所以只能下载文件进行编译,编译时指定openssl地址,

./configure --with-openssl=/usr/local/openssl  --with-http_ssl_module

所以首先要重新安装openssl:

指定安装目录 :

./config --prefix=/usr/local/openssl 

明明本地系统是64位的,却自动设置了32位的,还告诉你,You have about 5 seconds to press Ctrl-C to abort.,蛋疼,好吧,64位应该这样配置:

./Configure darwin64-x86_64-cc --prefix=/usr/local/openssl
make 
make install	

2.制作CA证书

shell> openssl genrsa -des3 -out ca.key 2048
shell> openssl req -new -x509 -days 7305 -key ca.key -out ca.crt

3.生成nginx服务器所需证书,并用CA签名

shell> openssl genrsa -des3 -out client.key 1024
shell> openssl req -new -key client.key -out client.csr
shell> openssl x509 -req -in client.csr -out client.pem -signkey client.key -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650

然后在

server {
        listen 443 ssl;
        server_name  blog.luoxianming.cn;
        #ssl on;

        ssl_certificate  /usr/local/nginx/conf/httpsCA/blog.luoxianming.cn.crt;
        ssl_certificate_key  /usr/local/nginx/conf/httpsCA/blog.luoxianming.cn.key;
        location / {
                 root /usr/local/nginx/html/https;
                index  index.html index.htm;
                }
    }

http协议中域名不区分大小写,其他部分区分大小写

反向代理https

在转发项中,添加一个设置:

proxy_set_header X-Forwarded-Proto  $scheme;

然后再添加一个转发重定向:

proxy_redirect http:// https://;

禁止ip地址访问

listen  80 default_server;
server_name _;
return 404;

could not build the server_names_hash

有时候在server_name处配置的域名太长太多,nginx会报错:

nginx: [emerg] could not build the server_names_hash, you should increase server_names_hash_bucket_size: 64

在nginx.conf中设置`server_names_hash_bucket_size`就可以解决问题了,这个属性时保存域名的哈希表的大小。

配置 http2.0

Nginx终于原生支持HTTP/2了。在编译的时候configure时加入--with-http_v2_module.

编译成功后在conf文件里把listen 443 ssl改为 listen 443 ssl http2即可开启http2支持

server {
    listen 443 ssl http2;
}

Cerbot 获取https 证书

sudo yum install epel-release
sudo yum install certbot

CertBot的standalone模式,这个模式虽然可以配置好服务器,但是以后Renew的时候,需要让服务停止一下,再启动。因此抛弃这个模式,我们使用Webroot配置模式。

CertBot在验证服务器域名的时候,会生成一个随机文件,然后CertBot的服务器会通过HTTP访问你的这个文件,因此要确保你的Nginx配置好,以便可以访问到这个文件。

location ^~ /.well-known/acme-challenge/ {
   default_type "text/plain";
   root     /usr/share/nginx/html;
}

sudo certbot certonly --webroot -w /usr/share/nginx/html/ -d your.domain.com

443 端口执行证书

    ssl_certificate /etc/letsencrypt/live/your.domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your.domain.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/your.domain.com/chain.pem;
    
    
    不过由于这个证书的时效只有90天,我们需要设置自动更新的功能,帮我们自动更新证书的时效。

自动更新证书 先在命令行模拟证书更新:

sudo certbot renew --dry-run

既然模拟成功,我们就使用crontab -e的命令来启用自动任务,命令行:

sudo crontab -e

添加配置:

30 2 * * 1 /usr/bin/certbot renew  >> /var/log/le-renew.log