Closed JimmyDaddy closed 5 years ago
服务端代码用的是官方的 demo,然后将 registry 配置成 zookeeper
https://github.com/apache/incubator-dubbo/tree/master/dubbo-demo/dubbo-demo-provider
'use strict';
const { RpcClient } = require('sofa-node-rpc').client;
const { ZookeeperRegistry } = require('sofa-node-rpc').registry;
const protocol = require('dubbo-remoting');
const logger = console;
const registry = new ZookeeperRegistry({
logger,
address: '127.0.0.1:2181/dubbo/', // 注意:这里需要以 /dubbo/ 结尾
});
async function invoke() {
const client = new RpcClient({
logger,
registry,
protocol,
group: 'dubbo', // 这个根据实际情况填
version: null, // 这个根据实际情况填
});
const consumer = client.createConsumer({
interfaceName: 'org.apache.dubbo.demo.DemoService',
});
await consumer.ready();
const result = await consumer.invoke('sayHello', [{
$class: 'java.lang.String',
$: 'zongyu',
}], { responseTimeout: 3000 });
console.log(result);
}
invoke().catch(console.error);
我按照 demo 试了一下,注册中心连接成功了,但是 group 的设置貌似依然不对 这里是我的代码:
'use strict'
const { RpcClient } = require('sofa-rpc-node').client
const { ZookeeperRegistry } = require('sofa-rpc-node').registry
const { RpcServer } = require('sofa-rpc-node').server
const protocol = require('dubbo-remoting')
const logger = console
const registry = new ZookeeperRegistry({
logger,
address: '127.0.0.1:2181/dubbo/'
})
async function call() {
const client = new RpcClient({
logger: app.logger,
protocol,
registry,
group: 'HSF'
})
const consumer = client.createConsumer({
interfaceName: 'com.demo.provider.UserBaseQueryProvider',
version: '1.0.0.dev' //指定版本
})
await consumer.ready()
const result = await consumer.invoke('getUserInfo',
[{
$class: ' com.demo.provider.param.UserInfoQueryDTO',
$: {
mobilePhoneLike: {
$class: 'java.lang.String',
$: '157'
}
}
}], {
responseTimeout: 3000
})
console.log('==============result======================')
console.log(result)
console.log('====================================')
return result
}
结果运行报错:
com.alibaba.dubbo.remoting.RemotingException:
Not found exported service:
com.demo.provider.UserBaseQueryProvider: 1.0 .0.dev: 21880
in
[
HSF / com.demo.provider.UserBaseProvider: 1.0 .0.dev: 21880,
HSF / com.demo.provider.customer.CustomerIdentityProvider: 1.0 .0.dev: 21880,
HSF / com.demo.testclient.provider.city.BaseUserCityRelationshipProvider: 1.0 .0.dev: 21880,
HSF / com.demo.testclient.provider.permission.menu.PermissionMenuProvider: 1.0 .0.dev: 21880,
HSF / com.demo.provider.UserBaseTagProvider: 1.0 .0.dev: 21880,
HSF / com.demo.provider.UserBaseQueryProvider: 1.0 .0.dev: 21880
],
may be version or group mismatch, channel: consumer: /121.*.*.1:55359 --> provider: /
121.*.* .202: 21880, message: RpcInvocation[
methodName = getUserInfo,
parameterTypes = [class com.demo.provider.param.UserInfoQueryDTO],
arguments = [com.demo.provider.param.UserInfoQueryDTO @86f0588],
attachments = {
path = com.demo.provider.UserBaseQueryProvider,
input = 433,
service = com.demo.provider.UserBaseQueryProvider: 1.0 .0.dev,
dubbo = 5.3 .0,
version = 1.0 .0.dev
}
]
并且程序还尝试了去连接这个接口的另外两个版本(1.0.0.daily 和 1.0.0.test)(我并没有去指定连接它们),抛出警告:
2018-10-30 10:52:27,188 WARN 15449 [ConnectionManager] create connection: dubbo://10.*.*.68:12210/com.demo.provider.UserBaseQueryProvider?ROUTE=-1&_CONTAINERID=ecc:e63288c0-17ca-4d62-bb79-a765c447d2fb&_ENV=DEFAULT&_SERIALIZETYPE=hessian&_TID=dcc6f6d8-6697-4d65-b520-5c4ae10d507f&_TIMEOUT=3000&_ih2=y&_p=hessian2&application=d58921e6-953c-4f37-9228-efd1b6413eb1&dubbo=2.6.1&group=HSF&interface=com.demo.provider.UserBaseQueryProvider&side=provider&timeout=3000&v=2.0&version=1.0.0.daily failed, caused by socket#dubbo://10.*.*.68:12210/com.demo.provider.UserBaseQueryProvider?ROUTE=-1&_CONTAINERID=ecc:e63288c0-17ca-4d62-bb79-a765c447d2fb&_ENV=DEFAULT&_SERIALIZETYPE=hessian&_TID=dcc6f6d8-6697-4d65-b520-5c4ae10d507f&_TIMEOUT=3000&_ih2=y&_p=hessian2&application=d58921e6-953c-4f37-9228-efd1b6413eb1&dubbo=2.6.1&group=HSF&interface=com.demo.provider.UserBaseQueryProvider&side=provider&timeout=3000&v=2.0&version=1.0.0.daily connect timeout(3000ms)
2018-10-30 10:52:27,189 WARN 15449 [ConnectionManager] create connection: dubbo://172.*.*.6:12202/com.demo.provider.UserBaseQueryProvider?APP=f42e78eb-d28c-4921-b058-248e99841976&ROUTE=-1&_CONTAINERID=ecc:8b6b6208-8dce-4b68-a80d-b2f3240363ee&_ENV=DEFAULT&_SERIALIZETYPE=hessian&_TID=5c098aaa-2bf1-4782-a641-fd63ec280452&_TIMEOUT=3000&_p=hessian2&application=f42e78eb-d28c-4921-b058-248e99841976&dubbo=2.6.1&group=HSF&interface=com.demo.provider.UserBaseQueryProvider&side=provider&timeout=3000&v=2.0&version=1.0.0.test failed, caused by socket#dubbo://172.*.*.6:12202/com.demo.provider.UserBaseQueryProvider?APP=f42e78eb-d28c-4921-b058-248e99841976&ROUTE=-1&_CONTAINERID=ecc:8b6b6208-8dce-4b68-a80d-b2f3240363ee&_ENV=DEFAULT&_SERIALIZETYPE=hessian&_TID=5c098aaa-2bf1-4782-a641-fd63ec280452&_TIMEOUT=3000&_p=hessian2&application=f42e78eb-d28c-4921-b058-248e99841976&dubbo=2.6.1&group=HSF&interface=com.demo.provider.UserBaseQueryProvider&side=provider&timeout=3000&v=2.0&version=1.0.0.test connect timeout(3000ms)
我大概知道了,稍等
https://github.com/alipay/sofa-rpc-node/pull/18
@JimmyDaddy 重新安装一下,再试试
问题还是存在的 我在 1.5.1 版本里面 通过 registry 报错:
no provider of *** found!
直连是可以成功的, 我稍微看了一下,貌似还是 address 获取失败的原因
async getConnection(req) {
const meta = req.meta;
meta.connectionGroup = this.key;
const address = this._loadbalancer.select(req); // address 为 null
if (!address) return null;
const { connectionOpts, connectionClass } = this.options;
return await this.connectionManager.createAndGet(address, connectionOpts, connectionClass);
}
测试代码和上面的 demo 一样
@JimmyDaddy 把完整的日志给我
要具体看下订阅到的 url,之前都可以访问到机器,只是 group 没有匹配上,现在找不到,说明是新加的逻辑把它过滤掉了
日志并不多,仅仅抛出了一个我上面提到的错误; 我看了看源码打了些日志,执行请求时:
client/consumer.js
的 _init()
里:this.registryConfig
为:
{
protocol: 'bolt',
interfaceName: 'com.demo.provider.UserBaseQueryProvider',
version: '1.0.0.dev',
group: 'HSF',
appName: undefined,
timeout: 3000
}
在 registry/zk/data_client.js
里面 subscribe
方法:
subscribe(config, listener) {
assert(config && config.interfaceName, '[ZookeeperRegistry] subscribe(config, listener) config.interfaceName is required');
const interfaceName = config.interfaceName;
if (!this._subscribeMap.has(interfaceName)) {
this._subscribeMap.set(interfaceName, null);
const providerPath = this._buildProviderPath(config); // /dubbo/com.sxc.jothuheim.userbaseclient.provider.UserBaseQueryProvider/providers
this._zkClient.mkdirp(providerPath)
.then(() => {
this._zkClient.watchChildren(providerPath, (err, children) => {
if (err) {
this.emit('error', err);
return;
}
console.log('=============children=======================');
console.log( children); // 这里的 children 返回了四个版本的接口,是我们服务器上已有的
console.log('====================================');
const originAddressList = children.map(url => urlencode.decode(url));
const addressList = originAddressList.filter(url => this._isMatch(config, url));
this.logger.info('[ZookeeperRegistry] receive interface:%s:%s@%s address list (%d):\n%s\nvalid providers (%d):\n%s',
config.interfaceName, config.version || '', config.group || '',
originAddressList.length, formatAddrs(originAddressList), addressList.length, formatAddrs(addressList));
this._subscribeMap.set(interfaceName, addressList);
this.emit(interfaceName, addressList);
});
})
.catch(err => { this.emit('error', err); });
const consumerPath = this._buildConsumerPath(config);
const consumerUrl = fmt('%s://%s?uniqueId=%s&version=%s&pid=%s&timeout=%s&appName=%s&serialization=%s&startTime=',
config.protocol, localIp, config.uniqueId || '', '1.0', process.pid, config.timeout, config.appName || '', Date.now());
const path = consumerPath + '/' + urlencode.encode(consumerUrl);
this._zkClient.mkdirp(consumerPath)
.then(() => {
return this._zkClient.create(path, EMPTY, CreateMode.EPHEMERAL);
})
.catch(err => {
this.logger.warn('[ZookeeperRegistry] create consumerPath: %s failed, caused by %s', path, err.message);
});
} else {
const addressList = this._subscribeMap.get(interfaceName);
if (addressList) {
setImmediate(() => { listener(addressList); });
}
}
this.on(interfaceName, listener);
}
其中 ` this._zkClient.watchChildren` 返回的 四个版本的 children 是我们已有的四个版本,分别为:
* `dubbo://192.168.0.59:21880/com.demo.provider.UserBaseQueryProvider?anyhost=true&application=user-service&default.group=HSF&default.version=1.0.0.yrc&dubbo=2.0.1&generic=false&interface=com.provider.UserBaseQueryProvider&logger=slf4j&methods=getListUserProperty,getMDSUserInfoByEdata,getByIds,getById,getByPhoneAndPassword,getByEdata,getUserInfoPage,getMockUserInfoByCatGroupId,getUserInfo,getByMobilePhone&pid=1379&revision=1.0.0-SNAPSHOT&side=provider×tamp=1541040082598`
这一个的 provider 是局域网 ip,
它的 providerInfo 为 :
URLSearchParams { 'anyhost' => 'true', 'application' => 'user-service', 'default.group' => 'HSF', 'default.version' => '1.0.0.yrc', 'dubbo' => '2.0.1', 'generic' => 'false', 'interface' => 'com.demo.provider.UserBaseQueryProvider', 'logger' => 'slf4j', 'methods' => 'getListUserProperty,getMDSUserInfoByEdata,getByIds,getById,getByPhoneAndPassword,getByEdata,getUserInfoPage,getMockUserInfoByCatGroupId,getUserInfo,getByMobilePhone', 'pid' => '30009', 'revision' => '1.0.0-SNAPSHOT', 'side' => 'provider', 'timestamp' => '1540797787690' }
* `dubbo://121.*.*.*:21880/com.demo.provider.UserBaseQueryProvider?anyhost=true&application=user-service&default.group=HSF&default.version=1.0.0.dev&dubbo=2.0.1&generic=false&interface=com.provider.UserBaseQueryProvider&logger=slf4j&methods=getListUserProperty,getMDSUserInfoByEdata,getByIds,getById,getByPhoneAndPassword,getByEdata,getUserInfoPage,getMockUserInfoByCatGroupId,getUserInfo,getByMobilePhone&pid=30009&revision=1.0.0-SNAPSHOT&side=provider×tamp=1540797787690`
这一个就是我要访问的那一个版本(1.0.0.dev)的 provider ,宿主是外网 ip 可访问的,直连能返回数据,但是通过 registry 就无法定位到它了,而且这个和 下面两个可定位到的 provider 有很大的不同 ,
它的 providerInfo 为:
URLSearchParams { 'anyhost' => 'true', 'application' => 'user-service', 'default.group' => 'HSF', // group 和 version 变为了 default.group 和 default.version 'default.version' => '1.0.0.dev', 'dubbo' => '2.0.1', 'generic' => 'false', 'interface' => 'com.demo.provider.UserBaseQueryProvider', 'logger' => 'slf4j', 'methods' => 'getListUserProperty,getMDSUserInfoByEdata,getByIds,getById,getByPhoneAndPassword,getByEdata,getUserInfoPage,getMockUserInfoByCatGroupId,getUserInfo,getByMobilePhone', 'pid' => '30009', 'revision' => '1.0.0-SNAPSHOT', 'side' => 'provider', 'timestamp' => '1540797787690' }
* `dubbo://172.*.*.6:12200/com.demo.provider.UserBaseQueryProvider?APP=f42e78eb-d28c-4921-b058-248e99841976&ROUTE=-1&_CONTAINERID=ecc:8b6b6208-8dce-4b68-a80d-b2f3240363ee&_ENV=DEFAULT&_SERIALIZETYPE=hessian&_TID=5c098aaa-2bf1-4782-a641-fd63ec280452&_TIMEOUT=3000&_p=hessian2&application=f42e78eb-d28c-4921-b058-248e99841976&dubbo=2.6.1&group=HSF&interface=com.provider.UserBaseQueryProvider&side=provider&timeout=3000&v=2.0&version=1.0.0.test`
这一个是属于内网 ip,我尝试过访问该版本的服务,能够定位到这个服务,因为内网 Ip 的缘故连接时 timeout ,
providerInfo 为 :
URLSearchParams { 'ROUTE' => '-1', '_CONTAINERID' => 'ecc:e63288c0-17ca-4d62-bb79-a765c447d2fb', '_ENV' => 'DEFAULT', '_SERIALIZETYPE' => 'hessian', '_TID' => 'dcc6f6d8-6697-4d65-b520-5c4ae10d507f', '_TIMEOUT' => '3000', '_ih2' => 'y', '_p' => 'hessian2', 'application' => 'd58921e6-953c-4f37-9228-efd1b6413eb1', 'dubbo' => '2.6.1', 'group' => 'HSF', 'interface' => 'com.demo.provider.UserBaseQueryProvider', 'side' => 'provider', 'timeout' => '3000', 'v' => '2.0', 'version' => '1.0.0.test' }
* `dubbo://10.*.*.68:12210/com.demo.provider.UserBaseQueryProvider?ROUTE=-1&_CONTAINERID=ecc:e63288c0-17ca-4d62-bb79-a765c447d2fb&_ENV=DEFAULT&_SERIALIZETYPE=hessian&_TID=dcc6f6d8-6697-4d65-b520-5c4ae10d507f&_TIMEOUT=3000&_ih2=y&_p=hessian2&application=d58921e6-953c-4f37-9228-efd1b6413eb1&dubbo=2.6.1&group=HSF&interface=com.provider.UserBaseQueryProvider&side=provider&timeout=3000&v=2.0&version=1.0.0.daily`
这一个是属于内网 ip,我尝试过访问该版本的服务,也能够定位到这个服务,因为内网 Ip 的缘故连接时 timeout ,
providerInfo 为 :
URLSearchParams { 'ROUTE' => '-1', '_CONTAINERID' => 'ecc:e63288c0-17ca-4d62-bb79-a765c447d2fb', '_ENV' => 'DEFAULT', '_SERIALIZETYPE' => 'hessian', '_TID' => 'dcc6f6d8-6697-4d65-b520-5c4ae10d507f', '_TIMEOUT' => '3000', '_ih2' => 'y', '_p' => 'hessian2', 'application' => 'd58921e6-953c-4f37-9228-efd1b6413eb1', 'dubbo' => '2.6.1', 'group' => 'HSF', 'interface' => 'com.demo.provider.UserBaseQueryProvider', 'side' => 'provider', 'timeout' => '3000', 'v' => '2.0', 'version' => '1.0.0.daily' }
***前两个是直接注册到 zk 上的,后两个则是通过 edas 注册到 zk 上的,并且前两个的 dubbo 版本 为 2.0.1 ,后两个版本为 2.6.1***
我发现问题出在 `data_client.js` 的 `_isMatch` 方法上:
```javascript
_isMatch(consumer, urlStr) {
const url = new URL(urlStr);
const providerInfo = url.searchParams || {};
const interfaceName = providerInfo.get('interface') || url.pathname.slice(1);
if (interfaceName && consumer.interfaceName !== interfaceName) {
return false;
}
const category = providerInfo.get('category');
if (category && category !== 'providers') {
return false;
}
const enabled = providerInfo.get('enabled');
if (enabled && enabled !== 'true') {
return false;
}
const consumerGroup = consumer.group;
const consumerVersion = consumer.version;
const providerGroup = providerInfo.get('group'); // group 有可能为 default.group
const providerVersion = providerInfo.get('version'); // version 有可能为 default.version
return (!consumerGroup || consumerGroup === providerGroup) &&
(!consumerVersion || consumerVersion === providerVersion);
}
我将 _isMatch
里面的两行代码改了一下:
const providerGroup = providerInfo.get('group');
const providerVersion = providerInfo.get('version');
改为
const providerGroup = providerInfo.get('group') || providerInfo.get('default.group');
const providerVersion = providerInfo.get('version') || providerInfo.get('default.version');
就能访问成功了
@JimmyDaddy ok,我改下
@JimmyDaddy 再试试
好了,没问题了@gxcsoccer 谢谢
集成 dubbo 时,AddressGroup 的 addressList 为空
async getConnection(req) { return await this._addressGroup.getConnection(req); }