apache / shenyu

Apache ShenYu is a Java native API Gateway for service proxy, protocol conversion and API governance.
https://shenyu.apache.org/
Apache License 2.0
8.41k stars 2.92k forks source link

[BUG] <When the project is started, the ZK node cannot be found exception occurs> #2274

Closed wtlihao closed 2 years ago

wtlihao commented 2 years ago

Question

jdk version: jdk11 shenyu version : 2.4.1 exception stack: Exception in thread "shenyu-disruptor-shenyu_disruptorconsumer-17" org.I0Itec.zkclient.exception.ZkNoNodeException: org.apache.zookeeper.KeeperException$NoNodeException: KeeperErrorCode = NoNode for /shenyu/register/metadata/http/knowledge-mall//knowledge-mall/--knowledge-mall-** at org.I0Itec.zkclient.exception.ZkException.create(ZkException.java:47) at org.I0Itec.zkclient.ZkClient.retryUntilConnected(ZkClient.java:1001) at org.I0Itec.zkclient.ZkClient.create(ZkClient.java:528) at org.I0Itec.zkclient.ZkClient.create(ZkClient.java:499) at org.I0Itec.zkclient.ZkClient.createPersistent(ZkClient.java:386) at org.apache.shenyu.register.client.zookeeper.ZookeeperClientRegisterRepository.registerMetadata(ZookeeperClientRegisterRepository.java:95) at org.apache.shenyu.register.client.zookeeper.ZookeeperClientRegisterRepository.persistInterface(ZookeeperClientRegisterRepository.java:64) at org.apache.shenyu.client.core.disruptor.subcriber.ShenyuClientMetadataExecutorSubscriber.executor(ShenyuClientMetadataExecutorSubscriber.java:51) at org.apache.shenyu.client.core.disruptor.executor.RegisterClientConsumerExecutor.run(RegisterClientConsumerExecutor.java:47) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:834)

wtlihao commented 2 years ago

who can response?

AhahaGe commented 2 years ago

please provide more information of your setup step, and related project and configuration.

wtlihao commented 2 years ago

when project bootstrap. occur this exception. config: shenyu: client: registerType: zookeeper serverLists: zk1.yaomaitong.net:2181 props: props: appName: appName

当前mvc项目在ShenYu网关的路由前缀

  contextPath: ${server.servlet.context-path}
  # 本项目的启动端口
  port: ${server.port}
  # 设置true 代表代理你的整个服务,false表示代理你其中某几个controller
  isFull: true
AhahaGe commented 2 years ago

can you format your config file?

wtlihao commented 2 years ago

step1:

shenyu:
    client:
    registerType: zookeeper
    serverLists: zk1.yaomaitong.net:2181
    props:
      contextPath: ${server.servlet.context-path}
      port: ${server.port}
      isFull: true

ZookeeperClientRegisterRepository DEBUG1: image

DEBUG2: image

when DEBUG2, occur the exception.

step2: I created a metaRegisterDTO object that is the same as in the DEBUG1 picture and tested it in the 2.4.1 source code

ZookeeperClientRegisterRepositoryTest#testPersistInterface():

    @Test
    public void testPersistInterface() {
        MetaDataRegisterDTO data = MetaDataRegisterDTO.builder()
                .rpcType("http")
                .host("192.168.3.179")
                .port(8081)
                .contextPath("/qxs-api/**")
                .ruleName("/qxs-api/**")
                .build();
        repository.persistInterface(data);
        String metadataPath = "/shenyu/register/metadata/http/qxs-api/qxs-api-**";
        Assert.assertTrue(zookeeperBroker.containsKey(metadataPath));
        Assert.assertEquals(zookeeperBroker.get(metadataPath), GsonUtils.getInstance().toJson(data));
        repository.close();
    }

Test Result:

