最近在做项目时公司有个需求,需要从外网访问内网,这不就是典型的反向代理么,然后就想到了nginx,一款很优秀的高性能应用代理软件,你值得学习和拥有。
nginx的安装和部署这里就不介绍了,网上大把的例子。然后我也是按照网上的例子安装和部署的,然后部署成功了,访问首页也没问题。并且大家都知道http默认端口是80,我在nginx服务器上使用80端口的时候也没问题,从首页点击进入其他页面跳转都没问题(因为nginx在设置代理地址的时候没有设置端口,所以默认就是80端口了),这是在测试环境。
然而当我在生产部署nginx服务的时候,发现80端口已经被占用了,无法再使用80端口来给我们的nginx代理使用,所以不得不换成其他的端口,比如:8002,然后我就换成了8002端口,然后就配置了,具体配置如下:
nginx.conf配置:
#user www www;
worker_processes 4;
worker_cpu_affinity 00000001 00000010 00000100 00001000;
#pid /tpsys/nginx/nginx/logs/nginx.pid
worker_rlimit_nofile 102400;
events
{
use epoll;
worker_connections 102400;
}
http
{
include mime.types;
default_type application/octet-stream;
fastcgi_intercept_errors on;
charset utf-8;
server_names_hash_bucket_size 128;
client_header_buffer_size 4k;
large_client_header_buffers 4 32k;
client_max_body_size 300m;
sendfile on;
tcp_nopush on;
keepalive_timeout 60;
tcp_nodelay on;
client_body_buffer_size 512k;
proxy_connect_timeout 5;
proxy_read_timeout 60;
proxy_send_timeout 5;
proxy_buffer_size 16k;
proxy_buffers 4 64k;
proxy_busy_buffers_size 128k;
proxy_temp_file_write_size 128k;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 2;
gzip_types text/plain application/x-javascript text/css application/xml;
gzip_vary on;
log_format main ' $remote_addr - $host - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $request_time';
#upstream web1 {
# server 127.0.0.1:8080 weight=1 max_fails=2 fail_timeout=30s;
# server 127.0.0.1:8081 weight=1 max_fails=2 fail_timeout=30s;
#}
#upstream web2 {
# server 127.0.0.1:8090 weight=1 max_fails=2 fail_timeout=30s;
# server 127.0.0.1:8091 weight=1 max_fails=2 fail_timeout=30s;
#}
include vhosts.conf;
}
vhost.conf配置:
server {
listen 8002;
server_name localhost;
#rewrite ^/(.*)$ http://192.168.81.135:8002/$1 permanent;
index index.jsp index.html index.htm;
root / ;
location /
{
proxy_next_upstream http_502 http_504 error timeout invalid_header;
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://192.168.136.1:8080;
}
# location ~ .*\.(php|jsp|cgi|shtml)?$
# {
# 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://jvm_web2;
# }
location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css)$
{
root /servletClient;
expires 30d;
}
access_log /tpsys/nginx/nginx/logs/access.log main;
error_log /tpsys/nginx/nginx/logs/error.log crit;
}
为了方便查看和理解,我的nginx.conf拆分成了以上两个,分别为:nginx.conf和vhost.conf。
然后在做了以上配置后访问nginx服务首页时没问题,可以正常访问,页面如下:
然后点击“登录”按钮,结果如下:
大家可以很清楚的看到原来的端口发生了变化,8002端口不见了,然而网页也访问不了了,是不是很奇怪呢?
我只是做了一个小小的测试,我的servlet的代码如下:
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String userName = req.getParameter("userName");
// base64编码处理
System.out.println("得到的用户名为:" + userName);
resp.setContentType("text/html;charset=utf-8");
// 重定向
resp.sendRedirect("/servletClient/index.jsp");
// 转发
// ServletContext sc = getServletContext();
// RequestDispatcher rd = null;
// req.setAttribute("userName", userName);
// rd = sc.getRequestDispatcher("/index.jsp");
// rd.forward(req, resp);
}
以上为重定向测试!
然而当我把重定向的代码注释掉,改用转发的方式,结果还会是这样么?我们会发现结果如下:
第一个页面是一样的,就不重复贴图了。
我们会发现转发的时候无问题,而重定向的时候问题很大,页面都显示不出来了,报404。
然后我们就会想,难道nginx不支持重定向吗?答案当然不是。
关键是要找到问题的症结在哪里,你想想是在页面进行跳转的时候地址栏发生了变化,那么肯定是nginx在重定向的时候出了问题,那么问题出在哪里呢?
我们找到nginx.conf最核心的配置server{},我这里是vhost.conf,如下:
然后会发现代理设置在location里面设置的,然后看到有一段是:proxy_set_header Host $host;
了解nginx的同学应该都知道$host指的是当前主机的ip地址,这个我在日志中也有打印,大家可以注意看下。
然后发现这个$host后面没有端口,那这是什么意思呢?因为使用了http的默认端口80,所以不加也不会报错(原则是你外网请求的端口也必须是80才行),
但当你请求的端口不是80时,那么问题就来了。比如你请求的是8002,那么经过这个配置一设置,那么你的端口是不是就变成80了,而我们在浏览器中看不到:80是因为浏览器将其做了隐藏。
所以要想进行正确的请求就必须修改这个配置,将上面那段修改成proxy_set_header Host $host:8002;,如下:
以上端口根据你的实际情况而定。
然后你再试下会发现问题解决。
总结:
1.你肯定会问为什么转发没问题,而重定向就会有问题了呢?
答:这是转发和重定向的性质决定的,因为转发是一次请求,由服务端进行的处理。而重定向是客户端进行的处理,相当于发起了两次请求,所以第二次请求的时候url就发生了变化。
2.在proxy_set_header Host $host;后面加上端口号会不会对转发请求造成影响?
答:不会,自己也可以多测试。
最后附上一篇重定向和转发的区别的文章:https://blog.csdn.net/meiyalei/article/details/2129120。