Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nacos服务注册ServiceName无法支持Identifier #612

Closed
jujusharp opened this issue May 9, 2019 · 11 comments · Fixed by #617
Closed

Nacos服务注册ServiceName无法支持Identifier #612

jujusharp opened this issue May 9, 2019 · 11 comments · Fixed by #617
Labels
help wanted Extra attention is needed

Comments

@jujusharp
Copy link
Contributor

Describe the bug

使用NacosRegistry进行服务注册时, 无法支持同一个接口多个实现通过Identifier区分的服务注册, Nacos永远用最后一个服务覆盖前面注册的实例.

Expected behavior

之前我认为这个是Nacos的问题, 在Nacos那边提了Issue, 希望服务注册除了InterfaceName还可以支持类似Group这种额外的参数. 但通过查看SOFARPC其它注册服务的代码发现. 在SOFARPC中, 其它的服务注册组件都是在生成ServiceName的时候将IdentifierName一起构造进去的, 调用的方法基本都是系统内置的方法: com.alipay.sofa.rpc.common.utils.StringUtils.ConfigUniqueNameGenerator.getUniqueName()和Protocol组合的方式. 而Nacos的获取方式是直接获取config.getInterfaceId()这种方式.

因此, 期望客户端注册ServiceName能类似其他服务注册客户端ServiceName由InterfaceId+Identifier+Protocol共同组成.

Actual behavior

NacosRegistry目前是直接获取InterfaceId, 代码:

String serviceName = config.getInterfaceId();

Steps to reproduce

  1. 编码实现一个接口的两种不同实现, 不同的实现类分别定义不同的Identifier
  2. 将两个实现均注册到Nacos服务管理中心
  3. 系统会只保留最后添加的接口实现. Identifier仅仅保留到实例Meta信息中.

Minimal yet complete reproducer code (or GitHub URL to code)

Environment

  • SOFARPC version:
  • JVM version JDK8:
  • OS version Centos 7:
  • Maven version: MAVEN 3
  • IDE version:
@jujusharp
Copy link
Contributor Author

另外, 我在本地已经实现了基于ConfigUniqueNameGenerator.getServiceName()+协议信息的代码实现, 如果可以确认的话, 我可以提交一个针对该问题的PR

@jujusharp
Copy link
Contributor Author

其他的服务注册客户端参考, 如registry-sofa实现方式参考:

/**
     * 构建服务列表的DataId, 格式为interface:version[:uniqueId]@protocol
     *
     * @param config   配置
     * @param protocol 协议
     * @return 返回值
     */
    public static String buildListDataId(AbstractInterfaceConfig config, String protocol) {
        if (RpcConstants.PROTOCOL_TYPE_BOLT.equals(protocol) || RpcConstants.PROTOCOL_TYPE_TR.equals(protocol)) {
            return ConfigUniqueNameGenerator.getUniqueName(config) + "@DEFAULT";
        } else {
            return ConfigUniqueNameGenerator.getUniqueName(config) + "@" + protocol;
        }
    }

@leizhiyuan leizhiyuan added the help wanted Extra attention is needed label May 9, 2019
@leizhiyuan
Copy link
Contributor

感谢,你是对的,应该下面这样getUniqueName 带上uniqueId。如果这两天可以的话,基于5.5分支拉一个分支,提一个pr到 5.5 分支。

如果要晚一点,可以基于master拉分支,提pr到master。

@jujusharp
Copy link
Contributor Author

好, 我尽快提交pr

@JervyShi
Copy link
Member

JervyShi commented May 9, 2019

@jujusharp Nacos Registry 的设计与 Zookeeper 的类似,服务发布时以 interface 为 key,但是每个接口在发布自己地址的时候 uniqueId 会以 MetaData 的形式挂载在 Nacos 的 Instance 下,订阅方在订阅到地址之后会根据 UniqueId 做一次过滤,所以不同 UniqueId 的场景应该是能支撑的,你可以看下 NacosRegistryTest 里面有相同 interface 不同 uniqueId 的订阅用例。如实测有问题,可以给个复现 demo 我们一起来看下。

@JervyShi
Copy link
Member

JervyShi commented May 9, 2019

@jujusharp 以下注释有描述我当时设计 Nacos Registry 的意图,protocoluniqueId 均作为当前服务实例的 meta 信息存在,订阅方是可以基于这份 meta 做自由过滤的,protocoluniqueId 不是一定要和 interface 加在一起作为 serviceName 的。
https://github.com/alipay/sofa-rpc/blob/a22a1c0efefd9c74d40f7bd99964fcb6194eed67/extension-impl/registry-nacos/src/main/java/com/alipay/sofa/rpc/registry/nacos/NacosRegistry.java#L60-L67

@jujusharp
Copy link
Contributor Author

@JervyShi meta信息确实会包含identifier信息, 但在nacos服务治理中心那里, 他们的实例唯一key是Ip+端口, 见line476, 意味着对于服务注册方, 如果同一个接口, 同一个IP, 同一个端口. 但多个不同的实现, 后面的接口实现会覆盖前面的实现, 因为他们的注册ip和端口是相同的. 但对于我们的服务来说. 是存在在一个服务实例中存在多个不同的实现的并且同时提供多个实现的服务的.

@jujusharp
Copy link
Contributor Author

jujusharp commented May 9, 2019

@JervyShi NacosRegistryTest中服务注册和消费确实包含了identifier的示例, 但在测试用例中, 是用来测试消费端是否正确的区分不同的identifier的. 在我们的场景中. 并不是说注册实例影响消费. 而是导致注册的实例在服务中心只存在一份, 原来的不同identifer但ip端口相同的会被覆盖, 从而无法消费时找不到对应注册实例. 只要能注册到服务中心(通过修改端口或者ip的方式), 消费的逻辑确实能正常工作.
如果我需要多份实现的话, 只能将每个实现分开部署多份(IP或者端口发生变化), 确实可以注册多份实例, 但这个就失去了意义.

@jujusharp
Copy link
Contributor Author

这个问题对于Nacos注册中心那边也不好作为一个bug,因为对于实例meta来说, 所有的meta字段都是平等的注册服务基础配置而已, 没办法说meta中一个特殊字段还参与决定Instance是否是同一个. 如果需要, 那只能将Instance的所有meta都参与决定Instance是否唯一的因子. 但这样就有些奇怪了.

@JervyShi
Copy link
Member

JervyShi commented May 9, 2019

@jujusharp 明白了,所以你的核心诉求是让 Nacos 的服务治理可以在 SOFA RPC 的场景下更完整的 Work,因此需要改造这个模型。

@jujusharp
Copy link
Contributor Author

jujusharp commented May 9, 2019

感谢回复. 是的, 因为我们现在的需求是根据系统负载能在业务负载的不同阶段决定是否需要将服务集成一个包部署还是拆成更多的独立服务部署(主要还是考虑不同阶段的资源和运维需求不同). 因此, 确实在某些场景需要将多个实现放到一个进程中(端口和ip相同)对外提供服务. 这时候可能更好的改造是在sofarpc这边会更适合些.
如果将每个实现都单独部署成不同的独立应用的话, 现有的模型是支持的.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants