Hello World

吞风吻雨葬落日 欺山赶海踏雪径

0%

DubboAdmin 注册nacos 失败问题

公司的使用的dubbo没有配置dubbo admin,调试不方便。准备本地搭建一个,但是nacos一直连接不上。

dubbo admin的注册中心配置的连接地址是:

1
admin.registry.address=nacos://xxx.com:80?group=DEFAULT_GROUP&namespace=public

用的是80端口,做了集群的负载均衡,80端口映射成了8848端口。通过debug源码发现,
com.alibaba.nacos.common.remote.client.grpc.GrpcClient#connectToServer是在使用grpc连接nacos。具体分析的如下:

首先dubbo-admin中的 DubboConfigApplicationListener 实现了 ApplicationListener 接口,在 onApplicationEvent 方法中初始化了dubbo的配置Bean

1
2
3
4
5
6
7
8
9
10
@Override
public void onApplicationEvent(DubboConfigInitEvent event) {
if (nullSafeEquals(applicationContext, event.getSource())) {
// It's expected to be notified at org.springframework.context.support.AbstractApplicationContext.registerListeners(),
// before loading non-lazy singleton beans. At this moment, all BeanFactoryPostProcessor have been processed,
if (initialized.compareAndSet(false, true)) {
initDubboConfigBeans();
}
}
}

后续调用到了
org.apache.dubbo.config.deploy.DefaultApplicationDeployer#initialize 方法进行初始化。

其中核心在startConfigCenter(); 方法中,后续一系列调用在createDynamicConfiguration方法中创建了 NacosDynamicConfiguration
NacosDynamicConfiguration 的构造函数中,调用了 buildConfigService 方法。

1
2
3
4
5
6
NacosDynamicConfiguration(URL url, ApplicationModel applicationModel) {
this.nacosProperties = buildNacosProperties(url);
this.configService = buildConfigService(url);
this.watchListenerMap = new ConcurrentHashMap<>();
this.applicationModel = applicationModel;
}

buildConfigService 中来获取服务状态。

1
String serverStatus = tmpConfigServices.getServerStatus();

最终在
com.alibaba.nacos.client.config.impl.ClientWorker.ConfigRpcTransportClient#ensureRpcClient中初始化了 rpcClient
而初始化的代码是在ScheduledExecutorService clientEventExecutor 中独立开线程实现的。
我们可以直接看
this.reconnect(reconnectContext.serverInfo, reconnectContext.onRequestFail); 方法的实现。
这就回到了我们最初提到的
com.alibaba.nacos.common.remote.client.grpc.GrpcClient#connectToServer 方法,在这里初始化了端口 port

1
int port = serverInfo.getServerPort() + this.rpcPortOffset();

这里的端口是设置的服务端口增加了固定的偏移量。 serverInfo.getServerPort() 设置的是80, 而this.rpcPortOffset()默认是 1000 (SDK_GRPC_PORT_DEFAULT_OFFSET)。
随后调用Response response = this.serverCheck(serverInfo.getServerIp(), port, newChannelStubTemp);连接 nacos。

所以问题就清晰了,nacos 中的grpc端口其实是配置的端口加了一定的偏移量,而做了负载均衡的 nacos 只转发了http的端口(80->8848),而缺少了(1080->9848)的逻辑,所以导致grpc连接不上。


调用栈:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
connectToServer:330, GrpcClient (com.alibaba.nacos.common.remote.client.grpc)
reconnect:506, RpcClient (com.alibaba.nacos.common.remote.client)
lambda$start$2:344, RpcClient (com.alibaba.nacos.common.remote.client)
run:-1, RpcClient$$Lambda$803/0x0000007801505b28 (com.alibaba.nacos.common.remote.client)
call:539, Executors$RunnableAdapter (java.util.concurrent)
run$$$capture:264, FutureTask (java.util.concurrent)
run:-1, FutureTask (java.util.concurrent)
- Async stack trace
<init>:151, FutureTask (java.util.concurrent)
<init>:215, ScheduledThreadPoolExecutor$ScheduledFutureTask (java.util.concurrent)
schedule:561, ScheduledThreadPoolExecutor (java.util.concurrent)
submit:715, ScheduledThreadPoolExecutor (java.util.concurrent)
start:281, RpcClient (com.alibaba.nacos.common.remote.client)
ensureRpcClient:1000, ClientWorker$ConfigRpcTransportClient (com.alibaba.nacos.client.config.impl)
getOneRunningClient:1147, ClientWorker$ConfigRpcTransportClient (com.alibaba.nacos.client.config.impl)
isHealthServer:1193, ClientWorker$ConfigRpcTransportClient (com.alibaba.nacos.client.config.impl)
isHealthServer:568, ClientWorker (com.alibaba.nacos.client.config.impl)
getServerStatus:244, NacosConfigService (com.alibaba.nacos.client.config)
buildConfigService:111, NacosDynamicConfiguration (org.apache.dubbo.configcenter.support.nacos)
<init>:98, NacosDynamicConfiguration (org.apache.dubbo.configcenter.support.nacos)
createDynamicConfiguration:46, NacosDynamicConfigurationFactory (org.apache.dubbo.configcenter.support.nacos)
lambda$getDynamicConfiguration$0:39, AbstractDynamicConfigurationFactory (org.apache.dubbo.common.config.configcenter)
computeIfAbsent:1708, ConcurrentHashMap (java.util.concurrent)
computeIfAbsent:58, ConcurrentHashMapUtils (org.apache.dubbo.common.utils)
getDynamicConfiguration:39, AbstractDynamicConfigurationFactory (org.apache.dubbo.common.config.configcenter)
getDynamicConfiguration:886, DefaultApplicationDeployer (org.apache.dubbo.config.deploy)
prepareEnvironment:825, DefaultApplicationDeployer (org.apache.dubbo.config.deploy)
startConfigCenter:297, DefaultApplicationDeployer (org.apache.dubbo.config.deploy)
initialize:217, DefaultApplicationDeployer (org.apache.dubbo.config.deploy)
prepare:570, DefaultModuleDeployer (org.apache.dubbo.config.deploy)
initDubboConfigBeans:73, DubboConfigApplicationListener (org.apache.dubbo.config.spring.context)
onApplicationEvent:59, DubboConfigApplicationListener (org.apache.dubbo.config.spring.context)
onApplicationEvent:37, DubboConfigApplicationListener (org.apache.dubbo.config.spring.context)
doInvokeListener:172, SimpleApplicationEventMulticaster (org.springframework.context.event)
invokeListener:165, SimpleApplicationEventMulticaster (org.springframework.context.event)
multicastEvent:139, SimpleApplicationEventMulticaster (org.springframework.context.event)
multicastEvent:127, SimpleApplicationEventMulticaster (org.springframework.context.event)
registerListeners:842, AbstractApplicationContext (org.springframework.context.support)
refresh:548, AbstractApplicationContext (org.springframework.context.support)
refresh:143, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
refresh:755, SpringApplication (org.springframework.boot)
refresh:747, SpringApplication (org.springframework.boot)
refreshContext:402, SpringApplication (org.springframework.boot)
run:312, SpringApplication (org.springframework.boot)
run:1247, SpringApplication (org.springframework.boot)
run:1236, SpringApplication (org.springframework.boot)
main:34, DubboAdminApplication (org.apache.dubbo.admin)