继承上文:
Nginx location 配置 - Part 2
之前 介绍了 nginx 配置web服务器, 但是用nginx 多的情况下是作为反向代理。
本问就是介绍如何利用nginx 配置反向代理服务。
什么是 反向代理 和 正向代理
一张图很清楚地表达了
正向代理
所谓正向代理就是 代理 client的(网络请求发起方)
它有这些特点
- 角色类似家用路由器
- 与clients在同1个局域网
- 作用是为了让Lan内其他主机 能够访问外部网络
反向代理
所谓反向代理就是 代理 server的
它有这些特点
- 角色类似api gateway
- 与server在同1个局域网
- 作用是为了让Lan内其他主机 能够被外部网络访问, 而且防止被外部网络直接访问
两个例子和具体需求
第一个例子是代理tomcat 主页, 这个是最常用的
proxy host | proxy port | proxy domain | tomcat host | tomcat port |
---|---|---|---|---|
tf-vpc0-subnet0-main-server | 80 | jp-gcp-vms.cloud | tf-vpc0-subnet1-vm1 | 8080 |
第二例子是代理could run的某个api
proxy host | proxy port | proxy domain | Cloud run service name |
---|---|---|---|
tf-vpc0-subnet0-main-server | 8083 | jp-gcp-vms.cloud | helloservice-7hq3m4pdya-nw.a.run.app |
注意cloud run的service name并不是真正背后的主机名, 其真正的host/ip (好像是ipv6)是对我们隐藏的, 也无法知道具体端口
第三个例子 是代理内网中的1个mysql 服务, 但是可惜nginx 只是 http 代理, 并不能处理mysql 的协议,只能用proxySQL等代替。没有第3个。。
代理tomcat 主页
这个相对简单
我们要在/etc/nginx/conf.d/ 下创建1个新的配置文件
upstream appserver {server tf-vpc0-subnet1-vm1:8080;
}server {listen 80;server_name jp-gcp-vms.cloud www.jp-gcp-vms.cloud;location / {proxy_pass http://appserver/;#loginaccess_log /var/log/nginx/proxytomcat.access.log;error_log /var/log/nginx/proxytomcat.error.log;}}
注意这里我们用upstream block 先定义了 tomcat 真正的服务器地址和host
然后在 server{} block 中并不需要想定义网站那样 提供1个 root 路径
直接用 proxy_pass 指向真正的后台服务地址就可以了。
测试效果
http://jp-gcp-vms.cloud/
由于代理用的是80端口, 浏览器也不再需要写端口地址了。
有个坑, 在配置文件中尽量避免写下划线_ 否则有可能出现下面的问题
代理cloud run service
同样地, 在/etc/nginx/conf.d/ 下再创建1个文件
# upstream helloservice {# server helloservice-7hq3m4pdya-nw.a.run.app; # not for cloudrun , upstream server could only point to the actual server host
# }server {listen 8083;server_name jp-gcp-vms.cloud www.jp-gcp-vms.cloud;#ssl_certificate /root/ssl/ssl_certificate.crt;#ssl_certificate_key /root/ssl/ssl_certificate.key;location /api/ {# proxy_pass https://helloservice/api/; # not for cloudrun , upstream server could only point to the actual server hostproxy_pass https://helloservice-7hq3m4pdya-nw.a.run.app/api/; proxy_pass_header Authorization;# proxy_set_header Authorization "Bearer $ID_TOKEN"; # Ngnix do not support read env variables by default# We might need to use envsubst to add env-value in nginx.conf before nginx service start# , but it's not dynamic enough# proxy_set_header Authorization "Bearer $(gcloud auth print-identity-token)"; # do not support this as well.. might need lua plugin# loginaccess_log /var/log/nginx/helloservice.ssl.access.log;error_log /var/log/nginx/helloservice.ssl.error.log;}
}
有几个坑
- 由于cloud run serice name 并不是1个真正的host, 所以我们无法使用upstream block 预定义。
- 这里的例子只代理了 这个service /api/ 下的api
- Authorization 这个header 要显式 pass
- 本人还没找到 能在 nginx 生成 google Identity token的方法, 见注释
测试结果
gateman@DESKTOP-UIU9RFJ:~$ curl -k -H "Authorization: Bearer $(gcloud auth print-identity-token)" http://jp-gcp-vms.cloud:8083/api/hello
Hello, Jason!!!!
gateman@DESKTOP-UIU9RFJ:~$