09:33:31.507 [main] INFO org.apache.shenyu.register.client.zookeeper.ZookeeperClientRegisterRepository - http zookeeper client register success: MetaDataRegisterDTO{appName='null, contextPath='/qxs-api/**, path='null, pathDesc='null, rpcType='http, serviceName='null, methodName='null, ruleName='/qxs-api/**, parameterTypes='null, rpcExt='null, enabled=false, host='192.168.3.179, port=8081, pluginNames=[], registerMetaData=false}

java.lang.AssertionError
    at org.junit.Assert.fail(Assert.java:86)
    at org.junit.Assert.assertTrue(Assert.java:41)
    at org.junit.Assert.assertTrue(Assert.java:52)
    at org.apache.shenyu.register.client.zookeeper.ZookeeperClientRegisterRepositoryTest.testPersistInterface(ZookeeperClientRegisterRepositoryTest.java:132)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
wtlihao commented 2 years ago

image the method's target replace "/" to "-" ,but when context path is "/xx/" rule name is "/xx/", then final nodeName still exist "/"

AhahaGe commented 2 years ago

step1:

shenyu:
    client:
    registerType: zookeeper
    serverLists: zk1.yaomaitong.net:2181
    props:
      contextPath: ${server.servlet.context-path}
      port: ${server.port}
      isFull: true

ZookeeperClientRegisterRepository DEBUG1: image

DEBUG2: image

when DEBUG2, occur the exception.

step2: I created a metaRegisterDTO object that is the same as in the DEBUG1 picture and tested it in the 2.4.1 source code

ZookeeperClientRegisterRepositoryTest#testPersistInterface():

    @Test
    public void testPersistInterface() {
        MetaDataRegisterDTO data = MetaDataRegisterDTO.builder()
                .rpcType("http")
                .host("192.168.3.179")
                .port(8081)
                .contextPath("/qxs-api/**")
                .ruleName("/qxs-api/**")
                .build();
        repository.persistInterface(data);
        String metadataPath = "/shenyu/register/metadata/http/qxs-api/qxs-api-**";
        Assert.assertTrue(zookeeperBroker.containsKey(metadataPath));
        Assert.assertEquals(zookeeperBroker.get(metadataPath), GsonUtils.getInstance().toJson(data));
        repository.close();
    }

Test Result:

09:33:31.507 [main] INFO org.apache.shenyu.register.client.zookeeper.ZookeeperClientRegisterRepository - http zookeeper client register success: MetaDataRegisterDTO{appName='null, contextPath='/qxs-api/**, path='null, pathDesc='null, rpcType='http, serviceName='null, methodName='null, ruleName='/qxs-api/**, parameterTypes='null, rpcExt='null, enabled=false, host='192.168.3.179, port=8081, pluginNames=[], registerMetaData=false}

java.lang.AssertionError
  at org.junit.Assert.fail(Assert.java:86)
  at org.junit.Assert.assertTrue(Assert.java:41)
  at org.junit.Assert.assertTrue(Assert.java:52)
  at org.apache.shenyu.register.client.zookeeper.ZookeeperClientRegisterRepositoryTest.testPersistInterface(ZookeeperClientRegisterRepositoryTest.java:132)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.base/java.lang.reflect.Method.invoke(Method.java:566)
  at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
  at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
  at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
  at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
  at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
  at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
  at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
  at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
  at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
  at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
  at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
  at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
  at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
  at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)

please change metadataPath from String metadataPath = "/shenyu/register/metadata/http/qxs-api/qxs-api-"; to String metadataPath = "/shenyu/register/metadata/http/qxs-api//qxs-api/--qxs-api-"; image

AhahaGe commented 2 years ago

yes, as your context contains / in middle.

AhahaGe commented 2 years ago

zk node can't be found exception,

this url contains two //, please check. /shenyu/register/metadata/http/knowledge-mall//knowledge-mall/--knowledge-mall-**

wtlihao commented 2 years ago

image

wtlihao commented 2 years ago

zk node can't be found exception,

this url contains two //, please check. /shenyu/register/metadata/http/knowledge-mall//knowledge-mall/--knowledge-mall-**

that is editor's problem, i upload image, please view image’s exception

AhahaGe commented 2 years ago

have you checked whether zk server has that node?

wtlihao commented 2 years ago

There is no node of that ZK, because the NO NODE exception is reported when it is created

wtlihao commented 2 years ago

can you give me for your wechat ? wecaht chat

AhahaGe commented 2 years ago

image

please change contextPath from /qxs-api/** to /qxs-api and retry

AhahaGe commented 2 years ago

can you give me for your wechat ? wecaht chat

ahahage@163.com please send you wechat there

AhahaGe commented 2 years ago

this is a bug, as user config is as below, isFull proxy all controller, but contextPath will rewrite to /contextPath/**, add /**, when register metadata, and call zkClient.createPersistent(realNode, GsonUtils.getInstance().toJson(metadata)); realNode will contain two /, in zk it means two level directory, but parent node is not created ever, this call print error. image

// if contextPath has two /, in zk means two folder, we need to create parent folder first, or else it will throw no node exception zkClient.createPersistent(realNode, true); zkClient.writeData(realNode, GsonUtils.getInstance().toJson(metadata));