前言
本篇文章是根据我的实际例子来写的,Nginx的配置就是我的博客网站所运用的
一、安装Ngiinx
我的云服务器是Centos,直接命令安装就可以了,当然你也可以到官网下载源码编译后安装,如果你明确自己需要Nginx哪些功能,比较推荐源码安装,可以根据自己的需求来配置Nginx 编译参数。
yum install nginx -y
安装完成后,就可以在/etc/nginx/ 下找到Nginx的所有配置了。
二、配置Nginx
安装完成之后,我们就需要根据自己的需求配置自己的Nginx了。我们在上篇Nginx文章中写到了Nginx的四种运用,反向代理、动静态资源分离、负载均衡和正向代理。
因为我只有一台服务器,所以没必要使用负载均衡,只运用了方向代理和动静分离。
说明: 我的tomcat端口用的是12345,本地IP为192.168.223.104。没有使用Nginx前浏览器访问http://192.168.223.104:12345/
1、实现反向代理和负载均衡
找到Nginx的配置文件nginx.conf,默认在/etc/nginx/ 目录下。在原始配置情况下,我们只需要改一点行了。如下图:
添加 红色方框中配置就可以了。当我们访问http://192.168.223.104/的时候,Nginx 会把它转给http://192.168.223.104:12345/ 。
在这里我只有一台服务器,如果哪天我突然想再加一台服务器怎么办呢。例如我发现哪天我的服务器访问的人太多,一台服务器忙不过来,我又添加了一台ip为192.168.223.105的服务器,其他都相同。那么我应该怎么配置呢 ?
首先我们要清楚添加一台服务器的目的,很明显是为了进行分压,不能让所有流量都去104那台服务器。所以我们就要通过反向代理实现负载均衡。
最简单的配置,如下图:
添加上面红色方框的配置,修改下面方框的配置就可以了。
从上一篇博客在中我们知道负载均衡有5种策略,上面的配置是默认策略RR。如果需要其他方式实现负载均衡,可以看看Nginx的上一篇博客。
PS: 因为这里所有配置都是我根据自己实际情况写的,但是我只有一台服务器,所以负载均衡不是很必要,也不好测试,只能简单的介绍一下。
2、实现动静资源分离
我们实现反向代理后,Nginx就像一个中转站,浏览器的所有请求都通过Nginx转到了tomcat 去处理了。那我们有没有什么办法减轻tomcat的负担呢。在Nginx上一篇博客中我们提到Nginx的另一个作用,就是作为Http服务器。而且浏览器的所有请求有动态(如jsp)和静态(html、jpg)资源两种,动态资源只能通过tomcat处理,但是静态资源可就不一定了,所以我们可以将所有静态资源直接交给Nginx处理,不再把静态请求转到tomcat了,这样就可以减轻了tomcat的负担。在这里Nginx 也有个Http服务器的作用。
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
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 /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
# 动态服务器组
upstream dynamic.qigaohua.com {
server 192.168.223.104:12345;
# server 192.168.223.105:12345; # 注释掉,这个只是假设情况。
}
# 静态服务器组
upstream static.qigaohua.com {
server 192.168.223.104:12346;
}
# 静态服务器
server {
listen 12346; # 监听端口,跟上面对应
server_name 192.168.223.104; # 有域名就写域名
charset utf8;
location / {
# 静态资源目录(这是我的)
root /opt/tomcat/apache-tomcat-8.5.34/webapps/blog/;
}
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://dynamic.qigaohua.com;
index index.html indde.jsp;
}
# 动态资源请求
location ~ .*\.(jsp|do|action)$ {
proxy_pass http://dynamic.qigaohua.com;
index index.jsp;
}
# 静态资源请求
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|ico|svg)$ {
proxy_pass http://static.qigaohua.com;
}
# 静态资源请求
location ~ .*\.(ttf|woff|woff2)$ {
proxy_pass http://static.qigaohua.com;
}
# 静态资源请求
location ~ .*\.(js|css)$ {
proxy_pass http://static.qigaohua.com;
}
# 其他请求
location ~ .*$ {
proxy_pass http://dynamic.qigaohua.com;
index index.jsp index.html;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
在nginx.conf文件中导入上面配置,就可以实现动静分离了。当我们访问某张图片时,就可以通过nginx直接返回了,不需要再把请求转给tomcat,tomcat再把结果转给nginx了。我们可以通过tomcat的日志去验证是否成功。(可以根据自己情况进行修改)
现在我们要考虑是不是上面那些配置就可以了呢,还要不要添加些其他的配置 ?? 可能对于我个人的实际情况,也不必要添加其他的了,应该是可以了。但是工作实际情况,那就不行了。
这里我们要考虑一下缓存的问题。既然我们已经动静分离了,那我们的静态资源难道每次都要从其他服务器去请求。那得多麻烦,而且消耗很多资源。对于我个人这个情况,所以服务都在一台服务器上,影响其实也不大,但是再工作项目中,服务器可能有几十台,分布在全国各地,那这样就不行了,我们必须在Nginx代理服务器上进行静态资源缓存。所以我们这里要添加缓存配置。
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes 1; # 设置值应和CPU核心数一样
# 格式: error_log ;
# level: debug|info|notice|warn|error|crit|alert|emerg
# 注意: 一般情况下不要配置info等级较低的级别,会带来大量的磁盘I/O消耗
error_log /var/log/nginx/error.log error;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
# 系统上最大的文件描述符的数量 值必须大于 worker_processes * worker_connections,这里即 1 * 1024;
worker_rlimit_nofile 65535;
events {
use epoll; # 使用epoll模式提高性能
worker_connections 1024; # 单个进程最大连接数
}
http {
# 定义记录日志的格式
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 /var/log/nginx/access.log main;
# 扩展名与文件类型映射表
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
client_header_buffer_size 32k; # 设置请求头缓冲区大小
large_client_header_buffers 4 32k; # 设置客户端请求头的缓冲区的最大数量和大小
client_max_body_size 8m; # 设置nginx能处理的最大请求主体大小
# 设置hash表最大值
# types_hash_max_size越大,就会消耗更多的内存,但散列key的冲突率会降低,检索速度就更快。
# types_hash_max_size越小,消耗的内存就越小,但散列key的冲突率可能上升。
types_hash_max_size 2048;
types_hash_bucket_size 128;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
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 on;
# 当返回内容大于此值时才会使用gzip进行压缩,以K为单位,当值为0时,所有页面都进行压缩
gzip_min_length 1k;
# 设置用于处理请求压缩的缓冲区数量和大小。
# 比如4 16K表示按照内存页(one memory page)大小以16K为单位(即一个系统中内存页为4K),
# 申请4倍的内存空间。建议此项不设置,使用默认值。
gzip_buffers 4 16k;
# 用于识别http协议的版本,早期的浏览器不支持gzip压缩,用户会看到乱码,
# 所以为了支持前期版本加了此选项。
# 默认在http/1.0的协议下不开启gzip压缩
gzip_http_version 1.0;
# 设置gzip压缩级别,级别越底压缩速度越快文件压缩比越小,反之速度越慢文件压缩比越大
gzip_comp_level 2;
# 设置需要压缩的MIME类型,如果不在设置类型范围内的请求不进行压缩
gzip_types text/plain application/x-javascript text/css application/xml;
# 增加响应头”Vary: Accept-Encoding”
gzip_vary on;
#配置代理参数
proxy_redirect off;
# 设置由后端服务器获取用户的主机名或者真实IP地址,以及代理者的真实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;
# client_max_body_size 10m;
# 用于指定客户端请求主体缓冲区的大小,可以理解为先保存到本地再传给用户
client_body_buffer_size 128k;
# 表示与后端服务器连接的超时时间,即发起握手等候相应的超时时间
proxy_connect_timeout 90;
# 表示后端服务器的数据回传时间,即在规定时间之内后端服务器必须先传完所有的数据,否则,Nginx将断开这个连接
proxy_send_timeout 90;
# 设置Nginx从代理的后端服务器获取信息的时间
proxy_read_timeout 90;
# 设置缓冲区的大小,默认,该缓冲区大小等于指令proxy_buffers设置的大小
proxy_buffer_size 16k;
# 设置缓冲区的数量和大小,nginx从代理的后端服务器获取的相应的信息,会放置到缓冲区
proxy_buffers 4 32k;
# 用于设置系统很忙时可以使用的proxy_buffers,大小,官方推荐的大小为proxy_buffers*2
proxy_busy_buffers_size 64k;
# 指定proxy缓存临时文件的大小,就是buffer不够存到本地硬盘上
proxy_temp_file_write_size 64k;
#缓存配置
proxy_cache_key '$host:$server_port$request_uri';
# proxy_temp_file_write_size 64k;
proxy_temp_path /tmp/proxy_temp_path;
# 缓存文件路径
# levels 设置缓存文件目录层次;levels=1:2 表示两级目录
# keys_zone 设置缓存名字和共享内存大小
# inactive 在指定时间内没人访问则被删除
# max_size 最大缓存空间,如果缓存空间满,默认覆盖掉缓存时间最长的资源。
proxy_cache_path /tmp/proxy_cache_path levels=1:2 keys_zone=cache_one:100m inactive=5d max_size=500m;
proxy_ignore_headers X-Accel-Expires Expires Cache-Control Set-Cookie;
# 动态服务器组
upstream dynamic.qigaohua.com {
server 192.168.223.104:12345;
# server 192.168.223.105:12345; # 注释掉,这个只是假设情况。
}
# 静态服务器组
upstream static.qigaohua.com {
server 192.168.223.104:12346;
}
server {
listen 12346; # 监听端口,跟上面对应
server_name 192.168.223.104; # 有域名就写域名
charset utf8;
location / {
# 静态资源目录(这是我的)
root /opt/tomcat/apache-tomcat-8.5.34/webapps/blog/;
}
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://dynamic.qigaohua.com;
index index.html indde.jsp;
}
# 动态资源请求
location ~ .*\.(jsp|do|action)$ {
proxy_pass http://dynamic.qigaohua.com;
index index.jsp;
}
# 静态资源请求
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|ico|svg)$ {
proxy_pass http://static.qigaohua.com;
expires 7d; # 缓存7天
proxy_cache cache_one;
proxy_cache_valid 200 304 302 5d;
proxy_cache_valid any 5d;
proxy_cache_key '$host:$server_port$request_uri';
add_header X-Cache '$upstream_cache_status from $host';
}
# 静态资源请求
location ~ .*\.(ttf|woff|woff2)$ {
#缓存7天
expires 7d;
proxy_pass http://static.qigaohua.com;
proxy_cache cache_one;
proxy_cache_valid 200 304 302 5d;
proxy_cache_valid any 5d;
proxy_cache_key '$host:$server_port$request_uri';
add_header X-Cache '$upstream_cache_status from $host';
}
# 静态资源请求
location ~ .*\.(js|css)$ {
proxy_pass http://static.qigaohua.com;
expires 7d;
proxy_cache cache_one;
proxy_cache_valid 200 304 302 5d;
proxy_cache_valid any 5d;
proxy_cache_key '$host:$server_port$request_uri';
add_header X-Cache '$upstream_cache_status from $host';
}
# 其他请求
location ~ .*$ {
proxy_pass http://dynamic.qigaohua.com;
index index.jsp index.html;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
在其中我还添加了其他的一些配置,都加了注释。
上面都是在本地机上进行的配置,下面是我在云服务器上的配置,带有域名( 因为域名没备案,所以不能用默认端口,http使用端口3680)
云服务器上的 Nginx 配置:
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user root root;
worker_processes 1; # 设置值应和CPU核心数一样
# 格式: error_log ;
# level: debug|info|notice|warn|error|crit|alert|emerg
# 注意: 一般情况下不要配置info等级较低的级别,会带来大量的磁盘I/O消耗
error_log /var/log/nginx/error.log error;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
# 系统上最大的文件描述符的数量 值必须大于 worker_processes * worker_connections,这里即 1 * 1024;
worker_rlimit_nofile 65535;
events {
use epoll; # 使用epoll模式提高性能
worker_connections 1024; # 单个进程最大连接数
}
http {
# 定义记录日志的格式
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 /var/log/nginx/access.log main;
# 扩展名与文件类型映射表
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
client_header_buffer_size 32k; # 设置请求头缓冲区大小
large_client_header_buffers 4 32k; # 设置客户端请求头的缓冲区的最大数量和大小
client_max_body_size 8m; # 设置nginx能处理的最大请求主体大小
# 设置hash表最大值
# types_hash_max_size越大,就会消耗更多的内存,但散列key的冲突率会降低,检索速度就更快。
# types_hash_max_size越小,消耗的内存就越小,但散列key的冲突率可能上升。
types_hash_max_size 2048;
types_hash_bucket_size 128;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
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 on;
# 当返回内容大于此值时才会使用gzip进行压缩,以K为单位,当值为0时,所有页面都进行压缩
gzip_min_length 1k;
# 设置用于处理请求压缩的缓冲区数量和大小。
# 比如4 16K表示按照内存页(one memory page)大小以16K为单位(即一个系统中内存页为4K),申请4倍的内存空间。建议此项不设置,使用默认值。
gzip_buffers 4 16k;
# 用于识别http协议的版本,早期的浏览器不支持gzip压缩,用户会看到乱码,所以为了支持前期版本加了此选项。
# 默认在http/1.0的协议下不开启gzip压缩
gzip_http_version 1.0;
# 设置gzip压缩级别,级别越底压缩速度越快文件压缩比越小,反之速度越慢文件压缩比越大
gzip_comp_level 2;
# 设置需要压缩的MIME类型,如果不在设置类型范围内的请求不进行压缩
gzip_types text/plain application/x-javascript text/css application/xml;
# 增加响应头”Vary: Accept-Encoding”
gzip_vary on;
#配置代理参数
proxy_redirect off;
# 设置由后端服务器获取用户的主机名或者真实IP地址,以及代理者的真实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;
# client_max_body_size 10m;
# 用于指定客户端请求主体缓冲区的大小,可以理解为先保存到本地再传给用户
client_body_buffer_size 128k;
# 表示与后端服务器连接的超时时间,即发起握手等候相应的超时时间
proxy_connect_timeout 90;
# 表示后端服务器的数据回传时间,即在规定时间之内后端服务器必须先传完所有的数据,否则,Nginx将断开这个连接
proxy_send_timeout 90;
# 设置Nginx从代理的后端服务器获取信息的时间
proxy_read_timeout 90;
# 设置缓冲区的大小,默认,该缓冲区大小等于指令proxy_buffers设置的大小
proxy_buffer_size 16k;
# 设置缓冲区的数量和大小,nginx从代理的后端服务器获取的相应的信息,会放置到缓冲区
proxy_buffers 4 32k;
# 用于设置系统很忙时可以使用的proxy_buffers,大小,官方推荐的大小为proxy_buffers*2
proxy_busy_buffers_size 64k;
# 指定proxy缓存临时文件的大小,就是buffer不够存到本地硬盘上
proxy_temp_file_write_size 64k;
#缓存配置
proxy_cache_key '$host:$server_port$request_uri';
# proxy_temp_file_write_size 64k;
proxy_temp_path /tmp/proxy_temp_path;
# 缓存文件路径
# levels 设置缓存文件目录层次;levels=1:2 表示两级目录
# keys_zone 设置缓存名字和共享内存大小
# inactive 在指定时间内没人访问则被删除
# max_size 最大缓存空间,如果缓存空间满,默认覆盖掉缓存时间最长的资源。
proxy_cache_path /tmp/proxy_cache_path levels=1:2 keys_zone=cache_one:100m inactive=1d max_size=500m;
proxy_ignore_headers X-Accel-Expires Expires Cache-Control Set-Cookie;
# 动态资源服务器组
upstream dynamic.qigaohua.com {
server localhost:12345;
}
# 静态资源服务器组
upstream static.qigaohua.com {
server localhost:12346;
}
# 静态资源主机
server {
listen 12346;
server_name www.flighting.top;
charset utf8;
location / {
root /opt/tomcat/apache-tomcat-8.5.34/webapps/blog/;
}
}
server {
listen 3690 ;
# listen [::]:3690;
server_name www.flighting.top;
# root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://dynamic.qigaohua.com;
index index.html index.jsp;
}
location ~ .*\.(jsp|do|action)$ {
proxy_pass http://dynamic.qigaohua.com;
index index.jsp;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|ico|svg)$ {
proxy_pass http://static.qigaohua.com;
expires 7d; # 缓存7天
proxy_cache cache_one;
proxy_cache_valid 200 304 302 5d;
proxy_cache_valid any 5d;
proxy_cache_key '$host:$server_port$request_uri';
add_header X-Cache '$upstream_cache_status from $host';
}
location ~ .*\.(ttf|woff|woff2)$ {
#缓存7天
expires 7d;
proxy_pass http://static.qigaohua.com;
proxy_cache cache_one;
proxy_cache_valid 200 304 302 5d;
proxy_cache_valid any 5d;
proxy_cache_key '$host:$server_port$request_uri';
add_header X-Cache '$upstream_cache_status from $host';
}
location ~ .*\.(js|css)$ {
proxy_pass http://static.qigaohua.com;
expires 7d;
proxy_cache cache_one;
proxy_cache_valid 200 304 302 5d;
proxy_cache_valid any 5d;
proxy_cache_key '$host:$server_port$request_uri';
add_header X-Cache '$upstream_cache_status from $host';
}
location ~ .*$ {
proxy_pass http://dynamic.qigaohua.com;
index index.jsp index.html;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
云服务器的配置没多少改变,主要是ip换成你的域名,还有就是如果你的域名没有备案,那么就需要修改的一下默认端口。
配置完成后,当然是使用测试下。在测试中我发现了一个bug,就是访问端口变化了,导致无法访问。如果你使用的是默认端口,则不会出现这样的bug。
我在网上找到了一篇分析该错误的详解,基本上可以完全弄清楚其中的原因所在,下面的是部分原话:(地址:https://blog.csdn.net/cymm_liu/article/details/49680119)
出现的问题就是当访问http://host:81/app1/Login.do的时候,登录成功需要301跳转到用户中心页面,然后跳转的地址本应该是http://host:81/app1/userindex.do,但是结果不太尽如人意,浏览器实际出现的地址http://host/app1/userindex.do。这里面的问题就是81端口没了,跑80端口去了,自然就404了。扯了一大段,这就是今天想说的问题。
首先我打开chrome,然后来分析这次request发生了什么(打开开发者工具中的Network面板),能发现的基本就是请求Login.do是没问题的,但是Login.do之后发生的301重定向是错误的,一个重要的线索就是Login.do的请求中response中的Location的值是http://host/usercenter.do,这里丢掉了端口号。这个地方的具体原因后边会提到,先说下解决思路。
解决思路1: 利用nginx的proxy_redirect
这个思路其实有点偏重解决问题型,就是我看到这里错了,原因不纠结,我让你好使就可以了。可能好多人都是这个思路,毕竟解决问题是首要目的。
很多人在配置nginx的时候,习惯参考官方wiki的Full Example (taken from Nginx site),来做一些配置,参考这个肯定比参考baidu搜索出来的文档要靠谱很多,建议不了解每个属性的可以来参照下这个官方示例。这个配置里面proxy_redirect的属性为off,很多人应该没有问过为什么就直接根据人家来做了,之所以这样下结论是因为我看到太多国内人的集成例子中都是这样设置的了。我这里也是这样设置的,以前也倒是没想起来问下为啥,的确不太符合我的风格。反正服务器是这样配置的,现在是出来问题了,我们先来看下这个属性能做什么。
首先看官方文档Reference:proxy_redirect的说明:
Sets a text that should be changed in the header fields “Location” and “Refresh” of a response from the proxied server. Suppose a proxied server returned the header field “Location: http://localhost:8000/two/some/uri/”.
基本意思就是修改代理服务器(也就是此时的nginx)的response的头信息里面的Location和Refresh的值,按照这个解释的话我们的问题肯定就迎刃而解了,因为现在遇到的问题就是这个能够修改的两个中的一个Location出了问题,那么下面的代码就可以解决问题
proxy_redirect http://host http://host:81;
这样重启sudo nginx -s reload然后再访问应该就ok了。其实你google搜索nginx proxy_redirect 重定向有好多这样的例子和这个解决方式是一样的,就不细说了,如果有人想了解的可以自己参照nginx官方文档和结合例子来操作下试试就可以理解了。
解决思路2:找到问题原因,修改出错的地方解决
根据上个思路解决了问题以后,一点都没如释重负的感觉,反而各个地方都觉得很空的感觉,因为有好几个疑问没解决,其中包括为啥是80而不是81或者8080没道理?这个Location是不是应该nginx来重写,修改掉那个跳转错的地方是不是比这个思路会更好?
那就先来分析下问题的原因:既然response的Locaiton不对,那么首先想到的就是这个Location是谁构造出来的,了解HTTP协议的人应该都知道,request中的header都是client(浏览器等)构造好发送给服务器的,服务器收到请求以后构造response信息返回给client。那么这样Location这个值肯定就是nginx或者Tomcat给搞出的问题了,这个地方nginx只是一个proxy server,那么response肯定是Tomcat发给nginx的,也就是说我们应该从Tomcat下手来分析这个问题。
首先我就看了下Tomcat的官方文档 Proxy Support,这里面对这个介绍如下:
The proxyName and proxyPort attributes can be used when Tomcat is run behind a proxy server. These attributes modify the values returned to web applications that call the request.getServerName() and request.getServerPort() methods, which are often used to construct absolute URLs for redirects. Without configuring these attributes, the values returned would reflect the server name and port on which the connection from the proxy server was received, rather than the server name and port to whom the client directed the original request.
意思就是proxyPort的属性就是用来我这种nginx做前端代理服务器Tomcat在后端处理动态请求的情况的。修改属性的值可以作用于应用的两个方法,主要用于绝对路径和重定向之用。如果不配置的话,可能会不对头。那么既然是这里不对头,我就先把server.xml中我这个http的connector的配置加入了proxyPort="81",重启Tomcat,然后把nginx上步骤的修改注释掉,重启测试。结果基本如所料,完全正常跳转了。
事情到了这个时候,其实问题基本明了了,不过我还是对这个Tomcat为啥默认解析了80端口很是疑惑。我下载了Tomcat的source来看下问题究竟,看了以后用通俗的语言来表述的话就是这样:如果默认不配置proxyPort默认为0,然后在构造response的时候判断如果proxyPort为0那么就不添加端口,不添加端口当然就默认走了80端口,源代码如下:
// FIXME: the code below doesnt belongs to here,
// this is only have sense
// in Http11, not in ajp13..
// At this point the Host header has been processed.
// Override if the proxyPort/proxyHost are set
String proxyName = connector.getProxyName();
int proxyPort = connector.getProxyPort();
if (proxyPort != 0) {
req.setServerPort(proxyPort);
}
if (proxyName != null) {
req.serverName().setString(proxyName);
截取这些差不多就可以了,这个问题跟我的问题基本是一样的。最后通过方案2解决了我的问题。
五、结束
nginx + Tomcat我的配置基本就这样了,下一章就是怎么使用https代替http。