一、发现问题
应用启动时,增加Nacos服务端的配置信息。
应用使用IP加端口连接Nacos服务器时,运行一切正常:
#启动参数增加以下Nacos参数
-Dspring.cloud.nacos.discovery.namespace=DEV
-Dspring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
但是将server-addr换成解析好的域名就有问题:
#Nacos默认的服务端端口为8848,因而Nacos服务端的端口必须配置,
#否则建立TCP连接的时候会使用9848及9849这两个端口
#可以通过下面指定port的参数配置,也可以在server-addr的域名中增加上端口进行指定。
#启动参数增加以下Nacos参数
-Dspring.cloud.nacos.discovery.namespace=DEV
-Dspring.cloud.nacos.discovery.server-addr=nacos-dev.xxx.com
-Dnacos.server.port=80
#或者
#启动参数增加以下Nacos参数
-Dspring.cloud.nacos.discovery.namespace=DEV
-Dspring.cloud.nacos.discovery.server-addr=nacos-dev.xxx.com:80
Nacos TCP端口的处理代码:
(代码中应该可以增加一个没有端口配置时,默认为80端口的逻辑,后续我来提个PR)。
确认Nginx中域名解析配置是正确的,因为可以通过域名正常访问控制台,但是应用启动的时候报“Client not connected,current status:STARTING”错误:
该错误表示Nacos应用客户端与Nacos服务端没有建立TCP连接(一次都没有),是客户端报出来的错误,该请求还没有发送到服务端。错误原因为Nginx中没有开启对9848及9849的TCP代理,于是在Nginx中开启TCP代理。
二、错误配置TCP端口的转发
刚开始使用了错误的操作方式,即在Nginx的http反射代理服务中以http2的方式对开启TCP端口,如下所示:
upstream nacos-server{
server 192.168.12.50:8848 weight=1;
}
upstream nacos-server-grpc-9848{
server 192.168.12.50:9848 weight=1;
}
upstream nacos-server-grpc-9849{
server 192.168.12.50:9849 weight=1;
}
# http代理
server {
listen 80;
server_name nacos-dev.xxx.com;
access_log /data/nginxlog/access-nacos.imlaidian.com.log main;
error_log /data/nginxlog/error-nacos.imlaidian.com.log;
location / {
#反向代理的地址
proxy_pass http://nacos-server;
proxy_set_header Host $host;
proxy_set_header X-Real-Ip $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
# grpc 代理配置 9848
server {
#80端口加1000
listen 1080 http2; # grpc方式对外暴露端口
location / {
grpc_pass grpc://nacos-server-grpc-9848; # 此处配置grpc服务的ip和端口
}
}
# grpc 代理配置 9849
server {
#80端口加1001
listen 1081 http2; # grpc方式对外暴露端口
location / {
grpc_pass grpc://nacos-server-grpc-9849; # 此处配置grpc服务的ip和端口
}
}
这种方式暴露端口,应用在启动时客户端与服务端会成功建立一次或多次连接,但是在超时以后会被Nginx自动断开,应用启动时此时就会报如下错误:
这个错误是服务端报回来的错误,调试客户端RpcClient.request(Request, long)代码:
获取到服务端响应内容为如下:
metadata {
type: "ErrorResponse"
}
body {
value: "{\"resultCode\":500,\"errorCode\":301,\"message\":\"Connection is unregistered.\",\"success\":false}"
}
查看服务端的代码GrpcRequestAcceptor.request(Payload, StreamObserver<Payload>),其中返回错误内容“Connection is unregistered.”的代码块如下:
出现这个错误是原因是因为客户端往服务端发起请求时,服务端根据客户端传上来的connectionId在connectionManager中找不到对应的客户端连接,就报了这个错误(因为建立的连接被Nginx断开了,连接在服务端已经被删除,自然就找不到了)。
三、正确配置TCP端口转发
Nginx对TCP的代理支持,是从v1.9开始的,支持的模块为stream,在编译nginx的时候需要增加stream模块相关的参数,因为默认编译是不包括stream模块:
#编译时增加以下参数
--with-stream
编译并安装好后,在nginx的配置目录/etc/nginx中增加tcp.d目录,并在nginx.conf中增加tcp.d目录中stream配置的加载:
stream {
log_format proxy '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time "$upstream_addr" '
'"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
access_log /var/log/nginx/access-stream.log proxy;
error_log /var/log/nginx/error-stream.log;
open_log_file_cache off;
# tcp层转发的配置文件夹
include /etc/nginx/tcp.d/*.conf;
然后在tcp.d中新建包括Nacos TCP转发的配置,如nacos.conf:
upstream erp-nacos-grpc{
hash $remote_addr consistent;
server 192.168.12.50:9848 weight=1;
}
upstream erp-nacos-grpc9{
hash $remote_addr consistent;
server 192.168.12.50:9849 weight=1;
}
# grpc 代理配置
server {
listen 1080; # grpc方式对外暴露端口
proxy_connect_timeout 10s;
proxy_timeout 10s;
proxy_pass erp-nacos-grpc;
}
# grpc 代理配置
server {
listen 1081; # grpc方式对外暴露端口
proxy_connect_timeout 10s;
proxy_timeout 10s;
proxy_pass erp-nacos-grpc9;
}
Nginx中原来关于域名的80端口配置,可以继续用