From dabf81bec2f667ce661fafb3d21f9d130179d999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=AA=E5=BD=B1oO?= <213539@qq.com> Date: Sun, 9 Oct 2022 21:52:00 +0800 Subject: [PATCH] release 0.5.0 (#930) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * set branch protection * rat exclude ".asf.yaml" * add master-0.2.0 to branch protection * Exclude the".flattened-pom.xml" file into the source package (#799) * Update copyright year (#801) * fix NPE in ServiceTestUtil.java (#804) * polish dockerfile for 0.3.0 (#805) * update dockerfile and enable autotest * fix test script * fix zookeeper version * fix rat * develop-for-dubbo-3.x branch merge to develop branch (#808) * [3.0]Add mesh rule route (#789) * add mesh rule route * add mesh rule check * For #756 (#791) * [ISSUE #760]Application discover support (#807) * application discover support * fix checkstyle * fix ci * remove useless pom import,modify Chinese comment * fix UT bug Co-authored-by: haoyann <1064645534@qq.com> Co-authored-by: Aaron-boom <55744718+Aaron-boom@users.noreply.github.com> * Fix generic invoke fail (#810) * fix generic invoke fail * fix ci * Nacos support application discover (#812) * Fix generic can't invoke repeatedly (#814) * Reduce nacos mapping service storage (#817) * optimize some code for RegistryServerSync (#822) * Fix circular reference (#823) * Fix service version spell (#824) * For #756 (#815) * For #756 * for 830 (#832) * for 830 * For 830 * For 830 * For 830 * For 830 * For 830 * [Feature] Dubbo Admin provides service mock ability. (#838) * commit the API * develop the front page. * add edit logic * develop the front page and test. * ui change * change the config key and group * change rule enable to config center. * update GlobalMockRule update logic. * remove the GlobalMockRule * [feature admin mock] move the diver dependency out of the project. * [feature admin mock] remove the contributor name and date in javadoc. * [feature admin mock] optimize the delete mock rule step. * [feature admin mock] fix the dialog cannot be closed when delete successfully. * [feature admin mock] add the support for h2 database. * [feature admin mock] rollback to zookeeper registry. * [feature admin mock] fix properties. * [feature admin mock] change mock-admin-api maven version. * [feature admin mock] fix the feedback and add the parameters in docker-compose. * [feature admin mock] fix the ci problem. * [feature admin mock] fix the ci problem. * [feature admin mock] removed unused import. * [feature admin mock] add license. * GovernanceConfiguration use dubbo instead DynamicConfiguration (#840) * GovernanceConfiguration use dubbo instead DynamicConfiguration * remove useless change * for release 0.4.0 (#850) * [ISSUE #856] update README.md (#857) * 修复更新,删除service类型的条件路由异常的问题 (#861) * Fix flaky (#883) * fix flaky test * Delete dubbo-admin-server/.nondex directory Co-authored-by: Ubuntu * support jdk11 #862 (#886) * support jdk11 #862 * support jdk11 #862 Co-authored-by: 卫龙 * fix #895 (#896) Co-authored-by: 卫龙 * fix #893 (#894) fix #893 Co-authored-by: 卫龙 * Update index.html (#899) 原cdn.bootcss.com域名失效,需要切换到新域名cdn.bootcdn.net 官网申明:https://www.bootcdn.cn * support swagger.enable (#902) * support swagger.enable * enable swagger by default Co-authored-by: 璟源 * support dubbo 3.0.8 (#903) * [Fix bug](#908) (#910) * ZookeeperMetaDataCollector init method add zk digest acl support (#911) * Fix notice and opt registry source (#913) * update year * fix search * add relation support * disable swagger * Bump fastjson from 1.2.67 to 1.2.83 (#907) Bumps [fastjson](https://github.com/alibaba/fastjson) from 1.2.67 to 1.2.83. - [Release notes](https://github.com/alibaba/fastjson/releases) - [Commits](https://github.com/alibaba/fastjson/compare/1.2.67...1.2.83) --- updated-dependencies: - dependency-name: com.alibaba:fastjson dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Add seriialization & timeout (#914) * update year * fix search * add relation support * disable swagger * fix interface * fix interface * 解决重复点功能,浏览器控制台报错问题,如点击:服务查询-搜索按钮 (#916) * Fix error when host is null (#920) * 解决重复点功能,浏览器控制台报错问题,如点击:服务查询-搜索按钮 * 解决可能产生的空指针问题,导致 '消费者'标签无法显示数据 * 解决在服务测试,方法执行成功后。动态生成的consumer元数据,host取值为空的问题情况(dubbo version 3.0.8) * Update ServiceDetail.vue (#921) * Up develop (#926) * release 0.5.0 Co-authored-by: wuwen Co-authored-by: Huang YunKun Co-authored-by: haoyann <1064645534@qq.com> Co-authored-by: Aaron-boom <55744718+Aaron-boom@users.noreply.github.com> Co-authored-by: Wang Chengming <634749869@qq.com> Co-authored-by: brotherlu-xcq <1285823170@qq.com> Co-authored-by: Robert LU Co-authored-by: ymybxx <775289630@qq.com> Co-authored-by: plzdoo <55066376+plzdoo@users.noreply.github.com> Co-authored-by: Ubuntu Co-authored-by: chenjjl <50745778+chenjjl@users.noreply.github.com> Co-authored-by: 卫龙 Co-authored-by: VirensCn <595170292@qq.com> Co-authored-by: itmajing Co-authored-by: 璟源 Co-authored-by: sherl0ckLiu <108274057+sherl0ckLiu@users.noreply.github.com> Co-authored-by: sage.xue Co-authored-by: Albumen Kevin Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: cnjxzhao <85160585+cnjxzhao@users.noreply.github.com> --- NOTICE | 2 +- README.md | 18 ++++-- README_ZH.md | 22 ++++--- docker/0.4.0/Dockerfile | 30 ++++++++++ docker/0.4.0/Dockerfile.test | 23 ++++++++ docker/0.4.0/docker-compose.test.yml | 33 +++++++++++ docker/0.4.0/test.sh | 34 +++++++++++ docker/0.5.0/Dockerfile | 30 ++++++++++ docker/0.5.0/Dockerfile.test | 23 ++++++++ docker/0.5.0/docker-compose.test.yml | 33 +++++++++++ docker/0.5.0/test.sh | 34 +++++++++++ dubbo-admin-distribution/pom.xml | 2 + dubbo-admin-distribution/src/NOTICE | 4 +- .../src/bin/config/application.properties | 7 ++- dubbo-admin-server/pom.xml | 5 ++ .../dubbo/admin/common/util/SyncUtils.java | 14 ++++- .../dubbo/admin/config/ConfigCenter.java | 15 ++--- .../admin/config/SwaggerConfiguration.java | 2 + .../dubbo/admin/model/domain/Entity.java | 18 +++++- .../dubbo/admin/model/domain/Provider.java | 41 ++++++++++++- .../admin/model/domain/RegistrySource.java | 2 + .../mapping/AdminMappingListener.java | 6 ++ .../mapping/impl/ZookeeperServiceMapping.java | 3 +- .../metadata/impl/NacosMetaDataCollector.java | 7 ++- .../impl/ZookeeperMetaDataCollector.java | 10 +++- .../admin/service/RegistryServerSync.java | 7 ++- .../service/impl/ConsumerServiceImpl.java | 13 ++++- .../service/impl/InstanceRegistryCache.java | 57 +++++++++++++++++++ .../impl/InstanceRegistryQueryHelper.java | 40 ++++++++++++- .../service/impl/ProviderServiceImpl.java | 43 ++++++++++---- .../admin/service/impl/RouteServiceImpl.java | 2 + .../admin/utils/ApiDocsDubboGenericUtil.java | 2 + .../src/main/resources/application.properties | 2 +- .../dubbo/admin/common/util/UrlUtilsTest.java | 4 +- dubbo-admin-ui/public/dubbo-admin-info.json | 2 +- dubbo-admin-ui/public/index.html | 2 +- .../src/components/ServiceDetail.vue | 19 +++---- .../src/components/ServiceSearch.vue | 4 ++ .../src/components/public/Footers.vue | 2 +- dubbo-admin-ui/src/lang/en.js | 1 + dubbo-admin-ui/src/lang/zh.js | 1 + dubbo-admin-ui/src/router/index.js | 5 ++ pom.xml | 12 +++- 43 files changed, 572 insertions(+), 64 deletions(-) create mode 100644 docker/0.4.0/Dockerfile create mode 100644 docker/0.4.0/Dockerfile.test create mode 100644 docker/0.4.0/docker-compose.test.yml create mode 100644 docker/0.4.0/test.sh create mode 100644 docker/0.5.0/Dockerfile create mode 100644 docker/0.5.0/Dockerfile.test create mode 100644 docker/0.5.0/docker-compose.test.yml create mode 100644 docker/0.5.0/test.sh diff --git a/NOTICE b/NOTICE index 6367c40de..9776704f0 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Apache Dubbo Admin -Copyright 2018-2021 The Apache Software Foundation +Copyright 2018-2022 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). diff --git a/README.md b/README.md index e0182457b..20b112210 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,11 @@ service governance follows the version of Dubbo 2.7, and compatible for Dubbo 2. - [Vue.js](https://vuejs.org) and [Vue Cli](https://cli.vuejs.org/) - [dubbo-admin-ui/README.md](dubbo-admin-ui/README.md) for more detail -- Set npm **proxy mirror**: if you have network issue, you can set npm proxy mirror to speedup npm install: add `registry =https://registry.npm.taobao.org` to ~/.npmrc +- Set npm **proxy mirror**: + + if you have network issue, you can set npm proxy mirror to speedup npm install: + + add `registry=https://registry.npmmirror.com` to ~/.npmrc ### admin Server @@ -35,10 +39,9 @@ service governance follows the version of Dubbo 2.7, and compatible for Dubbo 2. 1. Clone source code on develop branch `git clone https://github.com/apache/dubbo-admin.git` 2. Specify registry address in `dubbo-admin-server/src/main/resources/application.properties` 3. Build - - > - `mvn clean package -Dmaven.test.skip=true` + - `mvn clean package -Dmaven.test.skip=true` 4. Start - * `mvn --projects dubbo-admin-server spring-boot:run` + * `mvn --projects dubbo-admin-server spring-boot:run` OR * `cd dubbo-admin-distribution/target`; `java -jar dubbo-admin-0.1.jar` 5. Visit `http://localhost:8080` @@ -47,10 +50,15 @@ service governance follows the version of Dubbo 2.7, and compatible for Dubbo 2. ### Development Setup * Run admin server project - backend is a standard spring boot project, you can run it in any java IDE + + backend is a standard spring boot project, you can run it in any java IDE + * Run admin ui project + run with `npm run dev`. + * visit web page + visit `http://localhost:8081`, frontend supports hot reload. ### Swagger support diff --git a/README_ZH.md b/README_ZH.md index c1a21d10f..4d3512835 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -20,7 +20,11 @@ - 使用[Vue.js](https://vuejs.org)作为javascript框架 - [dubbo-admin-ui/README.md](dubbo-admin-ui/README.md)中有更详细的介绍 -- 设置 npm **代理镜像** : 如果遇到了网络问题,可以设置npm代理镜像来加速npm install的过程:在~/.npmrc中增加 `registry =https://registry.npm.taobao.org` +- 设置 npm **代理镜像** : + + 如果遇到了网络问题,可以设置npm代理镜像来加速npm install的过程: + + 在~/.npmrc中增加 `registry=https://registry.npmmirror.com` ### 后端部分 @@ -33,21 +37,25 @@ 1. 下载代码: `git clone https://github.com/apache/dubbo-admin.git` 2. 在 `dubbo-admin-server/src/main/resources/application.properties`中指定注册中心地址 3. 构建 - - > - `mvn clean package -Dmaven.test.skip=true` + - `mvn clean package -Dmaven.test.skip=true` 4. 启动 - * `mvn --projects dubbo-admin-server spring-boot:run` - 或者 - * `cd dubbo-admin-distribution/target; java -jar dubbo-admin-0.1.jar` + * `mvn --projects dubbo-admin-server spring-boot:run` + 或者 + * `cd dubbo-admin-distribution/target; java -jar dubbo-admin-0.1.jar` 5. 访问 `http://localhost:8080` --- ### 开发环境配置 * 运行`dubbo admin server` - `dubbo admin server`是一个标准的spring boot项目, 可以在任何java IDE中运行它 + + `dubbo admin server`是一个标准的spring boot项目, 可以在任何java IDE中运行它 + * 运行`dubbo admin ui` + `dubbo admin ui`由npm管理和构建,在开发环境中,可以单独运行: `npm run dev` + * 页面访问 + 访问 `http://localhost:8081`, 由于前后端分开部署,前端支持热加载,任何页面的修改都可以实时反馈,不需要重启应用。 ### Swagger 支持 diff --git a/docker/0.4.0/Dockerfile b/docker/0.4.0/Dockerfile new file mode 100644 index 000000000..621959ca5 --- /dev/null +++ b/docker/0.4.0/Dockerfile @@ -0,0 +1,30 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM maven:3-openjdk-8 +RUN mkdir /source && wget https://github.com/apache/dubbo-admin/archive/0.4.0.zip && unzip -q 0.4.0.zip -d /source +WORKDIR /source/dubbo-admin-0.4.0 +RUN mvn --batch-mode clean package -Dmaven.test.skip=true + +FROM openjdk:8-jre +LABEL maintainer="dev@dubbo.apache.org" +RUN apt-get update && apt-get install -y tini +COPY --from=0 /source/dubbo-admin-0.4.0/dubbo-admin-distribution/target/dubbo-admin-0.4.0.jar /app.jar +COPY --from=0 /source/dubbo-admin-0.4.0/docker/entrypoint.sh /usr/local/bin/entrypoint.sh + +ENV JAVA_OPTS "" + +ENTRYPOINT ["tini", "--", "/usr/local/bin/entrypoint.sh"] +EXPOSE 8080 diff --git a/docker/0.4.0/Dockerfile.test b/docker/0.4.0/Dockerfile.test new file mode 100644 index 000000000..dee4d1d35 --- /dev/null +++ b/docker/0.4.0/Dockerfile.test @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM ubuntu:trusty +RUN apt-get update && apt-get install -yq curl && apt-get clean + +WORKDIR /app + +ADD test.sh /app/test.sh + +CMD ["bash", "test.sh"] \ No newline at end of file diff --git a/docker/0.4.0/docker-compose.test.yml b/docker/0.4.0/docker-compose.test.yml new file mode 100644 index 000000000..9ac7fec20 --- /dev/null +++ b/docker/0.4.0/docker-compose.test.yml @@ -0,0 +1,33 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +zookeeper: + image: zookeeper:3.5 +admin: + build: . + dockerfile: Dockerfile + links: + - zookeeper + environment: + - admin.registry.address=zookeeper://zookeeper:2181 + - admin.config-center=zookeeper://zookeeper:2181 + - admin.metadata-report.address=zookeeper://zookeeper:2181 + ports: + - 8080 +sut: + build: . + dockerfile: Dockerfile.test + links: + - admin \ No newline at end of file diff --git a/docker/0.4.0/test.sh b/docker/0.4.0/test.sh new file mode 100644 index 000000000..d342e3550 --- /dev/null +++ b/docker/0.4.0/test.sh @@ -0,0 +1,34 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOOP_SIZE=60 +i=0 + +while [[ $i -lt LOOP_SIZE ]]; do + status_code=$(curl --write-out %{http_code} --silent --output /dev/null http://admin:8080) + + if [[ "$status_code" -eq 200 ]] ; then + echo "Tests passed!" + exit 0 + else + curl -v http://admin:8080 + echo "status is incorrect, waiting for next turn" + fi + sleep 5 + i=$i+1 +done + +echo "Tests failed!" +exit 1 \ No newline at end of file diff --git a/docker/0.5.0/Dockerfile b/docker/0.5.0/Dockerfile new file mode 100644 index 000000000..0cf7bcd3b --- /dev/null +++ b/docker/0.5.0/Dockerfile @@ -0,0 +1,30 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM maven:3-openjdk-8 +RUN mkdir /source && wget https://github.com/apache/dubbo-admin/archive/0.5.0.zip && unzip -q 0.5.0.zip -d /source +WORKDIR /source/dubbo-admin-0.5.0 +RUN mvn --batch-mode clean package -Dmaven.test.skip=true + +FROM openjdk:8-jre +LABEL maintainer="dev@dubbo.apache.org" +RUN apt-get update && apt-get install -y tini +COPY --from=0 /source/dubbo-admin-0.5.0/dubbo-admin-distribution/target/dubbo-admin-0.5.0.jar /app.jar +COPY --from=0 /source/dubbo-admin-0.5.0/docker/entrypoint.sh /usr/local/bin/entrypoint.sh + +ENV JAVA_OPTS "" + +ENTRYPOINT ["tini", "--", "/usr/local/bin/entrypoint.sh"] +EXPOSE 8080 diff --git a/docker/0.5.0/Dockerfile.test b/docker/0.5.0/Dockerfile.test new file mode 100644 index 000000000..dee4d1d35 --- /dev/null +++ b/docker/0.5.0/Dockerfile.test @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM ubuntu:trusty +RUN apt-get update && apt-get install -yq curl && apt-get clean + +WORKDIR /app + +ADD test.sh /app/test.sh + +CMD ["bash", "test.sh"] \ No newline at end of file diff --git a/docker/0.5.0/docker-compose.test.yml b/docker/0.5.0/docker-compose.test.yml new file mode 100644 index 000000000..9ac7fec20 --- /dev/null +++ b/docker/0.5.0/docker-compose.test.yml @@ -0,0 +1,33 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +zookeeper: + image: zookeeper:3.5 +admin: + build: . + dockerfile: Dockerfile + links: + - zookeeper + environment: + - admin.registry.address=zookeeper://zookeeper:2181 + - admin.config-center=zookeeper://zookeeper:2181 + - admin.metadata-report.address=zookeeper://zookeeper:2181 + ports: + - 8080 +sut: + build: . + dockerfile: Dockerfile.test + links: + - admin \ No newline at end of file diff --git a/docker/0.5.0/test.sh b/docker/0.5.0/test.sh new file mode 100644 index 000000000..d342e3550 --- /dev/null +++ b/docker/0.5.0/test.sh @@ -0,0 +1,34 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOOP_SIZE=60 +i=0 + +while [[ $i -lt LOOP_SIZE ]]; do + status_code=$(curl --write-out %{http_code} --silent --output /dev/null http://admin:8080) + + if [[ "$status_code" -eq 200 ]] ; then + echo "Tests passed!" + exit 0 + else + curl -v http://admin:8080 + echo "status is incorrect, waiting for next turn" + fi + sleep 5 + i=$i+1 +done + +echo "Tests failed!" +exit 1 \ No newline at end of file diff --git a/dubbo-admin-distribution/pom.xml b/dubbo-admin-distribution/pom.xml index e8e42fa8b..3cd4ddae6 100644 --- a/dubbo-admin-distribution/pom.xml +++ b/dubbo-admin-distribution/pom.xml @@ -53,6 +53,8 @@ + diff --git a/dubbo-admin-distribution/src/NOTICE b/dubbo-admin-distribution/src/NOTICE index df92423ec..05c73d645 100644 --- a/dubbo-admin-distribution/src/NOTICE +++ b/dubbo-admin-distribution/src/NOTICE @@ -1,5 +1,5 @@ Apache Dubbo Admin -Copyright 2018-2021 The Apache Software Foundation +Copyright 2018-2022 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). @@ -100,7 +100,7 @@ dubbo NOTICE ======================================================================== Apache Dubbo -Copyright 2018-2021 The Apache Software Foundation +Copyright 2018-2022 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). diff --git a/dubbo-admin-distribution/src/bin/config/application.properties b/dubbo-admin-distribution/src/bin/config/application.properties index dbbc16cd4..232b05ed9 100644 --- a/dubbo-admin-distribution/src/bin/config/application.properties +++ b/dubbo-admin-distribution/src/bin/config/application.properties @@ -57,6 +57,11 @@ server.compression.enabled=true server.compression.mime-types=text/css,text/javascript,application/javascript server.compression.min-response-size=10240 +#token timeout, default is one hour +admin.check.tokenTimeoutMilli=3600000 +#Jwt signingKey +admin.check.signSecret=86295dd0c4ef69a1036b0b0c15158d77 + #dubbo config dubbo.application.name=dubbo-admin dubbo.registry.address=${admin.registry.address} @@ -68,7 +73,7 @@ dubbo.registry.address=${admin.registry.address} #spring.datasource.password=mysql # h2 -spring.datasource.url=jdbc:h2:mem:~/dubbo-admin; +spring.datasource.url=jdbc:h2:mem:~/dubbo-admin;MODE=MYSQL; spring.datasource.username=sa spring.datasource.password= diff --git a/dubbo-admin-server/pom.xml b/dubbo-admin-server/pom.xml index 73be90fff..f03e523b0 100644 --- a/dubbo-admin-server/pom.xml +++ b/dubbo-admin-server/pom.xml @@ -228,6 +228,11 @@ h2 runtime + + + javax.xml.bind + jaxb-api + diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/SyncUtils.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/SyncUtils.java index 7a36c0b60..34b4e6557 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/SyncUtils.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/SyncUtils.java @@ -21,6 +21,8 @@ import org.apache.dubbo.admin.model.domain.RegistrySource; import org.apache.dubbo.common.BaseServiceMetadata; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.common.url.component.DubboServiceAddressURL; import org.apache.dubbo.common.utils.StringUtils; import java.util.ArrayList; @@ -57,11 +59,13 @@ public static Provider url2Provider(Pair pair) { p.setService(service); p.setAddress(url.getAddress()); p.setApplication(url.getParameter(Constants.APPLICATION_KEY)); - p.setUrl(url.toIdentityString()); + p.setUrl(url.toFullString()); p.setParameters(url.toParameterString()); p.setDynamic(url.getParameter("dynamic", true)); p.setEnabled(url.getParameter(Constants.ENABLED_KEY, true)); + p.setSerialization(url.getParameter(org.apache.dubbo.remoting.Constants.SERIALIZATION_KEY, "hessian2")); + p.setTimeout(url.getParameter(CommonConstants.TIMEOUT_KEY, CommonConstants.DEFAULT_TIMEOUT)); p.setWeight(url.getParameter(Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT)); p.setUsername(url.getParameter("owner")); p.setRegistrySource(RegistrySource.INTERFACE); @@ -94,7 +98,13 @@ public static Consumer url2Consumer(Pair pair) { String version = url.getUrlParam().getParameter(Constants.VERSION_KEY); String service = BaseServiceMetadata.buildServiceKey(getServiceInterface(url), group, version); c.setService(service); - c.setAddress(url.getHost()); + if (url.getHost() == null) { + if (url instanceof DubboServiceAddressURL) { + c.setAddress(((DubboServiceAddressURL) url).getConsumerURL().getRawParameter("host")); + } + } else { + c.setAddress(url.getHost()); + } c.setApplication(url.getParameter(Constants.APPLICATION_KEY)); c.setParameters(url.toParameterString()); diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java index 8c39771a0..f354d6dd1 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java @@ -38,6 +38,7 @@ import org.apache.dubbo.registry.RegistryService; import org.apache.dubbo.registry.client.ServiceDiscovery; import org.apache.dubbo.registry.client.ServiceDiscoveryFactory; +import org.apache.dubbo.rpc.model.ApplicationModel; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -46,6 +47,7 @@ import java.util.Arrays; import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY; +import static org.apache.dubbo.common.constants.RegistryConstants.ENABLE_EMPTY_PROTECTION_KEY; import static org.apache.dubbo.registry.client.ServiceDiscoveryFactory.getExtension; @Configuration @@ -147,8 +149,8 @@ Registry getRegistry() { } registryUrl = formUrl(registryAddress, registryGroup, registryNameSpace, username, password); } - RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension(); - registry = registryFactory.getRegistry(registryUrl); + RegistryFactory registryFactory = ApplicationModel.defaultModel().getExtensionLoader(RegistryFactory.class).getAdaptiveExtension(); + registry = registryFactory.getRegistry(registryUrl.addParameter(ENABLE_EMPTY_PROTECTION_KEY, String.valueOf(false))); return registry; } @@ -166,7 +168,7 @@ MetaDataCollector getMetadataCollector() { } } if (metadataUrl != null) { - metaDataCollector = ExtensionLoader.getExtensionLoader(MetaDataCollector.class).getExtension(metadataUrl.getProtocol()); + metaDataCollector = ApplicationModel.defaultModel().getExtensionLoader(MetaDataCollector.class).getExtension(metadataUrl.getProtocol()); metaDataCollector.setUrl(metadataUrl); metaDataCollector.init(); } else { @@ -179,11 +181,10 @@ MetaDataCollector getMetadataCollector() { @Bean(destroyMethod = "destroy") @DependsOn("dubboRegistry") ServiceDiscovery getServiceDiscoveryRegistry() throws Exception { - URL registryURL = registryUrl.setPath(RegistryService.class.getName()); + URL registryURL = registryUrl.setPath(RegistryService.class.getName()) + .addParameter(ENABLE_EMPTY_PROTECTION_KEY, String.valueOf(false)); ServiceDiscoveryFactory factory = getExtension(registryURL); - ServiceDiscovery serviceDiscovery = factory.getServiceDiscovery(registryURL); - serviceDiscovery.initialize(registryURL); - return serviceDiscovery; + return factory.getServiceDiscovery(registryURL); } @Bean diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/SwaggerConfiguration.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/SwaggerConfiguration.java index a4a4e8a26..ef44250db 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/SwaggerConfiguration.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/SwaggerConfiguration.java @@ -17,6 +17,7 @@ package org.apache.dubbo.admin.config; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; @@ -29,6 +30,7 @@ @Configuration @EnableSwagger2 +@ConditionalOnProperty(name = "swagger.enable", havingValue = "true") public class SwaggerConfiguration { @Bean public Docket createRestApi() { diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/Entity.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/Entity.java index 3982d6297..9778d1b31 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/Entity.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/Entity.java @@ -19,10 +19,10 @@ import java.io.Serializable; import java.util.Date; import java.util.List; +import java.util.Objects; /** * Entity - * */ public abstract class Entity implements Serializable { @@ -128,4 +128,20 @@ public void setMiss(boolean miss) { this.miss = miss; } + @java.lang.Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Entity entity = (Entity) o; + return miss == entity.miss && Objects.equals(ids, entity.ids) && Objects.equals(id, entity.id) && Objects.equals(hash, entity.hash) && Objects.equals(created, entity.created) && Objects.equals(modified, entity.modified) && Objects.equals(now, entity.now) && Objects.equals(operator, entity.operator) && Objects.equals(operatorAddress, entity.operatorAddress); + } + + @java.lang.Override + public int hashCode() { + return Objects.hash(ids, id, hash, created, modified, now, operator, operatorAddress, miss); + } } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/Provider.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/Provider.java index 2de0ad07e..3d4b1514a 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/Provider.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/Provider.java @@ -23,10 +23,10 @@ import java.util.Date; import java.util.List; import java.util.Map; +import java.util.Objects; /** * Provider - * */ public class Provider extends Entity { @@ -46,6 +46,10 @@ public class Provider extends Entity { private boolean enabled; /* provider enabled or not */ + private int timeout; /* provider timeout */ + + private String serialization; /* provider serialization */ + private int weight; /* provider weight */ private String application; /* application name */ @@ -191,6 +195,22 @@ public void setRegistrySource(RegistrySource registrySource) { this.registrySource = registrySource; } + public int getTimeout() { + return timeout; + } + + public void setTimeout(int timeout) { + this.timeout = timeout; + } + + public String getSerialization() { + return serialization; + } + + public void setSerialization(String serialization) { + this.serialization = serialization; + } + public URL toUrl() { Map serviceName2Map = ConvertUtil.serviceName2Map(getService()); /*if(!serviceName2Map.containsKey(Constants.INTERFACE_KEY)) { @@ -221,4 +241,23 @@ public URL toUrl() { return url; } + @java.lang.Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + Provider provider = (Provider) o; + return dynamic == provider.dynamic && enabled == provider.enabled && timeout == provider.timeout && weight == provider.weight && alived == provider.alived && Objects.equals(service, provider.service) && Objects.equals(url, provider.url) && Objects.equals(parameters, provider.parameters) && Objects.equals(address, provider.address) && Objects.equals(registry, provider.registry) && Objects.equals(serialization, provider.serialization) && Objects.equals(application, provider.application) && Objects.equals(username, provider.username) && Objects.equals(expired, provider.expired) && Objects.equals(override, provider.override) && Objects.equals(overrides, provider.overrides) && registrySource == provider.registrySource; + } + + @java.lang.Override + public int hashCode() { + return Objects.hash(super.hashCode(), service, url, parameters, address, registry, dynamic, enabled, timeout, serialization, weight, application, username, expired, alived, override, overrides, registrySource); + } } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/RegistrySource.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/RegistrySource.java index e54644c94..a6a993976 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/RegistrySource.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/RegistrySource.java @@ -19,6 +19,8 @@ public enum RegistrySource { + ALL, + INTERFACE, INSTANCE diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AdminMappingListener.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AdminMappingListener.java index 750c7347e..e33575558 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AdminMappingListener.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AdminMappingListener.java @@ -115,6 +115,7 @@ public void notifyAddressChanged(String protocolServiceKey, List urls) { List instanceAddressUrls = urls.stream().map(url -> (InstanceAddressURL) url).collect(Collectors.toList()); serviceMap.put(serviceKey, instanceAddressUrls); } + instanceRegistryCache.refreshConsumer(false); } private String removeProtocol(String protocolServiceKey) { @@ -126,4 +127,9 @@ private String removeProtocol(String protocolServiceKey) { } } + @Override + public void stop() { + // ignore + } + } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/ZookeeperServiceMapping.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/ZookeeperServiceMapping.java index 799c0403d..4c5dc5ddf 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/ZookeeperServiceMapping.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/ZookeeperServiceMapping.java @@ -26,6 +26,7 @@ import org.apache.dubbo.metadata.MappingListener; import org.apache.dubbo.remoting.zookeeper.ZookeeperClient; import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter; +import org.apache.dubbo.rpc.model.ApplicationModel; import java.util.List; import java.util.Set; @@ -45,7 +46,7 @@ public class ZookeeperServiceMapping implements ServiceMapping { @Override public void init(URL url) { - ZookeeperTransporter zookeeperTransporter = ZookeeperTransporter.getExtension(); + ZookeeperTransporter zookeeperTransporter = ZookeeperTransporter.getExtension(ApplicationModel.defaultModel()); zkClient = zookeeperTransporter.connect(url); listenerAll(); } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/NacosMetaDataCollector.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/NacosMetaDataCollector.java index 4379eca04..f03ca39d0 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/NacosMetaDataCollector.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/NacosMetaDataCollector.java @@ -110,8 +110,11 @@ public String getConsumerMetaData(MetadataIdentifier key) { private String getMetaData(MetadataIdentifier identifier) { try { - return configService.getConfig(identifier.getUniqueKey(KeyTypeEnum.UNIQUE_KEY), - group, 1000 * 10); + String fromDubboGroup = configService.getConfig(identifier.getUniqueKey(KeyTypeEnum.UNIQUE_KEY), + "dubbo", 1000 * 10); + return org.apache.dubbo.common.utils.StringUtils.isNotEmpty(fromDubboGroup) ? fromDubboGroup : + configService.getConfig(identifier.getUniqueKey(KeyTypeEnum.UNIQUE_KEY), + group, 1000 * 10); } catch (NacosException e) { logger.warn("Failed to get " + identifier + " from nacos, cause: " + e.getMessage(), e); } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/ZookeeperMetaDataCollector.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/ZookeeperMetaDataCollector.java index 3048f643b..9bba7423e 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/ZookeeperMetaDataCollector.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/ZookeeperMetaDataCollector.java @@ -53,7 +53,15 @@ public void init() { group = Constants.PATH_SEPARATOR + group; } root = group; - client = CuratorFrameworkFactory.newClient(url.getAddress(), new ExponentialBackoffRetry(1000, 3)); + CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory. + builder() + .connectString(url.getAddress()) + .retryPolicy(new ExponentialBackoffRetry(1000, 3)); + String userInformation = url.getUserInformation(); + if (userInformation != null && userInformation.length() > 0) { + builder = builder.authorization("digest", userInformation.getBytes()); + } + client = builder.build(); client.start(); } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java index 3e6669464..886c5b6de 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java @@ -98,7 +98,12 @@ public void notify(List urls) { for (URL url : urls) { String category = url.getUrlParam().getParameter(Constants.CATEGORY_KEY); if (category == null) { - category = Constants.PROVIDERS_CATEGORY; + // Assign an initial value to category according to the information in url + if (Constants.CONSUMER_SIDE.equals(url.getSide()) || Constants.CONSUMER_PROTOCOL.equals(url.getProtocol())) { + category = Constants.CONSUMERS_CATEGORY; + } else { + category = Constants.PROVIDERS_CATEGORY; + } } // NOTE: group and version in empty protocol is * if (Constants.EMPTY_PROTOCOL.equalsIgnoreCase(url.getProtocol())) { diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java index 0d0f2e595..83950269d 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java @@ -24,6 +24,8 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier; + +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.HashMap; @@ -33,15 +35,22 @@ @Component public class ConsumerServiceImpl extends AbstractService implements ConsumerService { + @Autowired + private InstanceRegistryQueryHelper instanceRegistryQueryHelper; + @Override public List findByService(String service) { - return SyncUtils.url2ConsumerList(findConsumerUrlByService(service)); + List consumers = SyncUtils.url2ConsumerList(findConsumerUrlByService(service)); + consumers.addAll(instanceRegistryQueryHelper.findConsumerByService(service)); + return consumers; } @Override public List findAll() { - return SyncUtils.url2ConsumerList(findAllConsumerUrl()); + List consumers = SyncUtils.url2ConsumerList(findAllConsumerUrl()); + consumers.addAll(instanceRegistryQueryHelper.findAllConsumer()); + return consumers; } @Override diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryCache.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryCache.java index 9f1b5acaa..520f0db8f 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryCache.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryCache.java @@ -17,16 +17,29 @@ package org.apache.dubbo.admin.service.impl; +import org.apache.dubbo.admin.common.util.Constants; import org.apache.dubbo.admin.service.RegistryCache; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.NamedThreadFactory; +import org.apache.dubbo.metadata.MetadataService; import org.apache.dubbo.registry.client.InstanceAddressURL; +import org.apache.dubbo.registry.client.metadata.MetadataUtils; +import org.apache.dubbo.rpc.service.Destroyable; import org.springframework.stereotype.Component; +import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Function; +import java.util.stream.Collectors; /** * instance registry url {@link InstanceAddressURL} cache @@ -37,6 +50,10 @@ public class InstanceRegistryCache implements RegistryCache>>> registryCache = new ConcurrentHashMap<>(); + private final Map>> subscribedCache = new ConcurrentHashMap<>(); + + private final AtomicBoolean startRefresh = new AtomicBoolean(false); + @Override public void put(String key, ConcurrentMap>> value) { registryCache.put(key, value); @@ -52,4 +69,44 @@ public ConcurrentMap>> computeIfAbs Function>>> mappingFunction) { return registryCache.computeIfAbsent(key, mappingFunction); } + + public Map>> getSubscribedCache() { + return subscribedCache; + } + + public synchronized void refreshConsumer(boolean refreshAll) { + if (startRefresh.compareAndSet(false, true)) { + ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new NamedThreadFactory("Consumer-Refresh")); + executorService.scheduleAtFixedRate(() -> refreshConsumer(true), 60, 60, TimeUnit.MINUTES); + } + + Map>> origin; + + if (refreshAll) { + origin = new ConcurrentHashMap<>(); + } else { + origin = subscribedCache; + } + + Map> providers = get(Constants.PROVIDERS_CATEGORY).values().stream() + .flatMap((e) -> e.values().stream()) + .flatMap(Collection::stream) + .collect(Collectors.groupingBy(InstanceAddressURL::getAddress)); + + // remove cached + origin.keySet().forEach(providers::remove); + + for (List instanceAddressURLs : providers.values()) { + MetadataService metadataService = MetadataUtils.referProxy(instanceAddressURLs.get(0).getInstance()); + try { + Set subscribedURLs = metadataService.getSubscribedURLs(); + + Map> subscribed = subscribedURLs.stream().map(URL::valueOf).collect(Collectors.groupingBy(URL::getServiceKey)); + origin.put(instanceAddressURLs.get(0).getAddress(), subscribed); + } catch (Throwable ignored) { + + } + ((Destroyable) metadataService).$destroy(); + } + } } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryQueryHelper.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryQueryHelper.java index aae6e6579..c6d075d1e 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryQueryHelper.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryQueryHelper.java @@ -18,17 +18,25 @@ package org.apache.dubbo.admin.service.impl; import org.apache.dubbo.admin.common.util.Constants; +import org.apache.dubbo.admin.common.util.Pair; +import org.apache.dubbo.admin.common.util.SyncUtils; +import org.apache.dubbo.admin.model.domain.Consumer; import org.apache.dubbo.admin.model.domain.Provider; import org.apache.dubbo.admin.model.domain.RegistrySource; +import org.apache.dubbo.common.URLBuilder; +import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.common.url.component.ServiceConfigURL; import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.metadata.MetadataInfo; import org.apache.dubbo.registry.client.InstanceAddressURL; import org.apache.dubbo.registry.client.ServiceInstance; +import org.apache.dubbo.rpc.RpcContext; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import org.springframework.stereotype.Component; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; @@ -85,6 +93,23 @@ public List findByService(String serviceName) { .collect(Collectors.toList()); } + public List findAllConsumer() { + return instanceRegistryCache.getSubscribedCache().values().stream() + .flatMap(m -> m.values().stream()) + .flatMap(Collection::stream) + .map(m -> new Pair<>(m.toFullString(), m)) + .map(SyncUtils::url2Consumer) + .collect(Collectors.toList()); + } + + public List findConsumerByService(String serviceName) { + return instanceRegistryCache.getSubscribedCache().values().stream().filter(m -> m.containsKey(serviceName)) + .flatMap(m -> m.get(serviceName).stream()) + .map(m -> new Pair<>(m.toFullString(), m)) + .map(SyncUtils::url2Consumer) + .collect(Collectors.toList()); + } + public List findByAddress(String providerAddress) { ConcurrentMap>> appInterfaceMap = instanceRegistryCache.get(Constants.PROVIDERS_CATEGORY); if (appInterfaceMap == null) { @@ -136,18 +161,31 @@ private List urlsToProviderList(List urls) { MetadataInfo metadataInfo = url.getMetadataInfo(); metadataInfo.getServices().forEach((serviceKey, serviceInfo) -> { + // build consumer url + + ServiceConfigURL consumerUrl = new URLBuilder() + .setProtocol(serviceInfo.getProtocol()) + .setPath(serviceInfo.getPath()) + .addParameter("group", serviceInfo.getGroup()) + .addParameter("version", serviceInfo.getVersion()) + .build(); + RpcContext.getServiceContext().setConsumerUrl(consumerUrl); Provider p = new Provider(); String service = serviceInfo.getServiceKey(); p.setService(service); p.setAddress(url.getAddress()); p.setApplication(instance.getServiceName()); - p.setUrl(url.toParameterString()); + p.setUrl(url.toFullString()); p.setDynamic(url.getParameter("dynamic", true)); p.setEnabled(url.getParameter(Constants.ENABLED_KEY, true)); + p.setSerialization(url.getParameter(org.apache.dubbo.remoting.Constants.SERIALIZATION_KEY, "hessian2")); + p.setTimeout(url.getParameter(CommonConstants.TIMEOUT_KEY, CommonConstants.DEFAULT_TIMEOUT)); p.setWeight(url.getParameter(Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT)); p.setUsername(url.getParameter("owner")); p.setRegistrySource(RegistrySource.INSTANCE); providers.add(p); + + RpcContext.getServiceContext().setConsumerUrl(null); }); }); return providers; diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java index 1defce765..5e09ed763 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java @@ -21,10 +21,12 @@ import org.apache.dubbo.admin.common.util.SyncUtils; import org.apache.dubbo.admin.common.util.Tool; import org.apache.dubbo.admin.model.domain.Provider; +import org.apache.dubbo.admin.model.domain.RegistrySource; import org.apache.dubbo.admin.model.dto.ServiceDTO; import org.apache.dubbo.admin.service.ProviderService; import org.apache.dubbo.common.URL; import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier; + import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -292,19 +294,40 @@ public Set getServiceDTOS(String pattern, String filter, String env) */ public Set convertProviders2DTO(List providers) { Set result = new TreeSet<>(); - for (Provider provider : providers) { - String app = provider.getApplication(); - String service = provider.getService(); + Map> providerMap = providers.stream().collect(Collectors.groupingBy(Provider::getService)); + for (Map.Entry> entry : providerMap.entrySet()) { + String service = entry.getKey(); String group = Tool.getGroup(service); String version = Tool.getVersion(service); String interfaze = Tool.getInterface(service); - ServiceDTO s = new ServiceDTO(); - s.setAppName(app); - s.setService(interfaze); - s.setGroup(group); - s.setVersion(version); - s.setRegistrySource(provider.getRegistrySource()); - result.add(s); + + List value = entry.getValue(); + if (value.size() == 1) { + Provider provider = value.get(0); + ServiceDTO s = new ServiceDTO(); + s.setAppName(provider.getApplication()); + s.setService(interfaze); + s.setGroup(group); + s.setVersion(version); + s.setRegistrySource(provider.getRegistrySource()); + result.add(s); + } else { + String app = value.stream().map(Provider::getApplication).distinct().collect(Collectors.joining(", ")); + RegistrySource registrySource = value.get(0).getRegistrySource(); + + boolean matchInterface = value.stream().map(Provider::getRegistrySource).anyMatch(e -> e.equals(RegistrySource.INTERFACE)); + boolean matchInstance = value.stream().map(Provider::getRegistrySource).anyMatch(e -> e.equals(RegistrySource.INSTANCE)); + if (matchInterface && matchInstance) { + registrySource = RegistrySource.ALL; + } + ServiceDTO s = new ServiceDTO(); + s.setAppName(app); + s.setService(interfaze); + s.setGroup(group); + s.setVersion(version); + s.setRegistrySource(registrySource); + result.add(s); + } } return result; } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java index 4856a5fc5..e15375e36 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java @@ -77,6 +77,7 @@ public void updateConditionRoute(ConditionRouteDTO newConditionRoute) { //for 2.6 if (StringUtils.isNotEmpty(newConditionRoute.getService())) { for (Route old : convertRouteToOldRoute(oldConditionRoute)) { + old.setService(id); registry.unregister(old.toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true)); } for (Route updated : convertRouteToOldRoute(newConditionRoute)) { @@ -101,6 +102,7 @@ public void deleteConditionRoute(String id) { RoutingRule originRule = YamlParser.loadObject(config, RoutingRule.class); ConditionRouteDTO conditionRouteDTO = RouteUtils.createConditionRouteFromRule(originRule); for (Route old : convertRouteToOldRoute(conditionRouteDTO)) { + old.setService(id); URL oldUrl = old.toUrl(); if(oldUrl.getParameter("rule").contains("host") && oldUrl.getParameter("rule").contains("false")) { registry.unregister(oldUrl); diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/utils/ApiDocsDubboGenericUtil.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/utils/ApiDocsDubboGenericUtil.java index 12b54afd2..896749f79 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/utils/ApiDocsDubboGenericUtil.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/utils/ApiDocsDubboGenericUtil.java @@ -121,6 +121,8 @@ private static ReferenceConfig getReferenceConfig(String address referenceConfig.setTimeout(timeout); referenceConfig.setVersion(version); referenceConfig.setGroup(group); + //Keep it consistent with the ConfigManager cache + referenceConfig.setSticky(false); referenceConfig.setApplication(application); if (address.startsWith("dubbo")) { diff --git a/dubbo-admin-server/src/main/resources/application.properties b/dubbo-admin-server/src/main/resources/application.properties index 4aa924b22..232b05ed9 100644 --- a/dubbo-admin-server/src/main/resources/application.properties +++ b/dubbo-admin-server/src/main/resources/application.properties @@ -73,7 +73,7 @@ dubbo.registry.address=${admin.registry.address} #spring.datasource.password=mysql # h2 -spring.datasource.url=jdbc:h2:mem:~/dubbo-admin; +spring.datasource.url=jdbc:h2:mem:~/dubbo-admin;MODE=MYSQL; spring.datasource.username=sa spring.datasource.password= diff --git a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/common/util/UrlUtilsTest.java b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/common/util/UrlUtilsTest.java index 6d74e9a22..bdba1e841 100644 --- a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/common/util/UrlUtilsTest.java +++ b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/common/util/UrlUtilsTest.java @@ -19,14 +19,14 @@ import org.junit.Assert; import org.junit.Test; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; public class UrlUtilsTest { @Test public void testParamsMapToString() { - Map params = new HashMap<>(); + Map params = new LinkedHashMap<>(); params.put("a", new String[]{"1", "2", "3"}); params.put("b", new String[]{"8", "7", "6"}); String result = UrlUtils.paramsMapToString(params); diff --git a/dubbo-admin-ui/public/dubbo-admin-info.json b/dubbo-admin-ui/public/dubbo-admin-info.json index dfcc3af19..156772da8 100644 --- a/dubbo-admin-ui/public/dubbo-admin-info.json +++ b/dubbo-admin-ui/public/dubbo-admin-info.json @@ -1,3 +1,3 @@ { - "version": "0.3.0" + "version": "0.5.0" } diff --git a/dubbo-admin-ui/public/index.html b/dubbo-admin-ui/public/index.html index 63dadb18f..01be2e7b4 100644 --- a/dubbo-admin-ui/public/index.html +++ b/dubbo-admin-ui/public/index.html @@ -23,7 +23,7 @@ Dubbo Admin - +
diff --git a/dubbo-admin-ui/src/components/ServiceDetail.vue b/dubbo-admin-ui/src/components/ServiceDetail.vue index 79fa779f8..554e5bab3 100644 --- a/dubbo-admin-ui/src/components/ServiceDetail.vue +++ b/dubbo-admin-ui/src/components/ServiceDetail.vue @@ -55,8 +55,8 @@ {{getIp(props.item.address)}} {{getPort(props.item.address)}} {{props.item.registrySource}} - - + {{props.item.timeout}} + {{props.item.serialization}} {{props.item.weight}} @@ -84,7 +84,6 @@ > @@ -177,7 +176,7 @@ }, { text: this.$t('serialization'), - value: 'serial' + value: 'serialization' }, { text: this.$t('weight'), @@ -194,10 +193,6 @@ text: this.$t('ip'), value: 'ip' }, - { - text: this.$t('port'), - value: 'port' - }, { text: this.$t('appName'), value: 'appName' @@ -211,6 +206,7 @@ this.providerDetails = response.data.providers const instanceRegistry = this.$t('instanceRegistry') const interfaceRegistry = this.$t('interfaceRegistry') + const allRegistry = this.$t('allRegistry') for (let i = 0; i < this.providerDetails.length; i++) { if (this.providerDetails[i].registrySource === 'INSTANCE') { this.providerDetails[i].registrySource = instanceRegistry @@ -218,6 +214,9 @@ if (this.providerDetails[i].registrySource === 'INTERFACE') { this.providerDetails[i].registrySource = interfaceRegistry } + if (this.providerDetails[i].registrySource === 'ALL') { + this.providerDetails[i].registrySource = allRegistry + } console.log(this.providerDetails[i]) this.$set(this.providerDetails[i], 'hint', 'url') } @@ -228,10 +227,10 @@ }) }, getIp: function (address) { - return address.split(':')[0] + return address != null ? address.split(':')[0] : null }, getPort: function (address) { - return address.split(':')[1] + return address != null && address.split(':').length >= 2 ? address.split(':')[1] : null }, toCopyText (text) { this.$copyText(text).then(() => { diff --git a/dubbo-admin-ui/src/components/ServiceSearch.vue b/dubbo-admin-ui/src/components/ServiceSearch.vue index c5ce4fbe2..4627fbd41 100644 --- a/dubbo-admin-ui/src/components/ServiceSearch.vue +++ b/dubbo-admin-ui/src/components/ServiceSearch.vue @@ -201,6 +201,7 @@ export default { } const instanceRegistry = this.$t('instanceRegistry') const interfaceRegistry = this.$t('interfaceRegistry') + const allRegistry = this.$t('allRegistry') return this.resultPage.content.filter(function (item) { if (item.registrySource === 'INSTANCE') { item.registrySource = instanceRegistry @@ -208,6 +209,9 @@ export default { if (item.registrySource === 'INTERFACE') { item.registrySource = interfaceRegistry } + if (item.registrySource === 'ALL') { + item.registrySource = allRegistry + } return item }) } diff --git a/dubbo-admin-ui/src/components/public/Footers.vue b/dubbo-admin-ui/src/components/public/Footers.vue index 6ad8ae61c..08e4016a5 100644 --- a/dubbo-admin-ui/src/components/public/Footers.vue +++ b/dubbo-admin-ui/src/components/public/Footers.vue @@ -18,7 +18,7 @@