Compare commits
10 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
fce97fdc8a | |
|
|
54a6cdf119 | |
|
|
35f00f0395 | |
|
|
62df60a046 | |
|
|
9867be1422 | |
|
|
ce3b0e285a | |
|
|
5c895d4995 | |
|
|
c7974d0ae7 | |
|
|
c148bddd3a | |
|
|
a1bfac1001 |
117
.artifacts
117
.artifacts
|
|
@ -1,117 +0,0 @@
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
|
|
||||||
# Please add new modules to the end of the list.
|
|
||||||
|
|
||||||
dubbo
|
|
||||||
dubbo-auth
|
|
||||||
dubbo-apache-release
|
|
||||||
dubbo-bom
|
|
||||||
dubbo-build-tools
|
|
||||||
dubbo-cluster
|
|
||||||
dubbo-common
|
|
||||||
dubbo-compatible
|
|
||||||
dubbo-compiler
|
|
||||||
dubbo-config
|
|
||||||
dubbo-config-api
|
|
||||||
dubbo-config-spring
|
|
||||||
dubbo-configcenter
|
|
||||||
dubbo-configcenter-apollo
|
|
||||||
dubbo-configcenter-nacos
|
|
||||||
dubbo-configcenter-zookeeper
|
|
||||||
dubbo-container
|
|
||||||
dubbo-container-api
|
|
||||||
dubbo-container-spring
|
|
||||||
dubbo-core-spi
|
|
||||||
dubbo-dependencies
|
|
||||||
dubbo-dependencies-all
|
|
||||||
dubbo-dependencies-bom
|
|
||||||
dubbo-dependencies-zookeeper
|
|
||||||
dubbo-dependencies-zookeeper-curator5
|
|
||||||
dubbo-distribution
|
|
||||||
dubbo-filter
|
|
||||||
dubbo-filter-cache
|
|
||||||
dubbo-filter-validation
|
|
||||||
dubbo-kubernetes
|
|
||||||
dubbo-maven-plugin
|
|
||||||
dubbo-metadata
|
|
||||||
dubbo-metadata-api
|
|
||||||
dubbo-metadata-definition-protobuf
|
|
||||||
dubbo-metadata-processor
|
|
||||||
dubbo-metadata-report-nacos
|
|
||||||
dubbo-metadata-report-redis
|
|
||||||
dubbo-metadata-report-zookeeper
|
|
||||||
dubbo-metrics
|
|
||||||
dubbo-metrics-api
|
|
||||||
dubbo-metrics-default
|
|
||||||
dubbo-metrics-metadata
|
|
||||||
dubbo-metrics-prometheus
|
|
||||||
dubbo-metrics-registry
|
|
||||||
dubbo-metrics-config-center
|
|
||||||
dubbo-monitor
|
|
||||||
dubbo-monitor-api
|
|
||||||
dubbo-monitor-default
|
|
||||||
dubbo-native
|
|
||||||
dubbo-native-plugin
|
|
||||||
dubbo-parent
|
|
||||||
dubbo-plugin
|
|
||||||
dubbo-qos
|
|
||||||
dubbo-qos-api
|
|
||||||
dubbo-reactive
|
|
||||||
dubbo-registry
|
|
||||||
dubbo-registry-api
|
|
||||||
dubbo-registry-multicast
|
|
||||||
dubbo-registry-multiple
|
|
||||||
dubbo-registry-nacos
|
|
||||||
dubbo-registry-zookeeper
|
|
||||||
dubbo-remoting
|
|
||||||
dubbo-remoting-api
|
|
||||||
dubbo-remoting-http
|
|
||||||
dubbo-remoting-netty
|
|
||||||
dubbo-remoting-netty4
|
|
||||||
dubbo-remoting-zookeeper
|
|
||||||
dubbo-remoting-zookeeper-curator5
|
|
||||||
dubbo-rpc
|
|
||||||
dubbo-rpc-api
|
|
||||||
dubbo-rpc-dubbo
|
|
||||||
dubbo-rpc-injvm
|
|
||||||
dubbo-rpc-rest
|
|
||||||
dubbo-rpc-triple
|
|
||||||
dubbo-security
|
|
||||||
dubbo-serialization
|
|
||||||
dubbo-serialization-api
|
|
||||||
dubbo-serialization-fastjson2
|
|
||||||
dubbo-serialization-hessian2
|
|
||||||
dubbo-serialization-jdk
|
|
||||||
dubbo-spring-boot
|
|
||||||
dubbo-spring-boot-actuator
|
|
||||||
dubbo-spring-boot-actuator-compatible
|
|
||||||
dubbo-spring-boot-autoconfigure
|
|
||||||
dubbo-spring-boot-autoconfigure-compatible
|
|
||||||
dubbo-spring-boot-compatible
|
|
||||||
dubbo-spring-boot-observability-starters
|
|
||||||
dubbo-spring-boot-observability-autoconfigure
|
|
||||||
dubbo-spring-boot-tracing-brave-zipkin-starter
|
|
||||||
dubbo-spring-boot-tracing-otel-zipkin-starter
|
|
||||||
dubbo-spring-boot-tracing-otel-otlp-starter
|
|
||||||
dubbo-spring-boot-observability-starter
|
|
||||||
dubbo-spring-boot-starter
|
|
||||||
dubbo-spring-boot-starters
|
|
||||||
dubbo-nacos-spring-boot-starter
|
|
||||||
dubbo-zookeeper-spring-boot-starter
|
|
||||||
dubbo-zookeeper-curator5-spring-boot-starter
|
|
||||||
dubbo-spring-security
|
|
||||||
dubbo-xds
|
|
||||||
15
.asf.yaml
15
.asf.yaml
|
|
@ -25,7 +25,6 @@ notifications:
|
||||||
|
|
||||||
github:
|
github:
|
||||||
homepage: https://dubbo.apache.org/
|
homepage: https://dubbo.apache.org/
|
||||||
description: "The java implementation of Apache Dubbo. An RPC and microservice framework."
|
|
||||||
features:
|
features:
|
||||||
# Enable wiki for documentation
|
# Enable wiki for documentation
|
||||||
wiki: true
|
wiki: true
|
||||||
|
|
@ -43,17 +42,3 @@ github:
|
||||||
3.1:
|
3.1:
|
||||||
# only disable force push
|
# only disable force push
|
||||||
foo: bar
|
foo: bar
|
||||||
labels:
|
|
||||||
- java
|
|
||||||
- rpc
|
|
||||||
- microservices
|
|
||||||
- framework
|
|
||||||
- restful
|
|
||||||
- distributed-systems
|
|
||||||
- dubbo
|
|
||||||
- service-mesh
|
|
||||||
- http
|
|
||||||
- grpc
|
|
||||||
- web
|
|
||||||
collaborators:
|
|
||||||
- oxsean
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
coverage:
|
||||||
|
status:
|
||||||
|
# pull-requests only
|
||||||
|
patch:
|
||||||
|
default:
|
||||||
|
threshold: 0.1%
|
||||||
|
ignore:
|
||||||
|
- "dubbo-demo/.*"
|
||||||
|
- "dubbo-common/src/main/java/org/apache/dubbo/common/json/*.java" # internal JSON impl is deprecate, ignore test coverage for them
|
||||||
|
- "dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/AnnotationBean.java" # Deprecated
|
||||||
|
- "dubbo-rpc/dubbo-rpc-thrift/.*"
|
||||||
|
|
@ -19,55 +19,13 @@
|
||||||
# top-most EditorConfig file
|
# top-most EditorConfig file
|
||||||
root = true
|
root = true
|
||||||
|
|
||||||
|
# Unix-style newlines with a newline ending every file
|
||||||
[*]
|
[*]
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
indent_size = 4
|
|
||||||
indent_style = space
|
|
||||||
tab_width = 4
|
|
||||||
max_line_length = 120
|
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
trim_trailing_whitespace = true
|
|
||||||
|
|
||||||
[*.java]
|
# 4 space indentation
|
||||||
ij_java_continuation_indent_size = 8
|
[*.{java,xml}]
|
||||||
ij_java_keep_control_statement_in_one_line = false
|
indent_style = space
|
||||||
ij_java_for_brace_force = always
|
indent_size = 4
|
||||||
ij_java_if_brace_force = always
|
|
||||||
ij_java_keep_first_column_comment = false
|
|
||||||
ij_java_keep_line_breaks = false
|
|
||||||
ij_java_keep_simple_blocks_in_one_line = true
|
|
||||||
ij_java_keep_simple_classes_in_one_line = true
|
|
||||||
ij_java_keep_simple_lambdas_in_one_line = true
|
|
||||||
ij_java_keep_simple_methods_in_one_line = true
|
|
||||||
ij_java_keep_blank_lines_in_code = 1
|
|
||||||
ij_java_keep_blank_lines_in_declarations = 1
|
|
||||||
ij_java_class_count_to_use_import_on_demand = 999
|
|
||||||
ij_java_names_count_to_use_import_on_demand = 999
|
|
||||||
ij_java_imports_layout = org.apache.dubbo.**, |, javax.**, |, java.**, |, *, |, $*
|
|
||||||
ij_java_insert_inner_class_imports = true
|
|
||||||
ij_java_space_before_array_initializer_left_brace = true
|
|
||||||
ij_java_method_parameters_new_line_after_left_paren = true
|
|
||||||
ij_java_wrap_comments = true
|
|
||||||
ij_java_wrap_long_lines = true
|
|
||||||
ij_java_enum_constants_wrap = split_into_lines
|
|
||||||
ij_java_method_call_chain_wrap = split_into_lines
|
|
||||||
ij_java_method_parameters_wrap = on_every_item
|
|
||||||
ij_java_extends_list_wrap = on_every_item
|
|
||||||
ij_java_extends_keyword_wrap = normal
|
|
||||||
ij_java_binary_operation_wrap = normal
|
|
||||||
ij_java_binary_operation_sign_on_next_line = true
|
|
||||||
|
|
||||||
[*.json]
|
|
||||||
tab_width = 2
|
|
||||||
|
|
||||||
[*.{yml,yaml}]
|
|
||||||
indent_size = 2
|
|
||||||
|
|
||||||
[*.xml]
|
|
||||||
ij_xml_attribute_wrap = off
|
|
||||||
ij_xml_text_wrap = off
|
|
||||||
ij_xml_keep_blank_lines = 1
|
|
||||||
|
|
||||||
[pom.xml]
|
|
||||||
indent_size = 2
|
|
||||||
|
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
|
|
||||||
title: "[General][Java SDK (Component)] xxx"
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
<img src="https://dubbo.apache.org/imgs/nav_logo2.png" alt="Dubbo logo" height="90px" align="right" />
|
|
||||||
|
|
||||||
Thank you for finding the time to share your idea! We really appreciate the community efforts to improve Dubbo.
|
|
||||||
|
|
||||||
If you need to report a security issue, please visit [our security policy](https://github.com/apache/dubbo/security/policy).
|
|
||||||
|
|
||||||
**Dubbo is open for world wide collaboration, please make sure that all the content you provide is in English.**
|
|
||||||
Remember that non-English idea is quite not friendly for everyone, and might unable to get the response!
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Pre-check
|
|
||||||
options:
|
|
||||||
- label: >
|
|
||||||
I am sure that all the content I provide is in English.
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
attributes:
|
|
||||||
label: Apache Dubbo Component
|
|
||||||
description: |
|
|
||||||
What Apache Dubbo component are you using? Apache Dubbo has many subprojects, please make sure
|
|
||||||
to choose the component that you want to ask questions about.
|
|
||||||
multiple: false
|
|
||||||
options:
|
|
||||||
- "Java SDK (apache/dubbo)"
|
|
||||||
- "Java Samples (apache/dubbo-samples)"
|
|
||||||
- "Java Integration Cases (apache/dubbo-integration-cases)"
|
|
||||||
- "Java SPI Extensions (apache/dubbo-spi-extensions)"
|
|
||||||
- "Java Benchmark (apache/dubbo-benchmark)"
|
|
||||||
- "Go SDK (apache/dubbo-go)"
|
|
||||||
- "Go Samples (apache/dubbo-go-samples)"
|
|
||||||
- "Rust SDK (apache/dubbo-rust)"
|
|
||||||
- "Node.js SDK (apache/dubbo-js)"
|
|
||||||
- "Python SDK (apache/dubbo-python)"
|
|
||||||
- "Kubernetes Integration (apache/dubbo-kubernetes)"
|
|
||||||
- "Pixiu Gateway (apache/dubbo-go-pixiu)"
|
|
||||||
- "Pixiu Gateway Samples (apache/dubbo-go-pixiu-samples)"
|
|
||||||
- "Admin (apache/dubbo-admin)"
|
|
||||||
- "Website (apache/dubbo-website)"
|
|
||||||
- "Awesome (apache/dubbo-awesome)"
|
|
||||||
- "Initializer (apache/dubbo-intializer)"
|
|
||||||
- "Others (apache/dubbo-xxx)"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Details
|
|
||||||
description: Anything you want to ask?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Code of Conduct
|
|
||||||
description: The Code of Conduct helps create a safe space for everyone. We require that everyone agrees to it.
|
|
||||||
options:
|
|
||||||
- label: >
|
|
||||||
I agree to follow this project's
|
|
||||||
[Code of Conduct](https://www.apache.org/foundation/policies/conduct)
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: "Thanks for completing our form!"
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
|
|
||||||
title: "[Q/A][Java SDK (Component)] xxx"
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
<img src="https://dubbo.apache.org/imgs/nav_logo2.png" alt="Dubbo logo" height="90px" align="right" />
|
|
||||||
|
|
||||||
Thank you for finding the time to report the question! We really appreciate the community efforts to improve Dubbo.
|
|
||||||
|
|
||||||
If you need to report a security issue, please visit [our security policy](https://github.com/apache/dubbo/security/policy).
|
|
||||||
|
|
||||||
**Dubbo is open for world wide collaboration, please make sure that all the content you provide is in English.**
|
|
||||||
Remember that non-English question is quite not friendly for everyone, and might unable to get the response!
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Pre-check
|
|
||||||
options:
|
|
||||||
- label: >
|
|
||||||
I am sure that all the content I provide is in English.
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
attributes:
|
|
||||||
label: Apache Dubbo Component
|
|
||||||
description: |
|
|
||||||
What Apache Dubbo component are you using? Apache Dubbo has many subprojects, please make sure
|
|
||||||
to choose the component that you want to ask questions about.
|
|
||||||
multiple: false
|
|
||||||
options:
|
|
||||||
- "Java SDK (apache/dubbo)"
|
|
||||||
- "Java Samples (apache/dubbo-samples)"
|
|
||||||
- "Java Integration Cases (apache/dubbo-integration-cases)"
|
|
||||||
- "Java SPI Extensions (apache/dubbo-spi-extensions)"
|
|
||||||
- "Java Benchmark (apache/dubbo-benchmark)"
|
|
||||||
- "Go SDK (apache/dubbo-go)"
|
|
||||||
- "Go Samples (apache/dubbo-go-samples)"
|
|
||||||
- "Rust SDK (apache/dubbo-rust)"
|
|
||||||
- "Node.js SDK (apache/dubbo-js)"
|
|
||||||
- "Python SDK (apache/dubbo-python)"
|
|
||||||
- "Kubernetes Integration (apache/dubbo-kubernetes)"
|
|
||||||
- "Pixiu Gateway (apache/dubbo-go-pixiu)"
|
|
||||||
- "Pixiu Gateway Samples (apache/dubbo-go-pixiu-samples)"
|
|
||||||
- "Admin (apache/dubbo-admin)"
|
|
||||||
- "Website (apache/dubbo-website)"
|
|
||||||
- "Awesome (apache/dubbo-awesome)"
|
|
||||||
- "Initializer (apache/dubbo-intializer)"
|
|
||||||
- "Others (apache/dubbo-xxx)"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Details
|
|
||||||
description: Anything you want to know?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Code of Conduct
|
|
||||||
description: The Code of Conduct helps create a safe space for everyone. We require that everyone agrees to it.
|
|
||||||
options:
|
|
||||||
- label: >
|
|
||||||
I agree to follow this project's
|
|
||||||
[Code of Conduct](https://www.apache.org/foundation/policies/conduct)
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: "Thanks for completing our form!"
|
|
||||||
|
|
@ -1,142 +0,0 @@
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
|
|
||||||
name: Bug Report
|
|
||||||
description: File a bug report
|
|
||||||
title: "[Bug] "
|
|
||||||
labels: ["type/need-triage", "component/need-triage"]
|
|
||||||
projects: ["apache/337"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
<img src="https://dubbo.apache.org/imgs/nav_logo2.png" alt="Dubbo logo" height="90px" align="right" />
|
|
||||||
|
|
||||||
Thank you for finding the time to report the problem! We really appreciate the community efforts to improve Dubbo.
|
|
||||||
|
|
||||||
Please make sure what you are reporting is indeed a bug with reproducible steps, if you want to ask questions
|
|
||||||
or share ideas, please [subscribe to our mailing list](mailto:dev-subscribe@dubbo.apache.org) and sent
|
|
||||||
emails to [our mailing list](mailto:dev@dubbo.apache.org), you can also head to our
|
|
||||||
[Discussion](https://github.com/apache/dubbo/discussions) tab.
|
|
||||||
|
|
||||||
If you need to report a security issue, please visit [our security policy](https://github.com/apache/dubbo/security/policy).
|
|
||||||
|
|
||||||
**Dubbo is open for world wide collaboration, please make sure that all the content you provide is in English.**
|
|
||||||
Remember that non-English issues is quite not friendly for everyone, and might unable to get the response!
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Pre-check
|
|
||||||
options:
|
|
||||||
- label: >
|
|
||||||
I am sure that all the content I provide is in English.
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Search before asking
|
|
||||||
description: >
|
|
||||||
Please make sure to search in the [issues](https://github.com/apache/dubbo/issues?q=is%3Aissue) first to see
|
|
||||||
whether the same issue was reported already.
|
|
||||||
options:
|
|
||||||
- label: >
|
|
||||||
I had searched in the [issues](https://github.com/apache/dubbo/issues?q=is%3Aissue) and found no similar
|
|
||||||
issues.
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
attributes:
|
|
||||||
label: Apache Dubbo Component
|
|
||||||
description: |
|
|
||||||
What Apache Dubbo component are you using? Apache Dubbo has many subprojects, please make sure
|
|
||||||
to choose the component that you want to ask questions about.
|
|
||||||
multiple: false
|
|
||||||
options:
|
|
||||||
- "Java SDK (apache/dubbo)"
|
|
||||||
- "Java Samples (apache/dubbo-samples)"
|
|
||||||
- "Java Integration Cases (apache/dubbo-integration-cases)"
|
|
||||||
- "Java SPI Extensions (apache/dubbo-spi-extensions)"
|
|
||||||
- "Java Benchmark (apache/dubbo-benchmark)"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Dubbo Version
|
|
||||||
description: "Which Dubbo version, JDK version and operating system did you use?"
|
|
||||||
placeholder: "Example: Dubbo Java 3.2.12, OpenJDK 1.8, Ubuntu 20.04"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Steps to reproduce this issue
|
|
||||||
description: >
|
|
||||||
Describe how to reproduce this issue.If you are not able to provide a reproducible case,
|
|
||||||
please open a [Discussion](https://github.com/apache/dubbo/discussions) instead.
|
|
||||||
placeholder: >
|
|
||||||
Please provide the context in which the problem occurred and explain what happened.
|
|
||||||
A [GitHub address] would be helpful for maintainers to reproduce the problem.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: What you expected to happen
|
|
||||||
description: What do you think went wrong?
|
|
||||||
placeholder: >
|
|
||||||
Please explain why you think the behaviour is erroneous. It is extremely helpful if you copy and paste
|
|
||||||
the fragment of logs showing the exact error messages or wrong behaviour and screenshots for
|
|
||||||
UI problems. You can include files by dragging and dropping them here.
|
|
||||||
|
|
||||||
**NOTE**: please copy and paste texts instead of taking screenshots of them for easy future search.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Anything else
|
|
||||||
description: Anything else we need to know?
|
|
||||||
placeholder: >
|
|
||||||
How often does this problem occur? (Once? Every time? Only when certain conditions are met?)
|
|
||||||
Any relevant logs to include? Put them here inside fenced
|
|
||||||
``` ``` blocks or inside a collapsable details tag if it's too long:
|
|
||||||
<details><summary>x.log</summary> lots of stuff </details>
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Are you willing to submit a pull request to fix on your own?
|
|
||||||
description: >
|
|
||||||
This is absolutely not required, but we are happy to guide you in the contribution process
|
|
||||||
especially if you already have a good understanding of how to implement the fix.
|
|
||||||
Dubbo is a totally community-driven project and we love to bring new contributors in.
|
|
||||||
options:
|
|
||||||
- label: Yes I am willing to submit a pull request on my own!
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Code of Conduct
|
|
||||||
description: The Code of Conduct helps create a safe space for everyone. We require that everyone agrees to it.
|
|
||||||
options:
|
|
||||||
- label: >
|
|
||||||
I agree to follow this project's
|
|
||||||
[Code of Conduct](https://www.apache.org/foundation/policies/conduct)
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: "Thanks for completing our form!"
|
|
||||||
|
|
@ -1,106 +0,0 @@
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
|
|
||||||
name: Feature Request
|
|
||||||
description: Create a Feature Request for Dubbo
|
|
||||||
title: "[Feature] "
|
|
||||||
labels: ["type/need-triage", "component/need-triage"]
|
|
||||||
projects: ["apache/337"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
<img src="https://dubbo.apache.org/imgs/nav_logo2.png" alt="Dubbo logo" height="90px" align="right" />
|
|
||||||
|
|
||||||
Thank you for finding the time to propose new feature!
|
|
||||||
|
|
||||||
We really appreciate the community efforts to improve Dubbo.
|
|
||||||
|
|
||||||
**Dubbo is open for world wide collaboration, please make sure that all the content you provide is in English.**
|
|
||||||
Remember that non-English issues is quite not friendly for everyone, and might unable to get the response!
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Pre-check
|
|
||||||
options:
|
|
||||||
- label: >
|
|
||||||
I am sure that all the content I provide is in English.
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Search before asking
|
|
||||||
description: >
|
|
||||||
Please make sure to search in the [issues](https://github.com/apache/dubbo/issues?q=is%3Aissue) first to see
|
|
||||||
whether the same feature was requested already.
|
|
||||||
options:
|
|
||||||
- label: >
|
|
||||||
I had searched in the [issues](https://github.com/apache/dubbo/issues?q=is%3Aissue) and found no similar
|
|
||||||
feature requirement.
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
attributes:
|
|
||||||
label: Apache Dubbo Component
|
|
||||||
description: |
|
|
||||||
What Apache Dubbo component are you using? Apache Dubbo has many subprojects, please make sure
|
|
||||||
to choose the component that you want to ask questions about.
|
|
||||||
multiple: false
|
|
||||||
options:
|
|
||||||
- "Java SDK (apache/dubbo)"
|
|
||||||
- "Java Samples (apache/dubbo-samples)"
|
|
||||||
- "Java Integration Cases (apache/dubbo-integration-cases)"
|
|
||||||
- "Java SPI Extensions (apache/dubbo-spi-extensions)"
|
|
||||||
- "Java Benchmark (apache/dubbo-benchmark)"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Descriptions
|
|
||||||
description: A short description of your feature
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Related issues
|
|
||||||
description: Is there currently another issue associated with this?
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Are you willing to submit a pull request to fix on your own?
|
|
||||||
description: >
|
|
||||||
This is absolutely not required, but we are happy to guide you in the contribution process
|
|
||||||
especially if you already have a good understanding of how to implement the feature.
|
|
||||||
Dubbo is a totally community-driven project and we love to bring new contributors in.
|
|
||||||
options:
|
|
||||||
- label: Yes I am willing to submit a pull request on my own!
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Code of Conduct
|
|
||||||
description: The Code of Conduct helps create a safe space for everyone. We require that everyone agrees to it.
|
|
||||||
options:
|
|
||||||
- label: >
|
|
||||||
I agree to follow this project's
|
|
||||||
[Code of Conduct](https://www.apache.org/foundation/policies/conduct)
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: "Thanks for completing our form!"
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
---
|
||||||
|
name: Bug Report
|
||||||
|
about: Report a bug in Dubbo
|
||||||
|
title: ''
|
||||||
|
labels: type/bug
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
<!-- If you need to report a security issue please visit https://github.com/apache/dubbo/security/policy -->
|
||||||
|
|
||||||
|
- [ ] I have searched the [issues](https://github.com/apache/dubbo/issues) of this repository and believe that this is not a duplicate.
|
||||||
|
|
||||||
|
### Environment
|
||||||
|
|
||||||
|
* Dubbo version: xxx
|
||||||
|
* Operating System version: xxx
|
||||||
|
* Java version: xxx
|
||||||
|
|
||||||
|
### Steps to reproduce this issue
|
||||||
|
|
||||||
|
1. xxx
|
||||||
|
2. xxx
|
||||||
|
3. xxx
|
||||||
|
|
||||||
|
Pls. provide [GitHub address] to reproduce this issue.
|
||||||
|
|
||||||
|
### Expected Behavior
|
||||||
|
|
||||||
|
<!-- What do you expect from the above steps?-->
|
||||||
|
|
||||||
|
### Actual Behavior
|
||||||
|
|
||||||
|
<!-- What actually happens? -->
|
||||||
|
|
||||||
|
If there is an exception, please attach the exception trace:
|
||||||
|
|
||||||
|
```
|
||||||
|
Just put your stack trace here!
|
||||||
|
```
|
||||||
|
|
@ -1,22 +1,8 @@
|
||||||
#
|
blank_issues_enabled: true
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
|
|
||||||
blank_issues_enabled: false
|
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: Question & FAQ & Proposal
|
- name: Dubbo Community Repo
|
||||||
url: https://github.com/apache/dubbo/discussions/
|
url: https://github.com/apache/dubbo-website
|
||||||
about: Ask a question, request support or submit a proposal for Apache Dubbo.
|
about: Please see our community docs here.
|
||||||
|
- name: Report a security issue
|
||||||
|
url: https://github.com/apache/dubbo/security/policy
|
||||||
|
about: Please report security vulnerabilities using these instructions.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
---
|
||||||
|
name: Discussion
|
||||||
|
about: Start a discussion for Dubbo
|
||||||
|
title: ''
|
||||||
|
labels: type/discussion
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- If you need to report a security issue please visit https://github.com/apache/dubbo/security/policy -->
|
||||||
|
|
||||||
|
<!-- For all design discussions please continue. -->
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
name: Feature Request
|
||||||
|
about: Create a Feature Request for Dubbo
|
||||||
|
title: ''
|
||||||
|
labels: type/feature
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
<!-- If you need to report a security issue please visit https://github.com/apache/dubbo/security/policy -->
|
||||||
|
|
||||||
|
- [ ] I have searched the [issues](https://github.com/apache/dubbo/issues) of this repository and believe that this is not a duplicate.
|
||||||
|
- [ ] I have searched the [release notes](https://github.com/apache/dubbo/releases) of this repository and believe that this is not a duplicate.
|
||||||
|
|
||||||
|
## Describe the feature
|
||||||
|
<!-- Please also discuss possible business value -->
|
||||||
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
---
|
||||||
|
name: Proposal
|
||||||
|
about: Create a technical proposal for Dubbo
|
||||||
|
title: ''
|
||||||
|
labels: type/proposal
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
<!-- If you need to report a security issue please visit https://github.com/apache/dubbo/security/policy -->
|
||||||
|
|
||||||
|
- [ ] I have searched the [issues](https://github.com/apache/dubbo/issues) of this repository and believe that this is not a duplicate.
|
||||||
|
|
||||||
|
## Describe the proposal
|
||||||
|
<!-- Please use this for a concrete design proposal for functionality. -->
|
||||||
|
<!-- If you just want to request a new feature and discuss the possible business value, create a Feature Request. -->
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
name: Question
|
||||||
|
about: Ask a question about Dubbo
|
||||||
|
title: ''
|
||||||
|
labels: type/question
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
<!-- If you need to report a security issue please visit https://github.com/apache/dubbo/security/policy -->
|
||||||
|
|
||||||
|
- [ ] I have searched the [issues](https://github.com/apache/dubbo/issues) of this repository and believe that this is not a duplicate.
|
||||||
|
|
||||||
|
## Ask your question here
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
version: 2
|
|
||||||
updates:
|
|
||||||
|
|
||||||
- package-ecosystem: "maven"
|
|
||||||
directory: "/"
|
|
||||||
open-pull-requests-limit: 20
|
|
||||||
# Ignore major version updates
|
|
||||||
ignore:
|
|
||||||
- dependency-name: "*"
|
|
||||||
update-types: ["version-update:semver-major"]
|
|
||||||
schedule:
|
|
||||||
interval: "weekly"
|
|
||||||
day: "monday"
|
|
||||||
time: "03:00"
|
|
||||||
timezone: "US/Eastern"
|
|
||||||
|
|
@ -0,0 +1,244 @@
|
||||||
|
name: Build and Test For Dubbo 3
|
||||||
|
|
||||||
|
on: [push, pull_request, workflow_dispatch]
|
||||||
|
|
||||||
|
env:
|
||||||
|
FORK_COUNT: 2
|
||||||
|
FAIL_FAST: 0
|
||||||
|
SHOW_ERROR_DETAIL: 1
|
||||||
|
#multi-version size limit
|
||||||
|
VERSIONS_LIMIT: 4
|
||||||
|
CANDIDATE_VERSIONS: '
|
||||||
|
spring.version:4.3.30.RELEASE;
|
||||||
|
spring-boot.version:1.5.22.RELEASE;
|
||||||
|
spring-boot.version:2.4.1;
|
||||||
|
'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-source:
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
outputs:
|
||||||
|
version: ${{ steps.dubbo-version.outputs.version }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
path: dubbo
|
||||||
|
- uses: actions/setup-java@v1
|
||||||
|
with:
|
||||||
|
java-version: 8
|
||||||
|
- uses: actions/cache@v2
|
||||||
|
name: "Cache local Maven repository"
|
||||||
|
with:
|
||||||
|
path: ~/.m2/repository
|
||||||
|
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||||
|
- name: "Dubbo cache"
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ~/.m2/repository/org/apache/dubbo
|
||||||
|
key: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }}
|
||||||
|
- name: "Build Dubbo with Maven"
|
||||||
|
run: |
|
||||||
|
cd ./dubbo
|
||||||
|
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean source:jar install -Pjacoco,rat,checkstyle -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -Dmaven.test.skip=true -Dmaven.test.skip.exec=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
||||||
|
- name: "Pack rat file if failure"
|
||||||
|
if: failure()
|
||||||
|
run: 7z a ${{ github.workspace }}/rat.zip *rat.txt -r
|
||||||
|
- name: "Upload rat file if failure"
|
||||||
|
if: failure()
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: "rat-file"
|
||||||
|
path: ${{ github.workspace }}/rat.zip
|
||||||
|
- name: "Pack checkstyle file if failure"
|
||||||
|
if: failure()
|
||||||
|
run: 7z a ${{ github.workspace }}/checkstyle.zip *checkstyle* -r
|
||||||
|
- name: "Upload checkstyle file if failure"
|
||||||
|
if: failure()
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: "checkstyle-file"
|
||||||
|
path: ${{ github.workspace }}/checkstyle.zip
|
||||||
|
- name: "Calculate Dubbo Version"
|
||||||
|
id: dubbo-version
|
||||||
|
run: |
|
||||||
|
REVISION=`awk '/<revision>[^<]+<\/revision>/{gsub(/<revision>|<\/revision>/,"",$1);print $1;exit;}' ./dubbo/pom.xml`
|
||||||
|
echo "::set-output name=version::$REVISION"
|
||||||
|
echo "dubbo version: $REVISION"
|
||||||
|
|
||||||
|
unit-test-prepare:
|
||||||
|
name: " Preparation for Unit Test On ${{ matrix.os }} (JDK: ${{ matrix.jdk }})"
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ ubuntu-18.04, windows-2019 ]
|
||||||
|
jdk: [ 8, 11, 17 ]
|
||||||
|
env:
|
||||||
|
DISABLE_FILE_SYSTEM_TEST: true
|
||||||
|
ZOOKEEPER_VERSION: 3.6.3
|
||||||
|
steps:
|
||||||
|
- uses: actions/cache@v2
|
||||||
|
name: "Cache zookeeper binary archive"
|
||||||
|
id: "cache-zookeeper"
|
||||||
|
with:
|
||||||
|
path: ${{ github.workspace }}/.tmp/zookeeper
|
||||||
|
key: zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
||||||
|
restore-keys: |
|
||||||
|
zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
||||||
|
- name: "Set up msys2 if necessary"
|
||||||
|
if: ${{ startsWith( matrix.os, 'windows') && steps.cache-zookeeper.outputs.cache-hit != 'true' }}
|
||||||
|
uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
release: false # support cache, see https://github.com/msys2/setup-msys2#context
|
||||||
|
- name: "Download zookeeper binary archive in Linux OS"
|
||||||
|
if: ${{ startsWith( matrix.os, 'ubuntu') && steps.cache-zookeeper.outputs.cache-hit != 'true' }}
|
||||||
|
run: |
|
||||||
|
mkdir -p ${{ github.workspace }}/.tmp/zookeeper
|
||||||
|
wget -c https://archive.apache.org/dist/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
||||||
|
wget -c https://apache.website-solution.net/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
||||||
|
wget -c http://apache.stu.edu.tw/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
||||||
|
wget -c http://ftp.jaist.ac.jp/pub/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
||||||
|
wget -c http://apache.mirror.cdnetworks.com/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
||||||
|
wget -c http://mirror.apache-kr.org/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
||||||
|
echo "list the downloaded zookeeper binary archive"
|
||||||
|
ls -al ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
||||||
|
- name: "Download zookeeper binary archive in Windows OS"
|
||||||
|
if: ${{ startsWith( matrix.os, 'windows') && steps.cache-zookeeper.outputs.cache-hit != 'true' }}
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: |
|
||||||
|
mkdir -p ${{ github.workspace }}/.tmp/zookeeper
|
||||||
|
wget -c https://archive.apache.org/dist/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
||||||
|
wget -c https://apache.website-solution.net/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
||||||
|
wget -c http://apache.stu.edu.tw/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
||||||
|
wget -c http://ftp.jaist.ac.jp/pub/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
||||||
|
wget -c http://apache.mirror.cdnetworks.com/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
||||||
|
wget -c http://mirror.apache-kr.org/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
||||||
|
echo "list the downloaded zookeeper binary archive"
|
||||||
|
ls -al ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
||||||
|
|
||||||
|
unit-test:
|
||||||
|
needs: [build-source, unit-test-prepare]
|
||||||
|
name: "Unit Test On ${{ matrix.os }} (JDK: ${{ matrix.jdk }})"
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ ubuntu-18.04, windows-2019 ]
|
||||||
|
jdk: [ 8, 11, 17 ]
|
||||||
|
env:
|
||||||
|
DISABLE_FILE_SYSTEM_TEST: true
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: "Set up JDK ${{ matrix.jdk }}"
|
||||||
|
uses: actions/setup-java@v1
|
||||||
|
with:
|
||||||
|
java-version: ${{ matrix.jdk }}
|
||||||
|
- uses: actions/cache@v2
|
||||||
|
name: "Cache local Maven repository"
|
||||||
|
with:
|
||||||
|
path: ~/.m2/repository
|
||||||
|
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-maven-
|
||||||
|
- name: "Test with Maven with Integration Tests"
|
||||||
|
timeout-minutes: 70
|
||||||
|
if: ${{ startsWith( matrix.os, 'ubuntu') }}
|
||||||
|
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Pjacoco -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
||||||
|
- name: "Test with Maven without Integration Tests"
|
||||||
|
timeout-minutes: 90
|
||||||
|
if: ${{ startsWith( matrix.os, 'windows') }}
|
||||||
|
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Pjacoco -D"http.keepAlive=false" -D"maven.wagon.http.pool=false" -D"maven.wagon.httpconnectionManager.ttlSeconds=120" -D"maven.wagon.http.retryHandler.count=5" -DskipTests=false -DskipIntegrationTests=true -D"checkstyle.skip=false" -D"checkstyle_unix.skip=true" -D"rat.skip=false" -D"maven.javadoc.skip=true" -D"embeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper"
|
||||||
|
- name: "Upload coverage to Codecov"
|
||||||
|
uses: codecov/codecov-action@v1
|
||||||
|
|
||||||
|
integration-test-prepare:
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
env:
|
||||||
|
JOB_COUNT: 3
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
repository: 'apache/dubbo-samples'
|
||||||
|
ref: master
|
||||||
|
- name: "Prepare test list"
|
||||||
|
run: |
|
||||||
|
bash ./test/scripts/prepare-test.sh
|
||||||
|
- name: "Upload test list"
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: test-list
|
||||||
|
path: test/jobs
|
||||||
|
|
||||||
|
integration-test-job:
|
||||||
|
needs: [build-source, integration-test-prepare]
|
||||||
|
name: "Integration Test on ubuntu-18.04 (JobId: ${{matrix.job_id}})"
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
timeout-minutes: 30
|
||||||
|
env:
|
||||||
|
JAVA_VER: 8
|
||||||
|
TEST_CASE_FILE: jobs/testjob_${{matrix.job_id}}.txt
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
job_id: [1, 2, 3]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
repository: 'apache/dubbo-samples'
|
||||||
|
ref: master
|
||||||
|
- name: "Cache local Maven repository"
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ~/.m2/repository
|
||||||
|
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-maven-
|
||||||
|
- name: "Restore Dubbo cache"
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ~/.m2/repository/org/apache/dubbo
|
||||||
|
key: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }}
|
||||||
|
- name: "Download test list"
|
||||||
|
uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
name: test-list
|
||||||
|
path: test/jobs/
|
||||||
|
- name: "Set up JDK 8"
|
||||||
|
uses: actions/setup-java@v1
|
||||||
|
with:
|
||||||
|
java-version: 8
|
||||||
|
- name: "Init Candidate Versions"
|
||||||
|
run: |
|
||||||
|
DUBBO_VERSION="${{needs.build-source.outputs.version}}"
|
||||||
|
CANDIDATE_VERSIONS="dubbo.version:$DUBBO_VERSION;compiler.version:$DUBBO_VERSION;$CANDIDATE_VERSIONS;dubbo.compiler.version:$DUBBO_VERSION"
|
||||||
|
echo "CANDIDATE_VERSIONS=$CANDIDATE_VERSIONS" >> $GITHUB_ENV
|
||||||
|
- name: "Build test image"
|
||||||
|
run: |
|
||||||
|
cd test && bash ./build-test-image.sh
|
||||||
|
- name: "Run tests"
|
||||||
|
run: cd test && bash ./run-tests.sh
|
||||||
|
- name: "Upload test result"
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: test-result
|
||||||
|
path: test/jobs/*-result*
|
||||||
|
|
||||||
|
integration-test-result:
|
||||||
|
needs: [integration-test-job]
|
||||||
|
if: always()
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
env:
|
||||||
|
JAVA_VER: 8
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
repository: 'apache/dubbo-samples'
|
||||||
|
ref: master
|
||||||
|
- name: "Download test result"
|
||||||
|
uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
name: test-result
|
||||||
|
path: test/jobs/
|
||||||
|
- name: "Merge test result"
|
||||||
|
run: ./test/scripts/merge-test-results.sh
|
||||||
|
|
@ -1,604 +0,0 @@
|
||||||
name: Build and Test For PR
|
|
||||||
|
|
||||||
on: [push, pull_request, workflow_dispatch]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
env:
|
|
||||||
FORK_COUNT: 2
|
|
||||||
FAIL_FAST: 0
|
|
||||||
SHOW_ERROR_DETAIL: 1
|
|
||||||
#multi-version size limit
|
|
||||||
VERSIONS_LIMIT: 4
|
|
||||||
JACOCO_ENABLE: true
|
|
||||||
CANDIDATE_VERSIONS: '
|
|
||||||
spring.version:5.3.24;
|
|
||||||
spring-boot.version:2.7.6;
|
|
||||||
'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check-format:
|
|
||||||
name: Check if code needs formatting
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Maven
|
|
||||||
uses: actions/setup-java@v4
|
|
||||||
with:
|
|
||||||
java-version: 21
|
|
||||||
distribution: zulu
|
|
||||||
- name: Check if code aligns with code style
|
|
||||||
id: check
|
|
||||||
run: mvn --log-file mvn.log spotless:check
|
|
||||||
continue-on-error: true
|
|
||||||
- name: Upload checkstyle result
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: checkstyle-result
|
|
||||||
path: mvn.log
|
|
||||||
- name: Generate Summary for successful run
|
|
||||||
if: ${{ steps.check.outcome == 'success' }}
|
|
||||||
run: |
|
|
||||||
echo ":ballot_box_with_check: Kudos! No formatting issues found!" >> $GITHUB_STEP_SUMMARY
|
|
||||||
- name: Generate Summary for failed run
|
|
||||||
if: ${{ steps.check.outcome == 'failure' }}
|
|
||||||
run: |
|
|
||||||
echo "## :negative_squared_cross_mark: Formatting issues found!" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
|
|
||||||
cat mvn.log | grep "ERROR" | sed 's/Check if code needs formatting Check if code aligns with code style [0-9A-Z:.-]\+//' | sed 's/\[ERROR] //' | head -n -11 >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "Please run \`mvn spotless:apply\` to fix the formatting issues." >> $GITHUB_STEP_SUMMARY
|
|
||||||
- name: Fail if code needs formatting
|
|
||||||
if: ${{ steps.check.outcome == 'failure' }}
|
|
||||||
uses: actions/github-script@v7.0.1
|
|
||||||
with:
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
script: |
|
|
||||||
core.setFailed("Formatting issues found!")
|
|
||||||
|
|
||||||
license:
|
|
||||||
name: "Check License"
|
|
||||||
needs: check-format
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Check License
|
|
||||||
uses: apache/skywalking-eyes@e1a02359b239bd28de3f6d35fdc870250fa513d5
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: "Set up JDK 21"
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 21
|
|
||||||
- name: "Compile Dubbo (Linux)"
|
|
||||||
run: |
|
|
||||||
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean install -DskipTests=true -DskipIntegrationTests=true -Dcheckstyle.skip=true -Dcheckstyle_unix.skip=true -Drat.skip=true -Dmaven.javadoc.skip=true
|
|
||||||
- name: Check Dependencies' License
|
|
||||||
uses: apache/skywalking-eyes/dependency@e1a02359b239bd28de3f6d35fdc870250fa513d5
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
config: .licenserc.yaml
|
|
||||||
mode: check
|
|
||||||
|
|
||||||
build-source:
|
|
||||||
name: "Build Dubbo"
|
|
||||||
needs: check-format
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
version: ${{ steps.dubbo-version.outputs.version }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
path: dubbo
|
|
||||||
- uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 8
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache local Maven repository"
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- name: "Dubbo cache"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository/org/apache/dubbo
|
|
||||||
key: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }}-${{ github.run_id }}
|
|
||||||
- name: "Build Dubbo with Maven"
|
|
||||||
run: |
|
|
||||||
cd ./dubbo
|
|
||||||
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean source:jar install -Pjacoco,checkstyle -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -Dmaven.test.skip=true -Dmaven.test.skip.exec=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
- name: "Pack class result"
|
|
||||||
run: |
|
|
||||||
shopt -s globstar
|
|
||||||
zip ${{ github.workspace }}/class.zip **/target/classes/* -r
|
|
||||||
- name: "Upload class result"
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: "class-file"
|
|
||||||
path: ${{ github.workspace }}/class.zip
|
|
||||||
- name: "Pack checkstyle file if failure"
|
|
||||||
if: failure()
|
|
||||||
run: zip ${{ github.workspace }}/checkstyle.zip *checkstyle* -r
|
|
||||||
- name: "Upload checkstyle file if failure"
|
|
||||||
if: failure()
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: "checkstyle-file"
|
|
||||||
path: ${{ github.workspace }}/checkstyle.zip
|
|
||||||
- name: "Calculate Dubbo Version"
|
|
||||||
id: dubbo-version
|
|
||||||
run: |
|
|
||||||
REVISION=`awk '/<revision>[^<]+<\/revision>/{gsub(/<revision>|<\/revision>/,"",$1);print $1;exit;}' ./dubbo/pom.xml`
|
|
||||||
echo "version=$REVISION" >> $GITHUB_OUTPUT
|
|
||||||
echo "dubbo version: $REVISION"
|
|
||||||
|
|
||||||
unit-test-prepare:
|
|
||||||
name: "Preparation for Unit Test"
|
|
||||||
needs: check-format
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
env:
|
|
||||||
ZOOKEEPER_VERSION: 3.6.3
|
|
||||||
steps:
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache zookeeper binary archive"
|
|
||||||
id: "cache-zookeeper"
|
|
||||||
with:
|
|
||||||
path: ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
key: zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
|
||||||
restore-keys: |
|
|
||||||
zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
|
||||||
- name: "Set up msys2 if necessary"
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') && steps.cache-zookeeper.outputs.cache-hit != 'true' }}
|
|
||||||
uses: msys2/setup-msys2@v2
|
|
||||||
with:
|
|
||||||
release: false # support cache, see https://github.com/msys2/setup-msys2#context
|
|
||||||
- name: "Download zookeeper binary archive in Linux OS"
|
|
||||||
run: |
|
|
||||||
mkdir -p ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
wget -c https://archive.apache.org/dist/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c https://apache.website-solution.net/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://apache.stu.edu.tw/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://ftp.jaist.ac.jp/pub/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://apache.mirror.cdnetworks.com/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://mirror.apache-kr.org/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
|
||||||
echo "list the downloaded zookeeper binary archive"
|
|
||||||
ls -al ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache secret key"
|
|
||||||
id: "cache-secret-cert"
|
|
||||||
with:
|
|
||||||
path: ${{ github.workspace }}/.tmp/rsa
|
|
||||||
key: secret-rsa-${{ runner.os }}-${{ github.run_id }}
|
|
||||||
- name: "Create Secret"
|
|
||||||
run: |
|
|
||||||
mkdir -p ${{ github.workspace }}/.tmp/rsa
|
|
||||||
cd ${{ github.workspace }}/.tmp/rsa
|
|
||||||
openssl genrsa -out rsa_private.pem 1024
|
|
||||||
openssl rsa -in rsa_private.pem -pubout -out rsa_public.pem
|
|
||||||
echo "Current workflow run id: ${{ github.run_id }}"
|
|
||||||
echo "Start Print Rsa Public Key ---"
|
|
||||||
cat rsa_public.pem
|
|
||||||
echo "--- End Print Rsa Public Key"
|
|
||||||
|
|
||||||
unit-test:
|
|
||||||
needs: [check-format, build-source, unit-test-prepare]
|
|
||||||
name: "Unit Test On ubuntu-latest"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
env:
|
|
||||||
DISABLE_FILE_SYSTEM_TEST: true
|
|
||||||
CURRENT_ROLE: ${{ matrix.case-role }}
|
|
||||||
DUBBO_DEFAULT_SERIALIZATION: fastjson2
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: "Set up JDK ${{ matrix.jdk }}"
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 21
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache local Maven repository"
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache zookeeper binary archive"
|
|
||||||
id: "cache-zookeeper"
|
|
||||||
with:
|
|
||||||
path: ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
key: zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
|
||||||
restore-keys: |
|
|
||||||
zookeeper-${{ runner.os }}-
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache secret key"
|
|
||||||
id: "cache-secret-cert"
|
|
||||||
with:
|
|
||||||
path: ${{ github.workspace }}/.tmp/rsa
|
|
||||||
key: secret-rsa-${{ runner.os }}-${{ github.run_id }}
|
|
||||||
- name: "Get sonarcloud token"
|
|
||||||
if: ${{ github.repository == 'apache/dubbo' }}
|
|
||||||
run: |
|
|
||||||
curl "http://dubbo-vm.apache.org:8000/token?workflow_id=${{ github.run_id }}" -o ${{ github.workspace }}/.tmp/encrypted-sonarcloud-token
|
|
||||||
openssl rsautl -decrypt -in ${{ github.workspace }}/.tmp/encrypted-sonarcloud-token -out ${{ github.workspace }}/.tmp/decrypted-sonarcloud-token -inkey ${{ github.workspace }}/.tmp/rsa/rsa_private.pem
|
|
||||||
- name: "Test with Maven with SonarCloud Scan"
|
|
||||||
if: ${{ github.repository == 'apache/dubbo' }}
|
|
||||||
timeout-minutes: 70
|
|
||||||
env:
|
|
||||||
# Needed to get some information about the pull request, if any
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
source ${{ github.workspace }}/.tmp/decrypted-sonarcloud-token
|
|
||||||
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Pjacoco,jdk15ge-simple,'!jdk15ge',jacoco089 -Dsonar.host.url=https://sonarcloud.io -Dsonar.organization=apache -Dsonar.projectKey=apache_dubbo -DtrimStackTrace=false -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper -Dsonar.coverage.jacoco.xmlReportPaths=dubbo-test/dubbo-dependencies-all/target/site/jacoco-aggregate/jacoco.xml -Dsonar.login=${SONAR_TOKEN}
|
|
||||||
- name: "Test with Maven without SonarCloud Scan"
|
|
||||||
if: ${{ github.repository != 'apache/dubbo' }}
|
|
||||||
timeout-minutes: 70
|
|
||||||
run: |
|
|
||||||
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Pjacoco,jdk15ge-simple,'!jdk15ge',jacoco089 -DtrimStackTrace=false -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
- name: "Upload coverage result"
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: coverage-result
|
|
||||||
path: "**/target/site/**/jacoco.xml"
|
|
||||||
|
|
||||||
samples-test-prepare:
|
|
||||||
needs: check-format
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
JOB_COUNT: 3
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-samples'
|
|
||||||
ref: master
|
|
||||||
- name: "Prepare test list"
|
|
||||||
run: |
|
|
||||||
bash ./test/scripts/prepare-test.sh
|
|
||||||
- name: "Upload test list"
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-test-list
|
|
||||||
path: test/jobs
|
|
||||||
samples-test-job:
|
|
||||||
needs: [check-format, build-source, samples-test-prepare]
|
|
||||||
name: "Samples Test on ubuntu-latest (JobId: ${{matrix.job_id}})"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 90
|
|
||||||
env:
|
|
||||||
JAVA_VER: 8
|
|
||||||
TEST_CASE_FILE: jobs/testjob_${{matrix.job_id}}.txt
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
job_id: [1, 2, 3]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-samples'
|
|
||||||
ref: master
|
|
||||||
- name: "Cache local Maven repository"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- name: "Restore Dubbo cache"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository/org/apache/dubbo
|
|
||||||
key: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-dubbo-snapshot-${{ github.sha }}
|
|
||||||
${{ runner.os }}-dubbo-snapshot-
|
|
||||||
- name: "Download test list"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-test-list
|
|
||||||
path: test/jobs/
|
|
||||||
- name: "Set up JDK 8"
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 8
|
|
||||||
- name: "Init Candidate Versions"
|
|
||||||
run: |
|
|
||||||
DUBBO_VERSION="${{needs.build-source.outputs.version}}"
|
|
||||||
CANDIDATE_VERSIONS="dubbo.version:$DUBBO_VERSION;compiler.version:$DUBBO_VERSION;$CANDIDATE_VERSIONS;dubbo.compiler.version:$DUBBO_VERSION"
|
|
||||||
echo "CANDIDATE_VERSIONS=$CANDIDATE_VERSIONS" >> $GITHUB_ENV
|
|
||||||
- name: "Build test image"
|
|
||||||
run: |
|
|
||||||
cd test && bash ./build-test-image.sh
|
|
||||||
- name: "Run tests"
|
|
||||||
run: cd test && bash ./run-tests.sh
|
|
||||||
- name: "merge jacoco resule"
|
|
||||||
run: |
|
|
||||||
cd test/dubbo-test-jacoco-merger && mvn clean compile exec:java -Dexec.mainClass="org.apache.dubbo.test.JacocoMerge" -Dexec.args="${{github.workspace}}"
|
|
||||||
- name: "Upload jacoco"
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-jacoco-result
|
|
||||||
path: target/jacoco*.exec
|
|
||||||
- name: "Upload test result"
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-test-result
|
|
||||||
path: test/jobs/*-result*
|
|
||||||
samples-test-result:
|
|
||||||
needs: [check-format, samples-test-job]
|
|
||||||
if: always()
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
JAVA_VER: 8
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-samples'
|
|
||||||
ref: master
|
|
||||||
- name: "Download test result"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-test-result
|
|
||||||
path: test/jobs/
|
|
||||||
- name: "Merge test result"
|
|
||||||
run: ./test/scripts/merge-test-results.sh
|
|
||||||
|
|
||||||
integration-test-prepare:
|
|
||||||
needs: check-format
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
JOB_COUNT: 3
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-integration-cases'
|
|
||||||
ref: main
|
|
||||||
- name: "Prepare test list"
|
|
||||||
run: |
|
|
||||||
bash ./test/scripts/prepare-test.sh
|
|
||||||
- name: "Upload test list"
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: test-list
|
|
||||||
path: test/jobs
|
|
||||||
integration-test-job:
|
|
||||||
needs: [check-format, build-source, integration-test-prepare]
|
|
||||||
name: "Integration Test on ubuntu-latest (JobId: ${{matrix.job_id}})"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 90
|
|
||||||
env:
|
|
||||||
JAVA_VER: 8
|
|
||||||
TEST_CASE_FILE: jobs/testjob_${{matrix.job_id}}.txt
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
job_id: [1, 2, 3]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-integration-cases'
|
|
||||||
ref: main
|
|
||||||
- name: "Cache local Maven repository"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- name: "Restore Dubbo cache"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository/org/apache/dubbo
|
|
||||||
key: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-dubbo-snapshot-${{ github.sha }}
|
|
||||||
${{ runner.os }}-dubbo-snapshot-
|
|
||||||
- name: "Download test list"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: test-list
|
|
||||||
path: test/jobs/
|
|
||||||
- name: "Set up JDK 8"
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 8
|
|
||||||
- name: "Init Candidate Versions"
|
|
||||||
run: |
|
|
||||||
DUBBO_VERSION="${{needs.build-source.outputs.version}}"
|
|
||||||
CANDIDATE_VERSIONS="dubbo.version:$DUBBO_VERSION;compiler.version:$DUBBO_VERSION;$CANDIDATE_VERSIONS;dubbo.compiler.version:$DUBBO_VERSION"
|
|
||||||
echo "CANDIDATE_VERSIONS=$CANDIDATE_VERSIONS" >> $GITHUB_ENV
|
|
||||||
- name: "Build test image"
|
|
||||||
run: |
|
|
||||||
cd test && bash ./build-test-image.sh
|
|
||||||
- name: "Run tests"
|
|
||||||
run: cd test && bash ./run-tests.sh
|
|
||||||
- name: "merge jacoco resule"
|
|
||||||
run: |
|
|
||||||
cd test/dubbo-test-jacoco-merger && mvn clean compile exec:java -Dexec.mainClass="org.apache.dubbo.test.JacocoMerge" -Dexec.args="${{github.workspace}}"
|
|
||||||
- name: "Upload jacoco"
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: jacoco-result
|
|
||||||
path: target/jacoco*.exec
|
|
||||||
- name: "Upload test result"
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: test-result
|
|
||||||
path: test/jobs/*-result*
|
|
||||||
integration-test-result:
|
|
||||||
needs: [check-format, integration-test-job]
|
|
||||||
if: always()
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
JAVA_VER: 8
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-integration-cases'
|
|
||||||
ref: main
|
|
||||||
- name: "Download test result"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: test-result
|
|
||||||
path: test/jobs/
|
|
||||||
- name: "Merge test result"
|
|
||||||
run: ./test/scripts/merge-test-results.sh
|
|
||||||
|
|
||||||
jacoco-result-merge:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [check-format, integration-test-result, samples-test-result, unit-test]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
path: "./dubbo"
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-samples'
|
|
||||||
path: "./dubbo-samples"
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-integration-cases'
|
|
||||||
path: "./dubbo-integration-cases"
|
|
||||||
- name: "Set up JDK 21"
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 21
|
|
||||||
- name: "Restore class result"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: "class-file"
|
|
||||||
path: ${{ github.workspace }}
|
|
||||||
- name: "Unpack class result"
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo
|
|
||||||
unzip -o ${{ github.workspace }}/class.zip
|
|
||||||
- name: "Restore jacoco exec"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-jacoco-result
|
|
||||||
path: dubbo-samples/target/
|
|
||||||
- name: "Restore integration jacoco exec"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: jacoco-result
|
|
||||||
path: dubbo-integration-cases/target/
|
|
||||||
- name: "Merge jacoco result"
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo-samples/test/dubbo-test-jacoco-merger
|
|
||||||
mvn clean compile exec:java -Dexec.mainClass="org.apache.dubbo.test.JacocoReport" -Dexec.args="${{github.workspace}}/dubbo-samples ${{github.workspace}}/dubbo"
|
|
||||||
- name: "Merge samples jacoco result"
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo-integration-cases/test/dubbo-test-jacoco-merger
|
|
||||||
mvn clean compile exec:java -Dexec.mainClass="org.apache.dubbo.test.JacocoReport" -Dexec.args="${{github.workspace}}/dubbo-integration-cases ${{github.workspace}}/dubbo"
|
|
||||||
- name: "Restore coverage result"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: coverage-result
|
|
||||||
path: dubbo/
|
|
||||||
- name: "Upload coverage to Codecov"
|
|
||||||
uses: codecov/codecov-action@v3
|
|
||||||
with:
|
|
||||||
verbose: true
|
|
||||||
|
|
||||||
error-code-inspecting:
|
|
||||||
needs: check-format
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
path: "./dubbo"
|
|
||||||
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-test-tools'
|
|
||||||
ref: main
|
|
||||||
path: "./dubbo-test-tools"
|
|
||||||
|
|
||||||
- name: "Set up JDK 21"
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 21
|
|
||||||
|
|
||||||
- name: "Compile Dubbo (Linux)"
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo
|
|
||||||
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean install -DskipTests=true -DskipIntegrationTests=true -Dcheckstyle.skip=true -Dcheckstyle_unix.skip=true -Drat.skip=true -Dmaven.javadoc.skip=true
|
|
||||||
- name: "Run Error Code Inspecting"
|
|
||||||
env:
|
|
||||||
DUBBO_ECI_REPORT_AS_ERROR: true
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo-test-tools/dubbo-error-code-inspector
|
|
||||||
../mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C package exec:java -Ddubbo.eci.report-as-error=${DUBBO_ECI_REPORT_AS_ERROR} -Dmaven.test.skip=true -Dmaven.test.skip.exec=true -Ddubbo.eci.path=${{ github.workspace }}/dubbo
|
|
||||||
|
|
||||||
- name: "Upload error code inspection result"
|
|
||||||
# always() should not be used here, since we don't need to handle the 'canceled' situation.
|
|
||||||
if: ${{ success() || failure() }}
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: "error-inspection-result"
|
|
||||||
path: ${{ github.workspace }}/dubbo-test-tools/dubbo-error-code-inspector/error-inspection-result.txt
|
|
||||||
|
|
||||||
native-image-inspecting:
|
|
||||||
needs: check-format
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
path: "./dubbo"
|
|
||||||
|
|
||||||
- name: "Setup GraalVM environment"
|
|
||||||
uses: graalvm/setup-graalvm@v1
|
|
||||||
with:
|
|
||||||
version: '22.3.0'
|
|
||||||
java-version: '17'
|
|
||||||
components: 'native-image'
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
native-image-job-reports: 'true'
|
|
||||||
|
|
||||||
- name: "Setup Zookeeper environment"
|
|
||||||
run: |
|
|
||||||
wget https://dlcdn.apache.org/zookeeper/zookeeper-3.8.4/apache-zookeeper-3.8.4-bin.tar.gz
|
|
||||||
tar -zxvf apache-zookeeper-3.8.4-bin.tar.gz
|
|
||||||
mv apache-zookeeper-3.8.4-bin/conf/zoo_sample.cfg apache-zookeeper-3.8.4-bin/conf/zoo.cfg
|
|
||||||
apache-zookeeper-3.8.4-bin/bin/zkServer.sh start
|
|
||||||
|
|
||||||
- name: "Check environment"
|
|
||||||
run: |
|
|
||||||
java --version
|
|
||||||
native-image --version
|
|
||||||
|
|
||||||
- name: "Compile Dubbo (Linux)"
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo
|
|
||||||
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean install -DskipTests=true -DskipIntegrationTests=true -Dcheckstyle.skip=true -Dcheckstyle_unix.skip=true -Drat.skip=true -Dmaven.javadoc.skip=true
|
|
||||||
|
|
||||||
- name: "Compile and run Dubbo demo for native (Linux)"
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo/dubbo-demo/dubbo-demo-native/dubbo-demo-native-provider
|
|
||||||
${{ github.workspace }}/dubbo/mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean package -P native -Dmaven.test.skip=true native:compile
|
|
||||||
nohup ./target/dubbo-demo-native-provider &
|
|
||||||
cd ${{ github.workspace }}/dubbo/dubbo-demo/dubbo-demo-native/dubbo-demo-native-consumer
|
|
||||||
${{ github.workspace }}/dubbo/mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean package -P native -Dmaven.test.skip=true native:compile
|
|
||||||
./target/dubbo-demo-native-consumer
|
|
||||||
|
|
@ -1,502 +0,0 @@
|
||||||
name: Build and Test Scheduled On 3.1
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0/6 * * *'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
env:
|
|
||||||
FORK_COUNT: 2
|
|
||||||
FAIL_FAST: 0
|
|
||||||
SHOW_ERROR_DETAIL: 1
|
|
||||||
#multi-version size limit
|
|
||||||
VERSIONS_LIMIT: 4
|
|
||||||
ALL_REMOTE_VERSION: true
|
|
||||||
CANDIDATE_VERSIONS: '
|
|
||||||
spring.version:5.3.24;
|
|
||||||
spring-boot.version:2.7.6;
|
|
||||||
'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
license:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
ref: "3.1"
|
|
||||||
- name: Check License
|
|
||||||
uses: apache/skywalking-eyes@main
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
build-source:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
version: ${{ steps.dubbo-version.outputs.version }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
ref: "3.1"
|
|
||||||
path: dubbo
|
|
||||||
- uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 8
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache local Maven repository"
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- name: "Dubbo cache"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository/org/apache/dubbo
|
|
||||||
key: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }}-${{ github.run_id }}
|
|
||||||
- name: "Build Dubbo with Maven"
|
|
||||||
run: |
|
|
||||||
cd ./dubbo
|
|
||||||
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean source:jar install -Pjacoco,checkstyle -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -Dmaven.test.skip=true -Dmaven.test.skip.exec=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
- name: "Pack checkstyle file if failure"
|
|
||||||
if: failure()
|
|
||||||
run: 7z a ${{ github.workspace }}/checkstyle.zip *checkstyle* -r
|
|
||||||
- name: "Upload checkstyle file if failure"
|
|
||||||
if: failure()
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: "checkstyle-file"
|
|
||||||
path: ${{ github.workspace }}/checkstyle.zip
|
|
||||||
- name: "Calculate Dubbo Version"
|
|
||||||
id: dubbo-version
|
|
||||||
run: |
|
|
||||||
REVISION=`awk '/<revision>[^<]+<\/revision>/{gsub(/<revision>|<\/revision>/,"",$1);print $1;exit;}' ./dubbo/pom.xml`
|
|
||||||
echo "version=$REVISION" >> $GITHUB_OUTPUT
|
|
||||||
echo "dubbo version: $REVISION"
|
|
||||||
|
|
||||||
unit-test-prepare:
|
|
||||||
name: " Preparation for Unit Test On ${{ matrix.os }}"
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ ubuntu-latest, windows-latest ]
|
|
||||||
env:
|
|
||||||
ZOOKEEPER_VERSION: 3.6.3
|
|
||||||
steps:
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache zookeeper binary archive"
|
|
||||||
id: "cache-zookeeper"
|
|
||||||
with:
|
|
||||||
path: ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
key: zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
|
||||||
restore-keys: |
|
|
||||||
zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
|
||||||
- name: "Set up msys2 if necessary"
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') && steps.cache-zookeeper.outputs.cache-hit != 'true' }}
|
|
||||||
uses: msys2/setup-msys2@v2
|
|
||||||
with:
|
|
||||||
release: false # support cache, see https://github.com/msys2/setup-msys2#context
|
|
||||||
- name: "Download zookeeper binary archive in Linux OS"
|
|
||||||
if: ${{ startsWith( matrix.os, 'ubuntu') && steps.cache-zookeeper.outputs.cache-hit != 'true' }}
|
|
||||||
run: |
|
|
||||||
mkdir -p ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
wget -c https://archive.apache.org/dist/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c https://apache.website-solution.net/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://apache.stu.edu.tw/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://ftp.jaist.ac.jp/pub/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://apache.mirror.cdnetworks.com/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://mirror.apache-kr.org/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
|
||||||
echo "list the downloaded zookeeper binary archive"
|
|
||||||
ls -al ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
|
||||||
- name: "Download zookeeper binary archive in Windows OS"
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') && steps.cache-zookeeper.outputs.cache-hit != 'true' }}
|
|
||||||
shell: msys2 {0}
|
|
||||||
run: |
|
|
||||||
mkdir -p ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
wget -c https://archive.apache.org/dist/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c https://apache.website-solution.net/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://apache.stu.edu.tw/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://ftp.jaist.ac.jp/pub/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://apache.mirror.cdnetworks.com/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://mirror.apache-kr.org/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
|
||||||
echo "list the downloaded zookeeper binary archive"
|
|
||||||
ls -al ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
|
||||||
|
|
||||||
unit-test:
|
|
||||||
needs: [build-source, unit-test-prepare]
|
|
||||||
name: "Unit Test On ${{ matrix.os }} (JDK: ${{ matrix.jdk }})"
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ ubuntu-latest, windows-latest ]
|
|
||||||
jdk: [ 8, 11, 17, 21 ]
|
|
||||||
env:
|
|
||||||
DISABLE_FILE_SYSTEM_TEST: true
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
ref: "3.1"
|
|
||||||
- name: "Set up JDK ${{ matrix.jdk }}"
|
|
||||||
uses: actions/setup-java@v1
|
|
||||||
with:
|
|
||||||
java-version: ${{ matrix.jdk }}
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache local Maven repository"
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache zookeeper binary archive"
|
|
||||||
id: "cache-zookeeper"
|
|
||||||
with:
|
|
||||||
path: ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
key: zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
|
||||||
restore-keys: |
|
|
||||||
zookeeper-${{ runner.os }}-
|
|
||||||
- name: "Test with Maven with Integration Tests"
|
|
||||||
timeout-minutes: 70
|
|
||||||
if: ${{ startsWith( matrix.os, 'ubuntu') }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Pjacoco -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
- name: "Test with Maven without Integration Tests"
|
|
||||||
timeout-minutes: 90
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Pjacoco -D"http.keepAlive=false" -D"maven.wagon.http.pool=false" -D"maven.wagon.httpconnectionManager.ttlSeconds=120" -D"maven.wagon.http.retryHandler.count=5" -DskipTests=false -DskipIntegrationTests=true -D"checkstyle.skip=false" -D"checkstyle_unix.skip=true" -D"rat.skip=false" -D"maven.javadoc.skip=true" -D"embeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper"
|
|
||||||
|
|
||||||
unit-test-fastjson2:
|
|
||||||
needs: [build-source, unit-test-prepare]
|
|
||||||
name: "Unit Test On ${{ matrix.os }} (JDK: ${{ matrix.jdk }}, Serialization: fastjson2)"
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ ubuntu-latest, windows-latest ]
|
|
||||||
jdk: [ 8, 11, 17, 21 ]
|
|
||||||
env:
|
|
||||||
DISABLE_FILE_SYSTEM_TEST: true
|
|
||||||
DUBBO_DEFAULT_SERIALIZATION: fastjson2
|
|
||||||
MAVEN_SUREFIRE_ADD_OPENS: true
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: "Set up JDK ${{ matrix.jdk }}"
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: ${{ matrix.jdk }}
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache local Maven repository"
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache zookeeper binary archive"
|
|
||||||
id: "cache-zookeeper"
|
|
||||||
with:
|
|
||||||
path: ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
key: zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
|
||||||
restore-keys: |
|
|
||||||
zookeeper-${{ runner.os }}-
|
|
||||||
- name: "Test with Maven with Integration Tests on JDK 8"
|
|
||||||
timeout-minutes: 70
|
|
||||||
if: ${{ startsWith( matrix.os, 'ubuntu') && matrix.jdk == '8' }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Pjacoco,'!jdk15ge' -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
- name: "Test with Maven without Integration Tests on JDK 8"
|
|
||||||
timeout-minutes: 90
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') && matrix.jdk == '8' }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -P"jacoco,'!jdk15ge'" -D"http.keepAlive=false" -D"maven.wagon.http.pool=false" -D"maven.wagon.httpconnectionManager.ttlSeconds=120" -D"maven.wagon.http.retryHandler.count=5" -DskipTests=false -DskipIntegrationTests=true -D"checkstyle.skip=false" -D"checkstyle_unix.skip=true" -D"rat.skip=false" -D"maven.javadoc.skip=true" -D"embeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper"
|
|
||||||
- name: "Test with Maven with Integration Tests"
|
|
||||||
timeout-minutes: 70
|
|
||||||
if: ${{ startsWith( matrix.os, 'ubuntu') && matrix.jdk != '8' }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Pjacoco,jdk15ge-simple,'!jdk15ge' -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
- name: "Test with Maven without Integration Tests"
|
|
||||||
timeout-minutes: 90
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') && matrix.jdk != '8' }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -P"jacoco,jdk15ge-simple,'!jdk15ge'" -D"http.keepAlive=false" -D"maven.wagon.http.pool=false" -D"maven.wagon.httpconnectionManager.ttlSeconds=120" -D"maven.wagon.http.retryHandler.count=5" -DskipTests=false -DskipIntegrationTests=true -D"checkstyle.skip=false" -D"checkstyle_unix.skip=true" -D"rat.skip=false" -D"maven.javadoc.skip=true" -D"embeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper"
|
|
||||||
|
|
||||||
samples-test-prepare:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
JOB_COUNT: 5
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-samples'
|
|
||||||
ref: master
|
|
||||||
- name: "Prepare test list"
|
|
||||||
run: |
|
|
||||||
bash ./test/scripts/prepare-test.sh
|
|
||||||
- name: "Upload test list"
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-test-list
|
|
||||||
path: test/jobs
|
|
||||||
samples-test-job:
|
|
||||||
needs: [build-source, samples-test-prepare]
|
|
||||||
name: "Samples Test on ubuntu-latest (JobId: ${{matrix.job_id}} JavaVer: ${{matrix.jdk}})"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 90
|
|
||||||
env:
|
|
||||||
JAVA_VER: ${{matrix.jdk}}
|
|
||||||
TEST_CASE_FILE: jobs/testjob_${{matrix.job_id}}.txt
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
jdk: [ 8, 11 ]
|
|
||||||
job_id: [1, 2, 3, 4, 5]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-samples'
|
|
||||||
ref: master
|
|
||||||
- name: "Cache local Maven repository"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- name: "Restore Dubbo cache"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository/org/apache/dubbo
|
|
||||||
key: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-dubbo-snapshot-${{ github.sha }}
|
|
||||||
${{ runner.os }}-dubbo-snapshot-
|
|
||||||
- name: "Download test list"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-test-list
|
|
||||||
path: test/jobs/
|
|
||||||
- name: "Set up JDK ${{matrix.jdk}}"
|
|
||||||
uses: actions/setup-java@v1
|
|
||||||
with:
|
|
||||||
java-version: ${{matrix.jdk}}
|
|
||||||
- name: "Init Candidate Versions"
|
|
||||||
run: |
|
|
||||||
DUBBO_VERSION="${{needs.build-source.outputs.version}}"
|
|
||||||
CANDIDATE_VERSIONS="dubbo.version:$DUBBO_VERSION;compiler.version:$DUBBO_VERSION;$CANDIDATE_VERSIONS;dubbo.compiler.version:$DUBBO_VERSION"
|
|
||||||
echo "CANDIDATE_VERSIONS=$CANDIDATE_VERSIONS" >> $GITHUB_ENV
|
|
||||||
- name: "Build test image"
|
|
||||||
run: |
|
|
||||||
cd test && bash ./build-test-image.sh
|
|
||||||
- name: "Run tests"
|
|
||||||
run: cd test && bash ./run-tests.sh
|
|
||||||
- name: "Upload test result"
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-test-result-${{matrix.jdk}}
|
|
||||||
path: test/jobs/*-result*
|
|
||||||
samples-test-result:
|
|
||||||
needs: [samples-test-job]
|
|
||||||
if: always()
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
JAVA_VER: ${{matrix.jdk}}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
jdk: [ 8, 11 ]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-samples'
|
|
||||||
ref: master
|
|
||||||
- name: "Download test result"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-test-result-${{matrix.jdk}}
|
|
||||||
path: test/jobs/
|
|
||||||
- name: "Merge test result"
|
|
||||||
run: ./test/scripts/merge-test-results.sh
|
|
||||||
|
|
||||||
integration-test-prepare:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
JOB_COUNT: 5
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-integration-cases'
|
|
||||||
ref: main
|
|
||||||
- name: "Prepare test list"
|
|
||||||
run: |
|
|
||||||
bash ./test/scripts/prepare-test.sh
|
|
||||||
- name: "Upload test list"
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: integration-test-list
|
|
||||||
path: test/jobs
|
|
||||||
integration-test-job:
|
|
||||||
needs: [build-source, integration-test-prepare]
|
|
||||||
name: "Integration Test on ubuntu-latest (JobId: ${{matrix.job_id}} JavaVer: ${{matrix.jdk}})"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 90
|
|
||||||
env:
|
|
||||||
JAVA_VER: ${{matrix.jdk}}
|
|
||||||
TEST_CASE_FILE: jobs/testjob_${{matrix.job_id}}.txt
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
jdk: [ 8, 11 ]
|
|
||||||
job_id: [1, 2, 3, 4, 5]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-integration-cases'
|
|
||||||
ref: main
|
|
||||||
- name: "Cache local Maven repository"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- name: "Restore Dubbo cache"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository/org/apache/dubbo
|
|
||||||
key: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-dubbo-snapshot-${{ github.sha }}
|
|
||||||
${{ runner.os }}-dubbo-snapshot-
|
|
||||||
- name: "Download test list"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: integration-test-list
|
|
||||||
path: test/jobs/
|
|
||||||
- name: "Set up JDK ${{matrix.jdk}}"
|
|
||||||
uses: actions/setup-java@v1
|
|
||||||
with:
|
|
||||||
java-version: ${{matrix.jdk}}
|
|
||||||
- name: "Init Candidate Versions"
|
|
||||||
run: |
|
|
||||||
DUBBO_VERSION="${{needs.build-source.outputs.version}}"
|
|
||||||
CANDIDATE_VERSIONS="dubbo.version:$DUBBO_VERSION;compiler.version:$DUBBO_VERSION;$CANDIDATE_VERSIONS;dubbo.compiler.version:$DUBBO_VERSION"
|
|
||||||
echo "CANDIDATE_VERSIONS=$CANDIDATE_VERSIONS" >> $GITHUB_ENV
|
|
||||||
- name: "Build test image"
|
|
||||||
run: |
|
|
||||||
cd test && bash ./build-test-image.sh
|
|
||||||
- name: "Run tests"
|
|
||||||
run: cd test && bash ./run-tests.sh
|
|
||||||
- name: "Upload test result"
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: integration-test-result-${{matrix.jdk}}
|
|
||||||
path: test/jobs/*-result*
|
|
||||||
integration-test-result:
|
|
||||||
needs: [integration-test-job]
|
|
||||||
if: always()
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
JAVA_VER: ${{matrix.jdk}}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
jdk: [ 8, 11 ]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-integration-cases'
|
|
||||||
ref: main
|
|
||||||
- name: "Download test result"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: integration-test-result-${{matrix.jdk}}
|
|
||||||
path: test/jobs/
|
|
||||||
- name: "Merge test result"
|
|
||||||
run: ./test/scripts/merge-test-results.sh
|
|
||||||
|
|
||||||
error-code-inspecting:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
ref: "3.1"
|
|
||||||
path: "./dubbo"
|
|
||||||
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-test-tools'
|
|
||||||
ref: main
|
|
||||||
path: "./dubbo-test-tools"
|
|
||||||
|
|
||||||
- name: "Set up JDK 21"
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 21
|
|
||||||
|
|
||||||
- name: "Compile Dubbo (Linux)"
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo
|
|
||||||
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean install -DskipTests=true -DskipIntegrationTests=true -Dcheckstyle.skip=true -Dcheckstyle_unix.skip=true -Drat.skip=true -Dmaven.javadoc.skip=true
|
|
||||||
- name: "Run Error Code Inspecting"
|
|
||||||
env:
|
|
||||||
DUBBO_ECI_REPORT_AS_ERROR: true
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo-test-tools/dubbo-error-code-inspector
|
|
||||||
../mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C package exec:java -Ddubbo.eci.report-as-error=${DUBBO_ECI_REPORT_AS_ERROR} -Dmaven.test.skip=true -Dmaven.test.skip.exec=true -Ddubbo.eci.path=${{ github.workspace }}/dubbo
|
|
||||||
|
|
||||||
- name: "Upload error code inspection result"
|
|
||||||
# always() should not be used here, since we don't need to handle the 'canceled' situation.
|
|
||||||
if: ${{ success() || failure() }}
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: "error-inspection-result"
|
|
||||||
path: ${{ github.workspace }}/dubbo-test-tools/dubbo-error-code-inspector/error-inspection-result.txt
|
|
||||||
|
|
||||||
native-image-inspecting:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
ref: "3.1"
|
|
||||||
path: "./dubbo"
|
|
||||||
|
|
||||||
- name: "Setup GraalVM environment"
|
|
||||||
uses: graalvm/setup-graalvm@v1
|
|
||||||
with:
|
|
||||||
version: '22.3.0'
|
|
||||||
java-version: '17'
|
|
||||||
components: 'native-image'
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
native-image-job-reports: 'true'
|
|
||||||
|
|
||||||
- name: "Setup Zookeeper environment"
|
|
||||||
run: |
|
|
||||||
wget https://dlcdn.apache.org/zookeeper/zookeeper-3.8.4/apache-zookeeper-3.8.4-bin.tar.gz
|
|
||||||
tar -zxvf apache-zookeeper-3.8.4-bin.tar.gz
|
|
||||||
mv apache-zookeeper-3.8.4-bin/conf/zoo_sample.cfg apache-zookeeper-3.8.4-bin/conf/zoo.cfg
|
|
||||||
apache-zookeeper-3.8.4-bin/bin/zkServer.sh start
|
|
||||||
|
|
||||||
- name: "Check environment"
|
|
||||||
run: |
|
|
||||||
java --version
|
|
||||||
native-image --version
|
|
||||||
|
|
||||||
- name: "Compile Dubbo (Linux)"
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo
|
|
||||||
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean install -DskipTests=true -DskipIntegrationTests=true -Dcheckstyle.skip=true -Dcheckstyle_unix.skip=true -Drat.skip=true -Dmaven.javadoc.skip=true
|
|
||||||
|
|
||||||
- name: "Compile and run Dubbo demo for native (Linux)"
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo/dubbo-demo/dubbo-demo-native/dubbo-demo-native-provider
|
|
||||||
${{ github.workspace }}/dubbo/mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean package -P native -Dmaven.test.skip=true native:compile
|
|
||||||
nohup ./target/dubbo-demo-native-provider &
|
|
||||||
cd ${{ github.workspace }}/dubbo/dubbo-demo/dubbo-demo-native/dubbo-demo-native-consumer
|
|
||||||
${{ github.workspace }}/dubbo/mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean package -P native -Dmaven.test.skip=true native:compile
|
|
||||||
./target/dubbo-demo-native-consumer
|
|
||||||
|
|
@ -1,502 +0,0 @@
|
||||||
name: Build and Test Scheduled On 3.2
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0/6 * * *'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
env:
|
|
||||||
FORK_COUNT: 2
|
|
||||||
FAIL_FAST: 0
|
|
||||||
SHOW_ERROR_DETAIL: 1
|
|
||||||
#multi-version size limit
|
|
||||||
VERSIONS_LIMIT: 4
|
|
||||||
ALL_REMOTE_VERSION: true
|
|
||||||
CANDIDATE_VERSIONS: '
|
|
||||||
spring.version:5.3.24;
|
|
||||||
spring-boot.version:2.7.6;
|
|
||||||
'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
license:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
ref: "3.2"
|
|
||||||
- name: Check License
|
|
||||||
uses: apache/skywalking-eyes@main
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
build-source:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
version: ${{ steps.dubbo-version.outputs.version }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
ref: "3.2"
|
|
||||||
path: dubbo
|
|
||||||
- uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 8
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache local Maven repository"
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- name: "Dubbo cache"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository/org/apache/dubbo
|
|
||||||
key: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }}-${{ github.run_id }}
|
|
||||||
- name: "Build Dubbo with Maven"
|
|
||||||
run: |
|
|
||||||
cd ./dubbo
|
|
||||||
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean source:jar install -Pjacoco,checkstyle -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -Dmaven.test.skip=true -Dmaven.test.skip.exec=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
- name: "Pack checkstyle file if failure"
|
|
||||||
if: failure()
|
|
||||||
run: 7z a ${{ github.workspace }}/checkstyle.zip *checkstyle* -r
|
|
||||||
- name: "Upload checkstyle file if failure"
|
|
||||||
if: failure()
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: "checkstyle-file"
|
|
||||||
path: ${{ github.workspace }}/checkstyle.zip
|
|
||||||
- name: "Calculate Dubbo Version"
|
|
||||||
id: dubbo-version
|
|
||||||
run: |
|
|
||||||
REVISION=`awk '/<revision>[^<]+<\/revision>/{gsub(/<revision>|<\/revision>/,"",$1);print $1;exit;}' ./dubbo/pom.xml`
|
|
||||||
echo "version=$REVISION" >> $GITHUB_OUTPUT
|
|
||||||
echo "dubbo version: $REVISION"
|
|
||||||
|
|
||||||
unit-test-prepare:
|
|
||||||
name: " Preparation for Unit Test On ${{ matrix.os }}"
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ ubuntu-latest, windows-latest ]
|
|
||||||
env:
|
|
||||||
ZOOKEEPER_VERSION: 3.6.3
|
|
||||||
steps:
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache zookeeper binary archive"
|
|
||||||
id: "cache-zookeeper"
|
|
||||||
with:
|
|
||||||
path: ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
key: zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
|
||||||
restore-keys: |
|
|
||||||
zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
|
||||||
- name: "Set up msys2 if necessary"
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') && steps.cache-zookeeper.outputs.cache-hit != 'true' }}
|
|
||||||
uses: msys2/setup-msys2@v2
|
|
||||||
with:
|
|
||||||
release: false # support cache, see https://github.com/msys2/setup-msys2#context
|
|
||||||
- name: "Download zookeeper binary archive in Linux OS"
|
|
||||||
if: ${{ startsWith( matrix.os, 'ubuntu') && steps.cache-zookeeper.outputs.cache-hit != 'true' }}
|
|
||||||
run: |
|
|
||||||
mkdir -p ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
wget -c https://archive.apache.org/dist/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c https://apache.website-solution.net/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://apache.stu.edu.tw/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://ftp.jaist.ac.jp/pub/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://apache.mirror.cdnetworks.com/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://mirror.apache-kr.org/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
|
||||||
echo "list the downloaded zookeeper binary archive"
|
|
||||||
ls -al ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
|
||||||
- name: "Download zookeeper binary archive in Windows OS"
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') && steps.cache-zookeeper.outputs.cache-hit != 'true' }}
|
|
||||||
shell: msys2 {0}
|
|
||||||
run: |
|
|
||||||
mkdir -p ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
wget -c https://archive.apache.org/dist/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c https://apache.website-solution.net/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://apache.stu.edu.tw/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://ftp.jaist.ac.jp/pub/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://apache.mirror.cdnetworks.com/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://mirror.apache-kr.org/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
|
||||||
echo "list the downloaded zookeeper binary archive"
|
|
||||||
ls -al ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
|
||||||
|
|
||||||
unit-test:
|
|
||||||
needs: [build-source, unit-test-prepare]
|
|
||||||
name: "Unit Test On ${{ matrix.os }} (JDK: ${{ matrix.jdk }})"
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ ubuntu-latest, windows-latest ]
|
|
||||||
jdk: [ 8, 11, 17, 21 ]
|
|
||||||
env:
|
|
||||||
DISABLE_FILE_SYSTEM_TEST: true
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
ref: "3.2"
|
|
||||||
- name: "Set up JDK ${{ matrix.jdk }}"
|
|
||||||
uses: actions/setup-java@v1
|
|
||||||
with:
|
|
||||||
java-version: ${{ matrix.jdk }}
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache local Maven repository"
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache zookeeper binary archive"
|
|
||||||
id: "cache-zookeeper"
|
|
||||||
with:
|
|
||||||
path: ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
key: zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
|
||||||
restore-keys: |
|
|
||||||
zookeeper-${{ runner.os }}-
|
|
||||||
- name: "Test with Maven with Integration Tests"
|
|
||||||
timeout-minutes: 70
|
|
||||||
if: ${{ startsWith( matrix.os, 'ubuntu') }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Pjacoco -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
- name: "Test with Maven without Integration Tests"
|
|
||||||
timeout-minutes: 90
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Pjacoco -D"http.keepAlive=false" -D"maven.wagon.http.pool=false" -D"maven.wagon.httpconnectionManager.ttlSeconds=120" -D"maven.wagon.http.retryHandler.count=5" -DskipTests=false -DskipIntegrationTests=true -D"checkstyle.skip=false" -D"checkstyle_unix.skip=true" -D"rat.skip=false" -D"maven.javadoc.skip=true" -D"embeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper"
|
|
||||||
|
|
||||||
unit-test-fastjson2:
|
|
||||||
needs: [build-source, unit-test-prepare]
|
|
||||||
name: "Unit Test On ${{ matrix.os }} (JDK: ${{ matrix.jdk }}, Serialization: fastjson2)"
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ ubuntu-latest, windows-latest ]
|
|
||||||
jdk: [ 8, 11, 17, 21 ]
|
|
||||||
env:
|
|
||||||
DISABLE_FILE_SYSTEM_TEST: true
|
|
||||||
DUBBO_DEFAULT_SERIALIZATION: fastjson2
|
|
||||||
MAVEN_SUREFIRE_ADD_OPENS: true
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: "Set up JDK ${{ matrix.jdk }}"
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: ${{ matrix.jdk }}
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache local Maven repository"
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache zookeeper binary archive"
|
|
||||||
id: "cache-zookeeper"
|
|
||||||
with:
|
|
||||||
path: ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
key: zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
|
||||||
restore-keys: |
|
|
||||||
zookeeper-${{ runner.os }}-
|
|
||||||
- name: "Test with Maven with Integration Tests on JDK 8"
|
|
||||||
timeout-minutes: 70
|
|
||||||
if: ${{ startsWith( matrix.os, 'ubuntu') && matrix.jdk == '8' }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Pjacoco,'!jdk15ge' -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
- name: "Test with Maven without Integration Tests on JDK 8"
|
|
||||||
timeout-minutes: 90
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') && matrix.jdk == '8' }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -P"jacoco,'!jdk15ge'" -D"http.keepAlive=false" -D"maven.wagon.http.pool=false" -D"maven.wagon.httpconnectionManager.ttlSeconds=120" -D"maven.wagon.http.retryHandler.count=5" -DskipTests=false -DskipIntegrationTests=true -D"checkstyle.skip=false" -D"checkstyle_unix.skip=true" -D"rat.skip=false" -D"maven.javadoc.skip=true" -D"embeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper"
|
|
||||||
- name: "Test with Maven with Integration Tests"
|
|
||||||
timeout-minutes: 70
|
|
||||||
if: ${{ startsWith( matrix.os, 'ubuntu') && matrix.jdk != '8' }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Pjacoco,jdk15ge-simple,'!jdk15ge' -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
- name: "Test with Maven without Integration Tests"
|
|
||||||
timeout-minutes: 90
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') && matrix.jdk != '8' }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -P"jacoco,jdk15ge-simple,'!jdk15ge'" -D"http.keepAlive=false" -D"maven.wagon.http.pool=false" -D"maven.wagon.httpconnectionManager.ttlSeconds=120" -D"maven.wagon.http.retryHandler.count=5" -DskipTests=false -DskipIntegrationTests=true -D"checkstyle.skip=false" -D"checkstyle_unix.skip=true" -D"rat.skip=false" -D"maven.javadoc.skip=true" -D"embeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper"
|
|
||||||
|
|
||||||
samples-test-prepare:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
JOB_COUNT: 5
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-samples'
|
|
||||||
ref: master
|
|
||||||
- name: "Prepare test list"
|
|
||||||
run: |
|
|
||||||
bash ./test/scripts/prepare-test.sh
|
|
||||||
- name: "Upload test list"
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-test-list
|
|
||||||
path: test/jobs
|
|
||||||
samples-test-job:
|
|
||||||
needs: [build-source, samples-test-prepare]
|
|
||||||
name: "Samples Test on ubuntu-latest (JobId: ${{matrix.job_id}} JavaVer: ${{matrix.jdk}})"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 90
|
|
||||||
env:
|
|
||||||
JAVA_VER: ${{matrix.jdk}}
|
|
||||||
TEST_CASE_FILE: jobs/testjob_${{matrix.job_id}}.txt
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
jdk: [ 8, 11, 17, 21 ]
|
|
||||||
job_id: [1, 2, 3, 4, 5]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-samples'
|
|
||||||
ref: master
|
|
||||||
- name: "Cache local Maven repository"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- name: "Restore Dubbo cache"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository/org/apache/dubbo
|
|
||||||
key: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-dubbo-snapshot-${{ github.sha }}
|
|
||||||
${{ runner.os }}-dubbo-snapshot-
|
|
||||||
- name: "Download test list"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-test-list
|
|
||||||
path: test/jobs/
|
|
||||||
- name: "Set up JDK ${{matrix.jdk}}"
|
|
||||||
uses: actions/setup-java@v1
|
|
||||||
with:
|
|
||||||
java-version: ${{matrix.jdk}}
|
|
||||||
- name: "Init Candidate Versions"
|
|
||||||
run: |
|
|
||||||
DUBBO_VERSION="${{needs.build-source.outputs.version}}"
|
|
||||||
CANDIDATE_VERSIONS="dubbo.version:$DUBBO_VERSION;compiler.version:$DUBBO_VERSION;$CANDIDATE_VERSIONS;dubbo.compiler.version:$DUBBO_VERSION"
|
|
||||||
echo "CANDIDATE_VERSIONS=$CANDIDATE_VERSIONS" >> $GITHUB_ENV
|
|
||||||
- name: "Build test image"
|
|
||||||
run: |
|
|
||||||
cd test && bash ./build-test-image.sh
|
|
||||||
- name: "Run tests"
|
|
||||||
run: cd test && bash ./run-tests.sh
|
|
||||||
- name: "Upload test result"
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-test-result-${{matrix.jdk}}
|
|
||||||
path: test/jobs/*-result*
|
|
||||||
samples-test-result:
|
|
||||||
needs: [samples-test-job]
|
|
||||||
if: always()
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
JAVA_VER: ${{matrix.jdk}}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
jdk: [ 8, 11, 17, 21 ]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-samples'
|
|
||||||
ref: master
|
|
||||||
- name: "Download test result"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-test-result-${{matrix.jdk}}
|
|
||||||
path: test/jobs/
|
|
||||||
- name: "Merge test result"
|
|
||||||
run: ./test/scripts/merge-test-results.sh
|
|
||||||
|
|
||||||
integration-test-prepare:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
JOB_COUNT: 5
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-integration-cases'
|
|
||||||
ref: main
|
|
||||||
- name: "Prepare test list"
|
|
||||||
run: |
|
|
||||||
bash ./test/scripts/prepare-test.sh
|
|
||||||
- name: "Upload test list"
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: integration-test-list
|
|
||||||
path: test/jobs
|
|
||||||
integration-test-job:
|
|
||||||
needs: [build-source, integration-test-prepare]
|
|
||||||
name: "Integration Test on ubuntu-latest (JobId: ${{matrix.job_id}} JavaVer: ${{matrix.jdk}})"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 90
|
|
||||||
env:
|
|
||||||
JAVA_VER: ${{matrix.jdk}}
|
|
||||||
TEST_CASE_FILE: jobs/testjob_${{matrix.job_id}}.txt
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
jdk: [ 8, 11, 17, 21 ]
|
|
||||||
job_id: [1, 2, 3, 4, 5]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-integration-cases'
|
|
||||||
ref: main
|
|
||||||
- name: "Cache local Maven repository"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- name: "Restore Dubbo cache"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository/org/apache/dubbo
|
|
||||||
key: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-dubbo-snapshot-${{ github.sha }}
|
|
||||||
${{ runner.os }}-dubbo-snapshot-
|
|
||||||
- name: "Download test list"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: integration-test-list
|
|
||||||
path: test/jobs/
|
|
||||||
- name: "Set up JDK ${{matrix.jdk}}"
|
|
||||||
uses: actions/setup-java@v1
|
|
||||||
with:
|
|
||||||
java-version: ${{matrix.jdk}}
|
|
||||||
- name: "Init Candidate Versions"
|
|
||||||
run: |
|
|
||||||
DUBBO_VERSION="${{needs.build-source.outputs.version}}"
|
|
||||||
CANDIDATE_VERSIONS="dubbo.version:$DUBBO_VERSION;compiler.version:$DUBBO_VERSION;$CANDIDATE_VERSIONS;dubbo.compiler.version:$DUBBO_VERSION"
|
|
||||||
echo "CANDIDATE_VERSIONS=$CANDIDATE_VERSIONS" >> $GITHUB_ENV
|
|
||||||
- name: "Build test image"
|
|
||||||
run: |
|
|
||||||
cd test && bash ./build-test-image.sh
|
|
||||||
- name: "Run tests"
|
|
||||||
run: cd test && bash ./run-tests.sh
|
|
||||||
- name: "Upload test result"
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: integration-test-result-${{matrix.jdk}}
|
|
||||||
path: test/jobs/*-result*
|
|
||||||
integration-test-result:
|
|
||||||
needs: [integration-test-job]
|
|
||||||
if: always()
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
JAVA_VER: ${{matrix.jdk}}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
jdk: [ 8, 11, 17, 21 ]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-integration-cases'
|
|
||||||
ref: main
|
|
||||||
- name: "Download test result"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: integration-test-result-${{matrix.jdk}}
|
|
||||||
path: test/jobs/
|
|
||||||
- name: "Merge test result"
|
|
||||||
run: ./test/scripts/merge-test-results.sh
|
|
||||||
|
|
||||||
error-code-inspecting:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
ref: "3.2"
|
|
||||||
path: "./dubbo"
|
|
||||||
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-test-tools'
|
|
||||||
ref: main
|
|
||||||
path: "./dubbo-test-tools"
|
|
||||||
|
|
||||||
- name: "Set up JDK 21"
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 21
|
|
||||||
|
|
||||||
- name: "Compile Dubbo (Linux)"
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo
|
|
||||||
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean install -DskipTests=true -DskipIntegrationTests=true -Dcheckstyle.skip=true -Dcheckstyle_unix.skip=true -Drat.skip=true -Dmaven.javadoc.skip=true
|
|
||||||
- name: "Run Error Code Inspecting"
|
|
||||||
env:
|
|
||||||
DUBBO_ECI_REPORT_AS_ERROR: true
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo-test-tools/dubbo-error-code-inspector
|
|
||||||
../mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C package exec:java -Ddubbo.eci.report-as-error=${DUBBO_ECI_REPORT_AS_ERROR} -Dmaven.test.skip=true -Dmaven.test.skip.exec=true -Ddubbo.eci.path=${{ github.workspace }}/dubbo
|
|
||||||
|
|
||||||
- name: "Upload error code inspection result"
|
|
||||||
# always() should not be used here, since we don't need to handle the 'canceled' situation.
|
|
||||||
if: ${{ success() || failure() }}
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: "error-inspection-result"
|
|
||||||
path: ${{ github.workspace }}/dubbo-test-tools/dubbo-error-code-inspector/error-inspection-result.txt
|
|
||||||
|
|
||||||
native-image-inspecting:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
ref: "3.2"
|
|
||||||
path: "./dubbo"
|
|
||||||
|
|
||||||
- name: "Setup GraalVM environment"
|
|
||||||
uses: graalvm/setup-graalvm@v1
|
|
||||||
with:
|
|
||||||
version: '22.3.0'
|
|
||||||
java-version: '17'
|
|
||||||
components: 'native-image'
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
native-image-job-reports: 'true'
|
|
||||||
|
|
||||||
- name: "Setup Zookeeper environment"
|
|
||||||
run: |
|
|
||||||
wget https://dlcdn.apache.org/zookeeper/zookeeper-3.8.4/apache-zookeeper-3.8.4-bin.tar.gz
|
|
||||||
tar -zxvf apache-zookeeper-3.8.4-bin.tar.gz
|
|
||||||
mv apache-zookeeper-3.8.4-bin/conf/zoo_sample.cfg apache-zookeeper-3.8.4-bin/conf/zoo.cfg
|
|
||||||
apache-zookeeper-3.8.4-bin/bin/zkServer.sh start
|
|
||||||
|
|
||||||
- name: "Check environment"
|
|
||||||
run: |
|
|
||||||
java --version
|
|
||||||
native-image --version
|
|
||||||
|
|
||||||
- name: "Compile Dubbo (Linux)"
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo
|
|
||||||
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean install -DskipTests=true -DskipIntegrationTests=true -Dcheckstyle.skip=true -Dcheckstyle_unix.skip=true -Drat.skip=true -Dmaven.javadoc.skip=true
|
|
||||||
|
|
||||||
- name: "Compile and run Dubbo demo for native (Linux)"
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo/dubbo-demo/dubbo-demo-native/dubbo-demo-native-provider
|
|
||||||
${{ github.workspace }}/dubbo/mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean package -P native -Dmaven.test.skip=true native:compile
|
|
||||||
nohup ./target/dubbo-demo-native-provider &
|
|
||||||
cd ${{ github.workspace }}/dubbo/dubbo-demo/dubbo-demo-native/dubbo-demo-native-consumer
|
|
||||||
${{ github.workspace }}/dubbo/mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean package -P native -Dmaven.test.skip=true native:compile
|
|
||||||
./target/dubbo-demo-native-consumer
|
|
||||||
|
|
@ -1,502 +0,0 @@
|
||||||
name: Build and Test Scheduled On 3.3
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0/6 * * *'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
env:
|
|
||||||
FORK_COUNT: 2
|
|
||||||
FAIL_FAST: 0
|
|
||||||
SHOW_ERROR_DETAIL: 1
|
|
||||||
#multi-version size limit
|
|
||||||
VERSIONS_LIMIT: 4
|
|
||||||
ALL_REMOTE_VERSION: true
|
|
||||||
CANDIDATE_VERSIONS: '
|
|
||||||
spring.version:5.3.24;
|
|
||||||
spring-boot.version:2.7.6;
|
|
||||||
'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
license:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
ref: "3.3"
|
|
||||||
- name: Check License
|
|
||||||
uses: apache/skywalking-eyes@main
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
build-source:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
version: ${{ steps.dubbo-version.outputs.version }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
ref: "3.3"
|
|
||||||
path: dubbo
|
|
||||||
- uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 21
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache local Maven repository"
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- name: "Dubbo cache"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository/org/apache/dubbo
|
|
||||||
key: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }}-${{ github.run_id }}
|
|
||||||
- name: "Build Dubbo with Maven"
|
|
||||||
run: |
|
|
||||||
cd ./dubbo
|
|
||||||
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean source:jar install -Pjacoco,checkstyle -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -Dmaven.test.skip=true -Dmaven.test.skip.exec=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
- name: "Pack checkstyle file if failure"
|
|
||||||
if: failure()
|
|
||||||
run: 7z a ${{ github.workspace }}/checkstyle.zip *checkstyle* -r
|
|
||||||
- name: "Upload checkstyle file if failure"
|
|
||||||
if: failure()
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: "checkstyle-file"
|
|
||||||
path: ${{ github.workspace }}/checkstyle.zip
|
|
||||||
- name: "Calculate Dubbo Version"
|
|
||||||
id: dubbo-version
|
|
||||||
run: |
|
|
||||||
REVISION=`awk '/<revision>[^<]+<\/revision>/{gsub(/<revision>|<\/revision>/,"",$1);print $1;exit;}' ./dubbo/pom.xml`
|
|
||||||
echo "version=$REVISION" >> $GITHUB_OUTPUT
|
|
||||||
echo "dubbo version: $REVISION"
|
|
||||||
|
|
||||||
unit-test-prepare:
|
|
||||||
name: " Preparation for Unit Test On ${{ matrix.os }}"
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ ubuntu-latest, windows-latest ]
|
|
||||||
env:
|
|
||||||
ZOOKEEPER_VERSION: 3.6.3
|
|
||||||
steps:
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache zookeeper binary archive"
|
|
||||||
id: "cache-zookeeper"
|
|
||||||
with:
|
|
||||||
path: ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
key: zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
|
||||||
restore-keys: |
|
|
||||||
zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
|
||||||
- name: "Set up msys2 if necessary"
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') && steps.cache-zookeeper.outputs.cache-hit != 'true' }}
|
|
||||||
uses: msys2/setup-msys2@v2
|
|
||||||
with:
|
|
||||||
release: false # support cache, see https://github.com/msys2/setup-msys2#context
|
|
||||||
- name: "Download zookeeper binary archive in Linux OS"
|
|
||||||
if: ${{ startsWith( matrix.os, 'ubuntu') && steps.cache-zookeeper.outputs.cache-hit != 'true' }}
|
|
||||||
run: |
|
|
||||||
mkdir -p ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
wget -c https://archive.apache.org/dist/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c https://apache.website-solution.net/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://apache.stu.edu.tw/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://ftp.jaist.ac.jp/pub/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://apache.mirror.cdnetworks.com/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://mirror.apache-kr.org/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
|
||||||
echo "list the downloaded zookeeper binary archive"
|
|
||||||
ls -al ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
|
||||||
- name: "Download zookeeper binary archive in Windows OS"
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') && steps.cache-zookeeper.outputs.cache-hit != 'true' }}
|
|
||||||
shell: msys2 {0}
|
|
||||||
run: |
|
|
||||||
mkdir -p ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
wget -c https://archive.apache.org/dist/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c https://apache.website-solution.net/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://apache.stu.edu.tw/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://ftp.jaist.ac.jp/pub/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://apache.mirror.cdnetworks.com/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://mirror.apache-kr.org/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
|
||||||
echo "list the downloaded zookeeper binary archive"
|
|
||||||
ls -al ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
|
||||||
|
|
||||||
unit-test:
|
|
||||||
needs: [build-source, unit-test-prepare]
|
|
||||||
name: "Unit Test On ${{ matrix.os }} (JDK: ${{ matrix.jdk }})"
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ ubuntu-latest, windows-latest ]
|
|
||||||
jdk: [ 8, 11, 17, 21 ]
|
|
||||||
env:
|
|
||||||
DISABLE_FILE_SYSTEM_TEST: true
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
ref: "3.3"
|
|
||||||
- name: "Set up JDK ${{ matrix.jdk }}"
|
|
||||||
uses: actions/setup-java@v1
|
|
||||||
with:
|
|
||||||
java-version: ${{ matrix.jdk }}
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache local Maven repository"
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache zookeeper binary archive"
|
|
||||||
id: "cache-zookeeper"
|
|
||||||
with:
|
|
||||||
path: ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
key: zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
|
||||||
restore-keys: |
|
|
||||||
zookeeper-${{ runner.os }}-
|
|
||||||
- name: "Test with Maven with Integration Tests"
|
|
||||||
timeout-minutes: 70
|
|
||||||
if: ${{ startsWith( matrix.os, 'ubuntu') }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Pjacoco -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
- name: "Test with Maven without Integration Tests"
|
|
||||||
timeout-minutes: 90
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Pjacoco -D"http.keepAlive=false" -D"maven.wagon.http.pool=false" -D"maven.wagon.httpconnectionManager.ttlSeconds=120" -D"maven.wagon.http.retryHandler.count=5" -DskipTests=false -DskipIntegrationTests=true -D"checkstyle.skip=false" -D"checkstyle_unix.skip=true" -D"rat.skip=false" -D"maven.javadoc.skip=true" -D"embeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper"
|
|
||||||
|
|
||||||
unit-test-fastjson2:
|
|
||||||
needs: [build-source, unit-test-prepare]
|
|
||||||
name: "Unit Test On ${{ matrix.os }} (JDK: ${{ matrix.jdk }}, Serialization: fastjson2)"
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ ubuntu-latest, windows-latest ]
|
|
||||||
jdk: [ 8, 11, 17, 21 ]
|
|
||||||
env:
|
|
||||||
DISABLE_FILE_SYSTEM_TEST: true
|
|
||||||
DUBBO_DEFAULT_SERIALIZATION: fastjson2
|
|
||||||
MAVEN_SUREFIRE_ADD_OPENS: true
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: "Set up JDK ${{ matrix.jdk }}"
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: ${{ matrix.jdk }}
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache local Maven repository"
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache zookeeper binary archive"
|
|
||||||
id: "cache-zookeeper"
|
|
||||||
with:
|
|
||||||
path: ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
key: zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
|
||||||
restore-keys: |
|
|
||||||
zookeeper-${{ runner.os }}-
|
|
||||||
- name: "Test with Maven with Integration Tests on JDK 8"
|
|
||||||
timeout-minutes: 70
|
|
||||||
if: ${{ startsWith( matrix.os, 'ubuntu') && matrix.jdk == '8' }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Pjacoco,'!jdk15ge' -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
- name: "Test with Maven without Integration Tests on JDK 8"
|
|
||||||
timeout-minutes: 90
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') && matrix.jdk == '8' }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -P"jacoco,'!jdk15ge'" -D"http.keepAlive=false" -D"maven.wagon.http.pool=false" -D"maven.wagon.httpconnectionManager.ttlSeconds=120" -D"maven.wagon.http.retryHandler.count=5" -DskipTests=false -DskipIntegrationTests=true -D"checkstyle.skip=false" -D"checkstyle_unix.skip=true" -D"rat.skip=false" -D"maven.javadoc.skip=true" -D"embeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper"
|
|
||||||
- name: "Test with Maven with Integration Tests"
|
|
||||||
timeout-minutes: 70
|
|
||||||
if: ${{ startsWith( matrix.os, 'ubuntu') && matrix.jdk != '8' }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Pjacoco,jdk15ge-simple,'!jdk15ge' -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
- name: "Test with Maven without Integration Tests"
|
|
||||||
timeout-minutes: 90
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') && matrix.jdk != '8' }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -P"jacoco,jdk15ge-simple,'!jdk15ge'" -D"http.keepAlive=false" -D"maven.wagon.http.pool=false" -D"maven.wagon.httpconnectionManager.ttlSeconds=120" -D"maven.wagon.http.retryHandler.count=5" -DskipTests=false -DskipIntegrationTests=true -D"checkstyle.skip=false" -D"checkstyle_unix.skip=true" -D"rat.skip=false" -D"maven.javadoc.skip=true" -D"embeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper"
|
|
||||||
|
|
||||||
samples-test-prepare:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
JOB_COUNT: 5
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-samples'
|
|
||||||
ref: master
|
|
||||||
- name: "Prepare test list"
|
|
||||||
run: |
|
|
||||||
bash ./test/scripts/prepare-test.sh
|
|
||||||
- name: "Upload test list"
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-test-list
|
|
||||||
path: test/jobs
|
|
||||||
samples-test-job:
|
|
||||||
needs: [build-source, samples-test-prepare]
|
|
||||||
name: "Samples Test on ubuntu-latest (JobId: ${{matrix.job_id}} JavaVer: ${{matrix.jdk}})"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 90
|
|
||||||
env:
|
|
||||||
JAVA_VER: ${{matrix.jdk}}
|
|
||||||
TEST_CASE_FILE: jobs/testjob_${{matrix.job_id}}.txt
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
jdk: [ 8, 11, 17, 21 ]
|
|
||||||
job_id: [1, 2, 3, 4, 5]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-samples'
|
|
||||||
ref: master
|
|
||||||
- name: "Cache local Maven repository"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- name: "Restore Dubbo cache"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository/org/apache/dubbo
|
|
||||||
key: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-dubbo-snapshot-${{ github.sha }}
|
|
||||||
${{ runner.os }}-dubbo-snapshot-
|
|
||||||
- name: "Download test list"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-test-list
|
|
||||||
path: test/jobs/
|
|
||||||
- name: "Set up JDK ${{matrix.jdk}}"
|
|
||||||
uses: actions/setup-java@v1
|
|
||||||
with:
|
|
||||||
java-version: ${{matrix.jdk}}
|
|
||||||
- name: "Init Candidate Versions"
|
|
||||||
run: |
|
|
||||||
DUBBO_VERSION="${{needs.build-source.outputs.version}}"
|
|
||||||
CANDIDATE_VERSIONS="dubbo.version:$DUBBO_VERSION;compiler.version:$DUBBO_VERSION;$CANDIDATE_VERSIONS;dubbo.compiler.version:$DUBBO_VERSION"
|
|
||||||
echo "CANDIDATE_VERSIONS=$CANDIDATE_VERSIONS" >> $GITHUB_ENV
|
|
||||||
- name: "Build test image"
|
|
||||||
run: |
|
|
||||||
cd test && bash ./build-test-image.sh
|
|
||||||
- name: "Run tests"
|
|
||||||
run: cd test && bash ./run-tests.sh
|
|
||||||
- name: "Upload test result"
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-test-result-${{matrix.jdk}}
|
|
||||||
path: test/jobs/*-result*
|
|
||||||
samples-test-result:
|
|
||||||
needs: [samples-test-job]
|
|
||||||
if: always()
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
JAVA_VER: ${{matrix.jdk}}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
jdk: [ 8, 11, 17, 21 ]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-samples'
|
|
||||||
ref: master
|
|
||||||
- name: "Download test result"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-test-result-${{matrix.jdk}}
|
|
||||||
path: test/jobs/
|
|
||||||
- name: "Merge test result"
|
|
||||||
run: ./test/scripts/merge-test-results.sh
|
|
||||||
|
|
||||||
integration-test-prepare:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
JOB_COUNT: 5
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-integration-cases'
|
|
||||||
ref: main
|
|
||||||
- name: "Prepare test list"
|
|
||||||
run: |
|
|
||||||
bash ./test/scripts/prepare-test.sh
|
|
||||||
- name: "Upload test list"
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: integration-test-list
|
|
||||||
path: test/jobs
|
|
||||||
integration-test-job:
|
|
||||||
needs: [build-source, integration-test-prepare]
|
|
||||||
name: "Integration Test on ubuntu-latest (JobId: ${{matrix.job_id}} JavaVer: ${{matrix.jdk}})"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 90
|
|
||||||
env:
|
|
||||||
JAVA_VER: ${{matrix.jdk}}
|
|
||||||
TEST_CASE_FILE: jobs/testjob_${{matrix.job_id}}.txt
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
jdk: [ 8, 11, 17, 21 ]
|
|
||||||
job_id: [1, 2, 3, 4, 5]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-integration-cases'
|
|
||||||
ref: main
|
|
||||||
- name: "Cache local Maven repository"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- name: "Restore Dubbo cache"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository/org/apache/dubbo
|
|
||||||
key: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-dubbo-snapshot-${{ github.sha }}
|
|
||||||
${{ runner.os }}-dubbo-snapshot-
|
|
||||||
- name: "Download test list"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: integration-test-list
|
|
||||||
path: test/jobs/
|
|
||||||
- name: "Set up JDK ${{matrix.jdk}}"
|
|
||||||
uses: actions/setup-java@v1
|
|
||||||
with:
|
|
||||||
java-version: ${{matrix.jdk}}
|
|
||||||
- name: "Init Candidate Versions"
|
|
||||||
run: |
|
|
||||||
DUBBO_VERSION="${{needs.build-source.outputs.version}}"
|
|
||||||
CANDIDATE_VERSIONS="dubbo.version:$DUBBO_VERSION;compiler.version:$DUBBO_VERSION;$CANDIDATE_VERSIONS;dubbo.compiler.version:$DUBBO_VERSION"
|
|
||||||
echo "CANDIDATE_VERSIONS=$CANDIDATE_VERSIONS" >> $GITHUB_ENV
|
|
||||||
- name: "Build test image"
|
|
||||||
run: |
|
|
||||||
cd test && bash ./build-test-image.sh
|
|
||||||
- name: "Run tests"
|
|
||||||
run: cd test && bash ./run-tests.sh
|
|
||||||
- name: "Upload test result"
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: integration-test-result-${{matrix.jdk}}
|
|
||||||
path: test/jobs/*-result*
|
|
||||||
integration-test-result:
|
|
||||||
needs: [integration-test-job]
|
|
||||||
if: always()
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
JAVA_VER: ${{matrix.jdk}}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
jdk: [ 8, 11, 17, 21 ]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-integration-cases'
|
|
||||||
ref: main
|
|
||||||
- name: "Download test result"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: integration-test-result-${{matrix.jdk}}
|
|
||||||
path: test/jobs/
|
|
||||||
- name: "Merge test result"
|
|
||||||
run: ./test/scripts/merge-test-results.sh
|
|
||||||
|
|
||||||
error-code-inspecting:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
ref: "3.3"
|
|
||||||
path: "./dubbo"
|
|
||||||
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-test-tools'
|
|
||||||
ref: main
|
|
||||||
path: "./dubbo-test-tools"
|
|
||||||
|
|
||||||
- name: "Set up JDK 21"
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 21
|
|
||||||
|
|
||||||
- name: "Compile Dubbo (Linux)"
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo
|
|
||||||
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean install -DskipTests=true -DskipIntegrationTests=true -Dcheckstyle.skip=true -Dcheckstyle_unix.skip=true -Drat.skip=true -Dmaven.javadoc.skip=true
|
|
||||||
- name: "Run Error Code Inspecting"
|
|
||||||
env:
|
|
||||||
DUBBO_ECI_REPORT_AS_ERROR: true
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo-test-tools/dubbo-error-code-inspector
|
|
||||||
../mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C package exec:java -Ddubbo.eci.report-as-error=${DUBBO_ECI_REPORT_AS_ERROR} -Dmaven.test.skip=true -Dmaven.test.skip.exec=true -Ddubbo.eci.path=${{ github.workspace }}/dubbo
|
|
||||||
|
|
||||||
- name: "Upload error code inspection result"
|
|
||||||
# always() should not be used here, since we don't need to handle the 'canceled' situation.
|
|
||||||
if: ${{ success() || failure() }}
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: "error-inspection-result"
|
|
||||||
path: ${{ github.workspace }}/dubbo-test-tools/dubbo-error-code-inspector/error-inspection-result.txt
|
|
||||||
|
|
||||||
native-image-inspecting:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
ref: "3.3"
|
|
||||||
path: "./dubbo"
|
|
||||||
|
|
||||||
- name: "Setup GraalVM environment"
|
|
||||||
uses: graalvm/setup-graalvm@v1
|
|
||||||
with:
|
|
||||||
version: '22.3.0'
|
|
||||||
java-version: '17'
|
|
||||||
components: 'native-image'
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
native-image-job-reports: 'true'
|
|
||||||
|
|
||||||
- name: "Setup Zookeeper environment"
|
|
||||||
run: |
|
|
||||||
wget https://dlcdn.apache.org/zookeeper/zookeeper-3.8.4/apache-zookeeper-3.8.4-bin.tar.gz
|
|
||||||
tar -zxvf apache-zookeeper-3.8.4-bin.tar.gz
|
|
||||||
mv apache-zookeeper-3.8.4-bin/conf/zoo_sample.cfg apache-zookeeper-3.8.4-bin/conf/zoo.cfg
|
|
||||||
apache-zookeeper-3.8.4-bin/bin/zkServer.sh start
|
|
||||||
|
|
||||||
- name: "Check environment"
|
|
||||||
run: |
|
|
||||||
java --version
|
|
||||||
native-image --version
|
|
||||||
|
|
||||||
- name: "Compile Dubbo (Linux)"
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo
|
|
||||||
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean install -DskipTests=true -DskipIntegrationTests=true -Dcheckstyle.skip=true -Dcheckstyle_unix.skip=true -Drat.skip=true -Dmaven.javadoc.skip=true
|
|
||||||
|
|
||||||
- name: "Compile and run Dubbo demo for native (Linux)"
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo/dubbo-demo/dubbo-demo-native/dubbo-demo-native-provider
|
|
||||||
${{ github.workspace }}/dubbo/mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean package -P native -Dmaven.test.skip=true native:compile
|
|
||||||
nohup ./target/dubbo-demo-native-provider &
|
|
||||||
cd ${{ github.workspace }}/dubbo/dubbo-demo/dubbo-demo-native/dubbo-demo-native-consumer
|
|
||||||
${{ github.workspace }}/dubbo/mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean package -P native -Dmaven.test.skip=true native:compile
|
|
||||||
./target/dubbo-demo-native-consumer
|
|
||||||
|
|
@ -1,497 +0,0 @@
|
||||||
name: Release Test
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- '**-release'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
env:
|
|
||||||
FORK_COUNT: 2
|
|
||||||
FAIL_FAST: 0
|
|
||||||
SHOW_ERROR_DETAIL: 1
|
|
||||||
#multi-version size limit
|
|
||||||
VERSIONS_LIMIT: 4
|
|
||||||
ALL_REMOTE_VERSION: true
|
|
||||||
CANDIDATE_VERSIONS: '
|
|
||||||
spring.version:5.3.24;
|
|
||||||
spring-boot.version:2.7.6;
|
|
||||||
'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
license:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Check License
|
|
||||||
uses: apache/skywalking-eyes@main
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
build-source:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
version: ${{ steps.dubbo-version.outputs.version }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
path: dubbo
|
|
||||||
- uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: 8
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache local Maven repository"
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- name: "Dubbo cache"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository/org/apache/dubbo
|
|
||||||
key: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }}-${{ github.run_id }}
|
|
||||||
- name: "Build Dubbo with Maven"
|
|
||||||
run: |
|
|
||||||
cd ./dubbo
|
|
||||||
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean source:jar install -Pjacoco,checkstyle -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -Dmaven.test.skip=true -Dmaven.test.skip.exec=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
- name: "Pack checkstyle file if failure"
|
|
||||||
if: failure()
|
|
||||||
run: 7z a ${{ github.workspace }}/checkstyle.zip *checkstyle* -r
|
|
||||||
- name: "Upload checkstyle file if failure"
|
|
||||||
if: failure()
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: "checkstyle-file"
|
|
||||||
path: ${{ github.workspace }}/checkstyle.zip
|
|
||||||
- name: "Calculate Dubbo Version"
|
|
||||||
id: dubbo-version
|
|
||||||
run: |
|
|
||||||
REVISION=`awk '/<revision>[^<]+<\/revision>/{gsub(/<revision>|<\/revision>/,"",$1);print $1;exit;}' ./dubbo/pom.xml`
|
|
||||||
echo "version=$REVISION" >> $GITHUB_OUTPUT
|
|
||||||
echo "dubbo version: $REVISION"
|
|
||||||
|
|
||||||
unit-test-prepare:
|
|
||||||
name: " Preparation for Unit Test On ${{ matrix.os }}"
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ ubuntu-latest, windows-latest ]
|
|
||||||
env:
|
|
||||||
ZOOKEEPER_VERSION: 3.6.3
|
|
||||||
steps:
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache zookeeper binary archive"
|
|
||||||
id: "cache-zookeeper"
|
|
||||||
with:
|
|
||||||
path: ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
key: zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
|
||||||
restore-keys: |
|
|
||||||
zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
|
||||||
- name: "Set up msys2 if necessary"
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') && steps.cache-zookeeper.outputs.cache-hit != 'true' }}
|
|
||||||
uses: msys2/setup-msys2@v2
|
|
||||||
with:
|
|
||||||
release: false # support cache, see https://github.com/msys2/setup-msys2#context
|
|
||||||
- name: "Download zookeeper binary archive in Linux OS"
|
|
||||||
if: ${{ startsWith( matrix.os, 'ubuntu') && steps.cache-zookeeper.outputs.cache-hit != 'true' }}
|
|
||||||
run: |
|
|
||||||
mkdir -p ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
wget -c https://archive.apache.org/dist/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c https://apache.website-solution.net/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://apache.stu.edu.tw/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://ftp.jaist.ac.jp/pub/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://apache.mirror.cdnetworks.com/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://mirror.apache-kr.org/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
|
||||||
echo "list the downloaded zookeeper binary archive"
|
|
||||||
ls -al ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
|
||||||
- name: "Download zookeeper binary archive in Windows OS"
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') && steps.cache-zookeeper.outputs.cache-hit != 'true' }}
|
|
||||||
shell: msys2 {0}
|
|
||||||
run: |
|
|
||||||
mkdir -p ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
wget -c https://archive.apache.org/dist/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c https://apache.website-solution.net/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://apache.stu.edu.tw/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://ftp.jaist.ac.jp/pub/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://apache.mirror.cdnetworks.com/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz ||
|
|
||||||
wget -c http://mirror.apache-kr.org/apache/zookeeper/zookeeper-${{ env.ZOOKEEPER_VERSION }}/apache-zookeeper-${{ env.ZOOKEEPER_VERSION }}-bin.tar.gz -O ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
|
||||||
echo "list the downloaded zookeeper binary archive"
|
|
||||||
ls -al ${{ github.workspace }}/.tmp/zookeeper/apache-zookeeper-bin.tar.gz
|
|
||||||
|
|
||||||
unit-test:
|
|
||||||
needs: [build-source, unit-test-prepare]
|
|
||||||
name: "Unit Test On ${{ matrix.os }} (JDK: ${{ matrix.jdk }})"
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ ubuntu-latest, windows-latest ]
|
|
||||||
jdk: [ 8, 11, 17, 21 ]
|
|
||||||
env:
|
|
||||||
DISABLE_FILE_SYSTEM_TEST: true
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: "Set up JDK ${{ matrix.jdk }}"
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
java-version: ${{ matrix.jdk }}
|
|
||||||
distribution: 'zulu'
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache local Maven repository"
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache zookeeper binary archive"
|
|
||||||
id: "cache-zookeeper"
|
|
||||||
with:
|
|
||||||
path: ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
key: zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
|
||||||
restore-keys: |
|
|
||||||
zookeeper-${{ runner.os }}-
|
|
||||||
- name: "Test with Maven with Integration Tests"
|
|
||||||
timeout-minutes: 70
|
|
||||||
if: ${{ startsWith( matrix.os, 'ubuntu') }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Pjacoco -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
- name: "Test with Maven without Integration Tests"
|
|
||||||
timeout-minutes: 90
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Pjacoco -D"http.keepAlive=false" -D"maven.wagon.http.pool=false" -D"maven.wagon.httpconnectionManager.ttlSeconds=120" -D"maven.wagon.http.retryHandler.count=5" -DskipTests=false -DskipIntegrationTests=true -D"checkstyle.skip=false" -D"checkstyle_unix.skip=true" -D"rat.skip=false" -D"maven.javadoc.skip=true" -D"embeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper"
|
|
||||||
|
|
||||||
unit-test-fastjson2:
|
|
||||||
needs: [build-source, unit-test-prepare]
|
|
||||||
name: "Unit Test On ${{ matrix.os }} (JDK: ${{ matrix.jdk }}, Serialization: fastjson2)"
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os: [ ubuntu-latest, windows-latest ]
|
|
||||||
jdk: [ 8, 11, 17, 21 ]
|
|
||||||
env:
|
|
||||||
DISABLE_FILE_SYSTEM_TEST: true
|
|
||||||
DUBBO_DEFAULT_SERIALIZATION: fastjson2
|
|
||||||
MAVEN_SUREFIRE_ADD_OPENS: true
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: "Set up JDK ${{ matrix.jdk }}"
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'zulu'
|
|
||||||
java-version: ${{ matrix.jdk }}
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache local Maven repository"
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
name: "Cache zookeeper binary archive"
|
|
||||||
id: "cache-zookeeper"
|
|
||||||
with:
|
|
||||||
path: ${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
key: zookeeper-${{ runner.os }}-${{ env.ZOOKEEPER_VERSION }}
|
|
||||||
restore-keys: |
|
|
||||||
zookeeper-${{ runner.os }}-
|
|
||||||
- name: "Test with Maven with Integration Tests on JDK 8"
|
|
||||||
timeout-minutes: 70
|
|
||||||
if: ${{ startsWith( matrix.os, 'ubuntu') && matrix.jdk == '8' }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Pjacoco,'!jdk15ge' -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
- name: "Test with Maven without Integration Tests on JDK 8"
|
|
||||||
timeout-minutes: 90
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') && matrix.jdk == '8' }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -P"jacoco,'!jdk15ge'" -D"http.keepAlive=false" -D"maven.wagon.http.pool=false" -D"maven.wagon.httpconnectionManager.ttlSeconds=120" -D"maven.wagon.http.retryHandler.count=5" -DskipTests=false -DskipIntegrationTests=true -D"checkstyle.skip=false" -D"checkstyle_unix.skip=true" -D"rat.skip=false" -D"maven.javadoc.skip=true" -D"embeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper"
|
|
||||||
- name: "Test with Maven with Integration Tests"
|
|
||||||
timeout-minutes: 70
|
|
||||||
if: ${{ startsWith( matrix.os, 'ubuntu') && matrix.jdk != '8' }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -Pjacoco,jdk15ge-simple,'!jdk15ge' -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Dcheckstyle_unix.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true -DembeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper
|
|
||||||
- name: "Test with Maven without Integration Tests"
|
|
||||||
timeout-minutes: 90
|
|
||||||
if: ${{ startsWith( matrix.os, 'windows') && matrix.jdk != '8' }}
|
|
||||||
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean test verify -P"jacoco,jdk15ge-simple,'!jdk15ge'" -D"http.keepAlive=false" -D"maven.wagon.http.pool=false" -D"maven.wagon.httpconnectionManager.ttlSeconds=120" -D"maven.wagon.http.retryHandler.count=5" -DskipTests=false -DskipIntegrationTests=true -D"checkstyle.skip=false" -D"checkstyle_unix.skip=true" -D"rat.skip=false" -D"maven.javadoc.skip=true" -D"embeddedZookeeperPath=${{ github.workspace }}/.tmp/zookeeper"
|
|
||||||
|
|
||||||
samples-test-prepare:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
JOB_COUNT: 5
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-samples'
|
|
||||||
ref: master
|
|
||||||
- name: "Prepare test list"
|
|
||||||
run: |
|
|
||||||
bash ./test/scripts/prepare-test.sh
|
|
||||||
- name: "Upload test list"
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-test-list
|
|
||||||
path: test/jobs
|
|
||||||
samples-test-job:
|
|
||||||
needs: [build-source, samples-test-prepare]
|
|
||||||
name: "Samples Test on ubuntu-latest (JobId: ${{matrix.job_id}} JavaVer: ${{matrix.jdk}})"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 90
|
|
||||||
env:
|
|
||||||
JAVA_VER: ${{matrix.jdk}}
|
|
||||||
TEST_CASE_FILE: jobs/testjob_${{matrix.job_id}}.txt
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
jdk: [ 8, 11, 17, 21 ]
|
|
||||||
job_id: [1, 2, 3, 4, 5]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-samples'
|
|
||||||
ref: master
|
|
||||||
- name: "Cache local Maven repository"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- name: "Restore Dubbo cache"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository/org/apache/dubbo
|
|
||||||
key: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-dubbo-snapshot-${{ github.sha }}
|
|
||||||
${{ runner.os }}-dubbo-snapshot-
|
|
||||||
- name: "Download test list"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-test-list
|
|
||||||
path: test/jobs/
|
|
||||||
- name: "Set up JDK ${{matrix.jdk}}"
|
|
||||||
uses: actions/setup-java@v1
|
|
||||||
with:
|
|
||||||
java-version: ${{matrix.jdk}}
|
|
||||||
- name: "Init Candidate Versions"
|
|
||||||
run: |
|
|
||||||
DUBBO_VERSION="${{needs.build-source.outputs.version}}"
|
|
||||||
CANDIDATE_VERSIONS="dubbo.version:$DUBBO_VERSION;compiler.version:$DUBBO_VERSION;$CANDIDATE_VERSIONS;dubbo.compiler.version:$DUBBO_VERSION"
|
|
||||||
echo "CANDIDATE_VERSIONS=$CANDIDATE_VERSIONS" >> $GITHUB_ENV
|
|
||||||
- name: "Build test image"
|
|
||||||
run: |
|
|
||||||
cd test && bash ./build-test-image.sh
|
|
||||||
- name: "Run tests"
|
|
||||||
run: cd test && bash ./run-tests.sh
|
|
||||||
- name: "Upload test result"
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-test-result-${{matrix.jdk}}
|
|
||||||
path: test/jobs/*-result*
|
|
||||||
samples-test-result:
|
|
||||||
needs: [samples-test-job]
|
|
||||||
if: always()
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
JAVA_VER: ${{matrix.jdk}}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
jdk: [ 8, 11, 17, 21 ]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-samples'
|
|
||||||
ref: master
|
|
||||||
- name: "Download test result"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: samples-test-result-${{matrix.jdk}}
|
|
||||||
path: test/jobs/
|
|
||||||
- name: "Merge test result"
|
|
||||||
run: ./test/scripts/merge-test-results.sh
|
|
||||||
|
|
||||||
integration-test-prepare:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
JOB_COUNT: 5
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-integration-cases'
|
|
||||||
ref: main
|
|
||||||
- name: "Prepare test list"
|
|
||||||
run: |
|
|
||||||
bash ./test/scripts/prepare-test.sh
|
|
||||||
- name: "Upload test list"
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: integration-test-list
|
|
||||||
path: test/jobs
|
|
||||||
integration-test-job:
|
|
||||||
needs: [build-source, integration-test-prepare]
|
|
||||||
name: "Integration Test on ubuntu-latest (JobId: ${{matrix.job_id}} JavaVer: ${{matrix.jdk}})"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 90
|
|
||||||
env:
|
|
||||||
JAVA_VER: ${{matrix.jdk}}
|
|
||||||
TEST_CASE_FILE: jobs/testjob_${{matrix.job_id}}.txt
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
jdk: [ 8, 11, 17, 21 ]
|
|
||||||
job_id: [1, 2, 3, 4, 5]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-integration-cases'
|
|
||||||
ref: main
|
|
||||||
- name: "Cache local Maven repository"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository
|
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
||||||
${{ runner.os }}-maven-
|
|
||||||
- name: "Restore Dubbo cache"
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.m2/repository/org/apache/dubbo
|
|
||||||
key: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }}-${{ github.run_id }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-dubbo-snapshot-${{ github.sha }}
|
|
||||||
${{ runner.os }}-dubbo-snapshot-
|
|
||||||
- name: "Download test list"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: integration-test-list
|
|
||||||
path: test/jobs/
|
|
||||||
- name: "Set up JDK ${{matrix.jdk}}"
|
|
||||||
uses: actions/setup-java@v1
|
|
||||||
with:
|
|
||||||
java-version: ${{matrix.jdk}}
|
|
||||||
- name: "Init Candidate Versions"
|
|
||||||
run: |
|
|
||||||
DUBBO_VERSION="${{needs.build-source.outputs.version}}"
|
|
||||||
CANDIDATE_VERSIONS="dubbo.version:$DUBBO_VERSION;compiler.version:$DUBBO_VERSION;$CANDIDATE_VERSIONS;dubbo.compiler.version:$DUBBO_VERSION"
|
|
||||||
echo "CANDIDATE_VERSIONS=$CANDIDATE_VERSIONS" >> $GITHUB_ENV
|
|
||||||
- name: "Build test image"
|
|
||||||
run: |
|
|
||||||
cd test && bash ./build-test-image.sh
|
|
||||||
- name: "Run tests"
|
|
||||||
run: cd test && bash ./run-tests.sh
|
|
||||||
- name: "Upload test result"
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: integration-test-result-${{matrix.jdk}}
|
|
||||||
path: test/jobs/*-result*
|
|
||||||
integration-test-result:
|
|
||||||
needs: [integration-test-job]
|
|
||||||
if: always()
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
JAVA_VER: ${{matrix.jdk}}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
jdk: [ 8, 11, 17, 21 ]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-integration-cases'
|
|
||||||
ref: main
|
|
||||||
- name: "Download test result"
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: integration-test-result-${{matrix.jdk}}
|
|
||||||
path: test/jobs/
|
|
||||||
- name: "Merge test result"
|
|
||||||
run: ./test/scripts/merge-test-results.sh
|
|
||||||
|
|
||||||
error-code-inspecting:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
path: "./dubbo"
|
|
||||||
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: 'apache/dubbo-test-tools'
|
|
||||||
ref: main
|
|
||||||
path: "./dubbo-test-tools"
|
|
||||||
|
|
||||||
- name: "Set up JDK 21"
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
java-version: 21
|
|
||||||
distribution: 'zulu'
|
|
||||||
|
|
||||||
- name: "Compile Dubbo (Linux)"
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo
|
|
||||||
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean install -DskipTests=true -DskipIntegrationTests=true -Dcheckstyle.skip=true -Dcheckstyle_unix.skip=true -Drat.skip=true -Dmaven.javadoc.skip=true
|
|
||||||
- name: "Run Error Code Inspecting"
|
|
||||||
env:
|
|
||||||
DUBBO_ECI_REPORT_AS_ERROR: true
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo-test-tools/dubbo-error-code-inspector
|
|
||||||
../mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C package exec:java -Ddubbo.eci.report-as-error=${DUBBO_ECI_REPORT_AS_ERROR} -Dmaven.test.skip=true -Dmaven.test.skip.exec=true -Ddubbo.eci.path=${{ github.workspace }}/dubbo
|
|
||||||
|
|
||||||
- name: "Upload error code inspection result"
|
|
||||||
# always() should not be used here, since we don't need to handle the 'canceled' situation.
|
|
||||||
if: ${{ success() || failure() }}
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: "error-inspection-result"
|
|
||||||
path: ${{ github.workspace }}/dubbo-test-tools/dubbo-error-code-inspector/error-inspection-result.txt
|
|
||||||
|
|
||||||
native-image-inspecting:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
path: "./dubbo"
|
|
||||||
|
|
||||||
- name: "Setup GraalVM environment"
|
|
||||||
uses: graalvm/setup-graalvm@v1
|
|
||||||
with:
|
|
||||||
version: '22.3.0'
|
|
||||||
java-version: '17'
|
|
||||||
components: 'native-image'
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
native-image-job-reports: 'true'
|
|
||||||
|
|
||||||
- name: "Setup Zookeeper environment"
|
|
||||||
run: |
|
|
||||||
wget https://dlcdn.apache.org/zookeeper/zookeeper-3.8.4/apache-zookeeper-3.8.4-bin.tar.gz
|
|
||||||
tar -zxvf apache-zookeeper-3.8.4-bin.tar.gz
|
|
||||||
mv apache-zookeeper-3.8.4-bin/conf/zoo_sample.cfg apache-zookeeper-3.8.4-bin/conf/zoo.cfg
|
|
||||||
apache-zookeeper-3.8.4-bin/bin/zkServer.sh start
|
|
||||||
|
|
||||||
- name: "Check environment"
|
|
||||||
run: |
|
|
||||||
java --version
|
|
||||||
native-image --version
|
|
||||||
|
|
||||||
- name: "Compile Dubbo (Linux)"
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo
|
|
||||||
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean install -DskipTests=true -DskipIntegrationTests=true -Dcheckstyle.skip=true -Dcheckstyle_unix.skip=true -Drat.skip=true -Dmaven.javadoc.skip=true
|
|
||||||
|
|
||||||
- name: "Compile and run Dubbo demo for native (Linux)"
|
|
||||||
run: |
|
|
||||||
cd ${{ github.workspace }}/dubbo/dubbo-demo/dubbo-demo-native/dubbo-demo-native-provider
|
|
||||||
${{ github.workspace }}/dubbo/mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean package -P native -Dmaven.test.skip=true native:compile
|
|
||||||
nohup ./target/dubbo-demo-native-provider &
|
|
||||||
cd ${{ github.workspace }}/dubbo/dubbo-demo/dubbo-demo-native/dubbo-demo-native-consumer
|
|
||||||
${{ github.workspace }}/dubbo/mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast -T 2C clean package -P native -Dmaven.test.skip=true native:compile
|
|
||||||
./target/dubbo-demo-native-consumer
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
# maven ignore
|
# maven ignore
|
||||||
target/
|
target/
|
||||||
*.jar
|
*.jar
|
||||||
|
!.mvn/wrapper/*
|
||||||
*.war
|
*.war
|
||||||
*.zip
|
*.zip
|
||||||
*.tar
|
*.tar
|
||||||
|
|
@ -11,8 +12,6 @@ target/
|
||||||
.settings/
|
.settings/
|
||||||
.project
|
.project
|
||||||
.classpath
|
.classpath
|
||||||
.externalToolBuilders
|
|
||||||
maven-eclipse.xml
|
|
||||||
|
|
||||||
# idea ignore
|
# idea ignore
|
||||||
.idea/
|
.idea/
|
||||||
|
|
@ -49,9 +48,3 @@ dubbo-demo/dubbo-demo-triple/build/*
|
||||||
|
|
||||||
# global registry center
|
# global registry center
|
||||||
.tmp
|
.tmp
|
||||||
|
|
||||||
.git.exec.error
|
|
||||||
|
|
||||||
# log files generated by testcase.
|
|
||||||
dubbo-rpc/dubbo-rpc-api/custom-access.log*
|
|
||||||
|
|
||||||
|
|
|
||||||
235
.licenserc.yaml
235
.licenserc.yaml
|
|
@ -1,235 +0,0 @@
|
||||||
header:
|
|
||||||
license:
|
|
||||||
spdx-id: Apache-2.0
|
|
||||||
content: |
|
|
||||||
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.
|
|
||||||
|
|
||||||
paths-ignore:
|
|
||||||
- '**/*.versionsBackup'
|
|
||||||
- '**/.idea/'
|
|
||||||
- '**/*.iml'
|
|
||||||
- '**/.settings/*'
|
|
||||||
- '**/.classpath'
|
|
||||||
- '**/.project'
|
|
||||||
- '**/target/**'
|
|
||||||
- '**/generated/**'
|
|
||||||
- '**/*.log'
|
|
||||||
- '**/codestyle/*'
|
|
||||||
- '**/resources/META-INF/**'
|
|
||||||
- '**/resources/mockito-extensions/**'
|
|
||||||
- '**/*.proto'
|
|
||||||
- '**/*.cache'
|
|
||||||
- '**/*.txt'
|
|
||||||
- '**/*.load'
|
|
||||||
- '**/*.flex'
|
|
||||||
- '**/*.fc'
|
|
||||||
- '**/*.javascript'
|
|
||||||
- '**/*.properties'
|
|
||||||
- '**/*.sh'
|
|
||||||
- '**/*.bat'
|
|
||||||
- '**/*.md'
|
|
||||||
- '**/*.svg'
|
|
||||||
- '**/*.png'
|
|
||||||
- '**/*.json'
|
|
||||||
- '**/*.conf'
|
|
||||||
- '**/*.ftl'
|
|
||||||
- '**/*.tpl'
|
|
||||||
- '**/*.factories'
|
|
||||||
- '**/*.handlers'
|
|
||||||
- '**/*.schemas'
|
|
||||||
- '**/*.nojekyll'
|
|
||||||
- '.git/'
|
|
||||||
- '.github/**'
|
|
||||||
- '**/.gitignore'
|
|
||||||
- '**/.helmignore'
|
|
||||||
- '.repository/'
|
|
||||||
- 'compiler/**'
|
|
||||||
- '.gitmodules'
|
|
||||||
- '.mvn'
|
|
||||||
- 'mvnw'
|
|
||||||
- 'mvnw.cmd'
|
|
||||||
- 'LICENSE'
|
|
||||||
- 'NOTICE'
|
|
||||||
- 'CNAME'
|
|
||||||
- 'Jenkinsfile'
|
|
||||||
- '**/vendor/**'
|
|
||||||
- '**/src/test/resources/certs/**'
|
|
||||||
- '**/src/test/resources/definition/**'
|
|
||||||
- 'dubbo-common/src/main/java/org/apache/dubbo/common/threadlocal/InternalThreadLocal.java'
|
|
||||||
- 'dubbo-common/src/main/java/org/apache/dubbo/common/threadlocal/InternalThreadLocalMap.java'
|
|
||||||
- 'dubbo-common/src/main/java/org/apache/dubbo/common/timer/HashedWheelTimer.java'
|
|
||||||
- 'dubbo-common/src/main/java/org/apache/dubbo/common/timer/Timeout.java'
|
|
||||||
- 'dubbo-common/src/main/java/org/apache/dubbo/common/timer/Timer.java'
|
|
||||||
- 'dubbo-common/src/main/java/org/apache/dubbo/common/timer/TimerTask.java'
|
|
||||||
- 'dubbo-common/src/main/java/org/apache/dubbo/common/utils/CIDRUtils.java'
|
|
||||||
- 'dubbo-common/src/main/java/org/apache/dubbo/common/utils/Utf8Utils.java'
|
|
||||||
- 'dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/EmbeddedZooKeeper.java'
|
|
||||||
- 'dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/utils/TestSocketUtils.java'
|
|
||||||
- 'dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TriHttp2RemoteFlowController.java'
|
|
||||||
- 'dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/serial/SerializingExecutor.java'
|
|
||||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/AbstractAotMojo.java'
|
|
||||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/AbstractDependencyFilterMojo.java'
|
|
||||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/CommandLineBuilder.java'
|
|
||||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/DependencyFilter.java'
|
|
||||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/Exclude.java'
|
|
||||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/ExcludeFilter.java'
|
|
||||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/FilterableDependency.java'
|
|
||||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/Include.java'
|
|
||||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/IncludeFilter.java'
|
|
||||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/JavaCompilerPluginConfiguration.java'
|
|
||||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/JavaExecutable.java'
|
|
||||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/JavaProcessExecutor.java'
|
|
||||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/MatchingGroupIdFilter.java'
|
|
||||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/RunArguments.java'
|
|
||||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/aot/RunProcess.java'
|
|
||||||
- 'dubbo-native/src/main/java/org/apache/dubbo/aot/generate/BasicJsonWriter.java'
|
|
||||||
- 'dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ExecutableMode.java'
|
|
||||||
- 'dubbo-native/src/main/java/org/apache/dubbo/aot/generate/MemberCategory.java'
|
|
||||||
- 'dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/DubboMergingDigest.java'
|
|
||||||
- 'dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/DubboAbstractTDigest.java'
|
|
||||||
|
|
||||||
comment: on-failure
|
|
||||||
|
|
||||||
license-location-threshold: 130
|
|
||||||
|
|
||||||
dependency:
|
|
||||||
files:
|
|
||||||
- pom.xml
|
|
||||||
- dubbo-dependencies-bom/pom.xml
|
|
||||||
licenses:
|
|
||||||
- name: com.alibaba.spring:spring-context-support
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: com.fasterxml.jackson.core:jackson-annotations
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: com.fasterxml.jackson.core:jackson-core
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: com.fasterxml.jackson.core:jackson-databind
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: com.fasterxml.jackson.dataformat:jackson-dataformat-yaml
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: com.google.code.gson:gson
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: com.google.guava:listenablefuture
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: com.salesforce.servicelibs:grpc-contrib
|
|
||||||
license: BSD 3-clause
|
|
||||||
- name: com.squareup.okhttp3:logging-interceptor
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: com.squareup.okhttp3:okhttp
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: com.squareup.okio:okio
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: com.sun.xml.fastinfoset:FastInfoset
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: io.envoyproxy.controlplane:api
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: io.swagger:swagger-annotations
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: io.swagger:swagger-models
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.springframework.boot:spring-boot
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.springframework.boot:spring-boot-actuator
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.springframework.boot:spring-boot-autoconfigure
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.springframework.boot:spring-boot-configuration-processor
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.springframework.boot:spring-boot-starter
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.springframework.boot:spring-boot-starter-actuator
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.springframework.boot:spring-boot-starter-logging
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.springframework.boot:spring-boot-starter-tomcat
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.springframework.boot:spring-boot-starter-web
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.slf4j:slf4j-api
|
|
||||||
license: MIT
|
|
||||||
- name: org.slf4j:slf4j-log4j12
|
|
||||||
license: MIT
|
|
||||||
- name: org.jboss.resteasy:resteasy-jaxrs
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.jboss.resteasy:resteasy-client
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.jboss.resteasy:resteasy-netty4
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.jboss.resteasy:resteasy-jdk-http
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.jboss.resteasy:resteasy-jackson-provider
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.jboss.resteasy:resteasy-jaxb-provider
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: net.jcip:jcip-annotations
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.apache.zookeeper:zookeeper
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.apache.zookeeper:zookeeper-jute
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: net.bytebuddy:byte-buddy
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: javax.enterprise:cdi-api
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.codehaus.plexus:plexus-component-annotations
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.slf4j:jcl-over-slf4j
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.slf4j:jul-to-slf4j
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.codehaus.plexus:plexus-interpolation
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.sonatype.plexus:plexus-sec-dispatcher
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: org.sonatype.plexus:plexus-cipher
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: com.google.protobuf:protobuf-java
|
|
||||||
license: BSD 3-clause
|
|
||||||
- name: com.google.protobuf:protobuf-java-util
|
|
||||||
license: BSD 3-clause
|
|
||||||
# multi license
|
|
||||||
- name: org.javassist:javassist
|
|
||||||
license: Apache-2.0
|
|
||||||
- name: javax.annotation:javax.annotation-api
|
|
||||||
license: CDDL-1.0
|
|
||||||
- name: com.salesforce.servicelibs:jprotoc
|
|
||||||
license: CDDL-1.0
|
|
||||||
- name: org.checkerframework:checker-compat-qual
|
|
||||||
license: MIT
|
|
||||||
- name: ch.qos.logback:logback-classic
|
|
||||||
license: EPL-1.0
|
|
||||||
- name: ch.qos.logback:logback-core
|
|
||||||
license: EPL-1.0
|
|
||||||
- name: javax.servlet:javax.servlet-api
|
|
||||||
license: CDDL-1.1
|
|
||||||
- name: com.sun.activation:javax.activation
|
|
||||||
license: CDDL-1.1
|
|
||||||
- name: javax.activation:activation
|
|
||||||
license: CDDL-1.1
|
|
||||||
- name: jakarta.annotation:jakarta.annotation-api
|
|
||||||
license: EPL-2.0
|
|
||||||
- name: org.glassfish:jakarta.el
|
|
||||||
license: EPL-2.0
|
|
||||||
- name: org.jboss.spec.javax.annotation:jboss-annotations-api_1.2_spec
|
|
||||||
license: CDDL-1.1
|
|
||||||
- name: org.jboss.spec.javax.ws.rs:jboss-jaxrs-api_2.1_spec
|
|
||||||
license: EPL-2.0
|
|
||||||
- name: org.jboss.spec.javax.annotation:jboss-annotations-api_1.3_spec
|
|
||||||
license: EPL-2.0
|
|
||||||
excludes:
|
|
||||||
- name: javax.xml.bind:jsr173_api
|
|
||||||
Binary file not shown.
|
|
@ -1,18 +1 @@
|
||||||
# Licensed to the Apache Software Foundation (ASF) under one
|
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
|
||||||
# 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
|
|
||||||
#
|
|
||||||
# https://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.
|
|
||||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip
|
|
||||||
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
sudo: false # faster builds
|
||||||
|
os: linux
|
||||||
|
dist: focal
|
||||||
|
arch: arm64-graviton2
|
||||||
|
virt: lxd
|
||||||
|
group: edge
|
||||||
|
|
||||||
|
language: java
|
||||||
|
jdk: openjdk11
|
||||||
|
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/.m2
|
||||||
|
|
||||||
|
install: true
|
||||||
|
|
||||||
|
branches:
|
||||||
|
only:
|
||||||
|
- '3.0'
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- rm -rf $HOME/.m2/repository/org/glassfish/javax.el/3.0.1-b08
|
||||||
|
|
||||||
|
script: if [[ "${TRAVIS_EVENT_TYPE}" == "cron" ]]; then travis_wait 60 ./mvnw --batch-mode -U -q -e --no-transfer-progress clean test -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true; fi
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
- bash <(curl -s https://codecov.io/bash)
|
||||||
|
|
||||||
|
after_failure:
|
||||||
|
- echo "build failed!"
|
||||||
10
CHANGES.md
10
CHANGES.md
|
|
@ -101,7 +101,7 @@ check 2.7.5 milestone for details.
|
||||||
* In consumer side the app cannot catch the exception from provider that is configured serialization="kryo". #4238
|
* In consumer side the app cannot catch the exception from provider that is configured serialization="kryo". #4238
|
||||||
* fix StringUtils#isBlank #4725
|
* fix StringUtils#isBlank #4725
|
||||||
* when the interfaceName of the Reference annotation has duplicated,the exception is puzzled #4160
|
* when the interfaceName of the Reference annotation has duplicated,the exception is puzzled #4160
|
||||||
* when anonymity bean is defined in spring context,dubbo throw npe #
|
* when anonymity bean is defined in spirng context,dubbo throw npe #
|
||||||
* add Thread ContextClassLoader #4712
|
* add Thread ContextClassLoader #4712
|
||||||
* Fix judgment ipv4 address #4729
|
* Fix judgment ipv4 address #4729
|
||||||
* The compilation of static methods should be excluded when generating the proxy. #4647
|
* The compilation of static methods should be excluded when generating the proxy. #4647
|
||||||
|
|
@ -184,7 +184,7 @@ check 2.7.5 milestone for details.
|
||||||
- Add a script to check dependencies license. [#3840](https://github.com/apache/dubbo/issues/3840)
|
- Add a script to check dependencies license. [#3840](https://github.com/apache/dubbo/issues/3840)
|
||||||
- Change DynamicConfiguration definition to better adapt to Apollo's namespace storage model.[#3266](https://github.com/apache/dubbo/issues/3266)
|
- Change DynamicConfiguration definition to better adapt to Apollo's namespace storage model.[#3266](https://github.com/apache/dubbo/issues/3266)
|
||||||
- use equal explicit class to replace anonymous class [#4027](https://github.com/apache/dubbo/issues/4027)
|
- use equal explicit class to replace anonymous class [#4027](https://github.com/apache/dubbo/issues/4027)
|
||||||
- Separate Constants.java into some SubConstants Class [#3137](https://github.com/apache/dubbo/issues/3137)
|
- Seperate Constants.java into some SubConstants Class [#3137](https://github.com/apache/dubbo/issues/3137)
|
||||||
- Need to enhance DecodeableRpcResult error message [#3994](https://github.com/apache/dubbo/issues/3994)
|
- Need to enhance DecodeableRpcResult error message [#3994](https://github.com/apache/dubbo/issues/3994)
|
||||||
- Provide more meaningful binary releases. [#2491](https://github.com/apache/dubbo/issues/2491)
|
- Provide more meaningful binary releases. [#2491](https://github.com/apache/dubbo/issues/2491)
|
||||||
- remove useless module-dubbo-test-integration [#3573](https://github.com/apache/dubbo/issues/3573)
|
- remove useless module-dubbo-test-integration [#3573](https://github.com/apache/dubbo/issues/3573)
|
||||||
|
|
@ -211,7 +211,7 @@ check 2.7.5 milestone for details.
|
||||||
- Fix consumer will generate wrong stackTrace. [#4137](https://github.com/apache/dubbo/issues/4137)
|
- Fix consumer will generate wrong stackTrace. [#4137](https://github.com/apache/dubbo/issues/4137)
|
||||||
- nacos registry serviceName may conflict. [#4111](https://github.com/apache/dubbo/issues/4111)
|
- nacos registry serviceName may conflict. [#4111](https://github.com/apache/dubbo/issues/4111)
|
||||||
- The client loses the listener when the network is reconnected. [#4115](https://github.com/apache/dubbo/issues/4115)
|
- The client loses the listener when the network is reconnected. [#4115](https://github.com/apache/dubbo/issues/4115)
|
||||||
- fix registry urls increase forever when recreate reference proxy. [#4109](https://github.com/apache/dubbo/issues/4109)
|
- fix registery urls increase forever when recreate reference proxy. [#4109](https://github.com/apache/dubbo/issues/4109)
|
||||||
- In dubbo 2.7.1,the watcher processor of zookeeper client throw Nullpointexception. [#3866](https://github.com/apache/dubbo/issues/3866)
|
- In dubbo 2.7.1,the watcher processor of zookeeper client throw Nullpointexception. [#3866](https://github.com/apache/dubbo/issues/3866)
|
||||||
- ReferenceConfig initialized not changed to false once subscribe throws exception [#4068](https://github.com/apache/dubbo/issues/4068)
|
- ReferenceConfig initialized not changed to false once subscribe throws exception [#4068](https://github.com/apache/dubbo/issues/4068)
|
||||||
- dubbo registry extension compatibility with dubbo 2.6.x. [#3882](https://github.com/apache/dubbo/issues/3882)
|
- dubbo registry extension compatibility with dubbo 2.6.x. [#3882](https://github.com/apache/dubbo/issues/3882)
|
||||||
|
|
@ -400,7 +400,7 @@ Enhancement / New feature:
|
||||||
* tag route. #3065
|
* tag route. #3065
|
||||||
* Use Netty4 as default Netty version. #3029
|
* Use Netty4 as default Netty version. #3029
|
||||||
* upporting Java 8 Date/Time type when serializing with Kryo #3519
|
* upporting Java 8 Date/Time type when serializing with Kryo #3519
|
||||||
* support config telnet #3511
|
* supoort config telnet #3511
|
||||||
* add annotation driven in MethodConfig and ArgumentConfig #2603
|
* add annotation driven in MethodConfig and ArgumentConfig #2603
|
||||||
* add nacos-registry module #3296
|
* add nacos-registry module #3296
|
||||||
* add `protocol` attribute in `@Rerefence` #3555
|
* add `protocol` attribute in `@Rerefence` #3555
|
||||||
|
|
@ -416,7 +416,7 @@ BugFix:
|
||||||
* SPI entires dup by 3 times #3315
|
* SPI entires dup by 3 times #3315
|
||||||
* fix Consumer throws RpcException after RegistryDirectory notify in high QPS #2016
|
* fix Consumer throws RpcException after RegistryDirectory notify in high QPS #2016
|
||||||
* fix NPE in @Reference when using Junit to test dubbo service #3429
|
* fix NPE in @Reference when using Junit to test dubbo service #3429
|
||||||
* fix consumer always catch java.lang.reflect.UndeclaredThrowableException for any exception throws in provider #3386
|
* fix consuer always catch java.lang.reflect.UndeclaredThrowableException for any exception throws in provider #3386
|
||||||
* fix the priority of `DubboConfigConfigurationSelector ` #2897
|
* fix the priority of `DubboConfigConfigurationSelector ` #2897
|
||||||
* fix `@Rerefence#parameters()` not work #2301
|
* fix `@Rerefence#parameters()` not work #2301
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
pipeline {
|
|
||||||
agent {
|
|
||||||
label 'ubuntu'
|
|
||||||
}
|
|
||||||
|
|
||||||
tools {
|
|
||||||
maven 'maven_3_latest'
|
|
||||||
jdk 'jdk_11_latest'
|
|
||||||
}
|
|
||||||
|
|
||||||
stages {
|
|
||||||
stage('Code Quality') {
|
|
||||||
steps {
|
|
||||||
echo 'Checking Code Quality on SonarCloud'
|
|
||||||
script {
|
|
||||||
// Main parameters
|
|
||||||
def sonarcloudParams=""
|
|
||||||
if ( env.BRANCH_NAME.startsWith("PR-") ) {
|
|
||||||
// this is a pull request
|
|
||||||
withCredentials([string(credentialsId: 'sonarcloud-token', variable: 'SONAR_TOKEN')]) {
|
|
||||||
sh './mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean verify sonar:sonar -Dmaven.test.skip=true -Dsonar.host.url=https://sonarcloud.io -Dsonar.organization=apache -Dsonar.projectKey=apache_dubbo -Dsonar.coverage.jacoco.xmlReportPaths=dubbo-test/dubbo-dependencies-all/target/site/jacoco-aggregate/jacoco.xml -Dsonar.pullrequest.branch=${CHANGE_BRANCH} -Dsonar.pullrequest.base=${CHANGE_TARGET} -Dsonar.pullrequest.key=${CHANGE_ID} -Dsonar.login=${SONAR_TOKEN}'
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// this is just a branch
|
|
||||||
withCredentials([string(credentialsId: 'sonarcloud-token', variable: 'SONAR_TOKEN')]) {
|
|
||||||
sh './mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress --fail-fast clean verify sonar:sonar -Dmaven.test.skip=true -Dsonar.host.url=https://sonarcloud.io -Dsonar.organization=apache -Dsonar.projectKey=apache_dubbo -Dsonar.coverage.jacoco.xmlReportPaths=dubbo-test/dubbo-dependencies-all/target/site/jacoco-aggregate/jacoco.xml -Dsonar.branch.name=${BRANCH_NAME} -Dsonar.login=${SONAR_TOKEN}'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
6
NOTICE
6
NOTICE
|
|
@ -1,5 +1,5 @@
|
||||||
Apache Dubbo
|
Apache Dubbo
|
||||||
Copyright 2018-2024 The Apache Software Foundation
|
Copyright 2018-2023 The Apache Software Foundation
|
||||||
|
|
||||||
This product includes software developed at
|
This product includes software developed at
|
||||||
The Apache Software Foundation (http://www.apache.org/).
|
The Apache Software Foundation (http://www.apache.org/).
|
||||||
|
|
@ -12,7 +12,3 @@ Please visit the Netty web site for more information:
|
||||||
* http://netty.io/
|
* http://netty.io/
|
||||||
|
|
||||||
Copyright 2014 The Netty Project
|
Copyright 2014 The Netty Project
|
||||||
|
|
||||||
This product contains code form the t-digest Project:
|
|
||||||
The code for the t-digest was originally authored by Ted Dunning
|
|
||||||
Adrien Grand contributed the heart of the AVLTreeDigest (https://github.com/jpountz)
|
|
||||||
|
|
|
||||||
133
README.md
133
README.md
|
|
@ -1,15 +1,18 @@
|
||||||
# Apache Dubbo Project
|
# Apache Dubbo Project
|
||||||
|
|
||||||
[](https://github.com/apache/dubbo/actions/workflows/build-and-test-pr.yml)
|
[](https://github.com/apache/dubbo/actions/workflows/build-and-test-3.yml?query=branch%3A3.0)
|
||||||
[](https://codecov.io/gh/apache/dubbo)
|
[](https://codecov.io/gh/apache/dubbo)
|
||||||

|

|
||||||

|

|
||||||
[](http://isitmaintained.com/project/apache/dubbo "Average time to resolve an issue")
|
[](http://isitmaintained.com/project/apache/dubbo "Average time to resolve an issue")
|
||||||
[](http://isitmaintained.com/project/apache/dubbo "Percentage of issues still open")
|
[](http://isitmaintained.com/project/apache/dubbo "Percentage of issues still open")
|
||||||
|
[](https://twitter.com/intent/tweet?text=Apache%20Dubbo%20is%20a%20high-performance%2C%20java%20based%2C%20open%20source%20RPC%20framework.&url=http://dubbo.apache.org/&via=ApacheDubbo&hashtags=rpc,java,dubbo,micro-service)
|
||||||
|
[](https://twitter.com/intent/follow?screen_name=ApacheDubbo)
|
||||||
|
[](https://gitter.im/alibaba/dubbo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||||
|
|
||||||
Apache Dubbo is a high-performance, Java-based open-source RPC framework. Please visit the [official site](http://dubbo.apache.org) for the quick start guide and documentation, as well as the [wiki](https://github.com/apache/dubbo/wiki) for news, FAQ, and release notes.
|
Apache Dubbo is a high-performance, Java-based open-source RPC framework. Please visit the [official site](http://dubbo.apache.org) for the quick start guide and documentation, as well as the [wiki](https://github.com/apache/dubbo/wiki) for news, FAQ, and release notes.
|
||||||
|
|
||||||
We are now collecting Dubbo user info to help us to improve Dubbo further. Kindly support us by providing your usage information on [Wanted: who's using dubbo](https://github.com/apache/dubbo/discussions/13842), thanks :)
|
We are now collecting Dubbo user info to help us to improve Dubbo further. Kindly support us by providing your usage information on [issue#9436: Wanted: who's using dubbo](https://github.com/apache/dubbo/issues/9436), thanks :)
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
|
|
@ -26,20 +29,20 @@ We are now collecting Dubbo user info to help us to improve Dubbo further. Kindl
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
The following code snippet comes from [Dubbo Samples](https://github.com/apache/dubbo-samples.git). You may clone the sample project and step into the `dubbo-samples-api` subdirectory before proceeding.
|
The following code snippet comes from [Dubbo Samples](https://github.com/apache/dubbo-samples/tree/master/dubbo-samples-api). You may clone the sample project and step into the `dubbo-samples-api` subdirectory before proceeding.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/apache/dubbo-samples.git
|
git clone https://github.com/apache/dubbo-samples.git
|
||||||
cd dubbo-samples/1-basic/dubbo-samples-api
|
cd dubbo-samples/dubbo-samples-api
|
||||||
```
|
```
|
||||||
|
|
||||||
There's a [README](https://github.com/apache/dubbo-samples/blob/389cd612f1ea57ee6e575005b32f195c442c35a2/1-basic/dubbo-samples-api/README.md) file under `dubbo-samples-api` directory. We recommend referencing the samples in that directory by following the below-mentioned instructions:
|
There's a [README](https://github.com/apache/dubbo-samples/tree/master/dubbo-samples-api/README.md) file under `dubbo-samples-api` directory. We recommend referencing the samples in that directory by following the below-mentioned instructions:
|
||||||
|
|
||||||
### Maven dependency
|
### Maven dependency
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<properties>
|
<properties>
|
||||||
<dubbo.version>3.2.13-SNAPSHOT</dubbo.version>
|
<dubbo.version>3.0.10</dubbo.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
@ -67,7 +70,7 @@ public interface GreetingsService {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
*See [api/GreetingsService.java](https://github.com/apache/dubbo-samples/blob/389cd612f1ea57ee6e575005b32f195c442c35a2/1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/api/GreetingsService.java) on GitHub.*
|
*See [api/GreetingsService.java](https://github.com/apache/dubbo-samples/blob/master/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/api/GreetingsService.java) on GitHub.*
|
||||||
|
|
||||||
### Implement service interface for the provider
|
### Implement service interface for the provider
|
||||||
|
|
||||||
|
|
@ -84,7 +87,7 @@ public class GreetingsServiceImpl implements GreetingsService {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
*See [provider/GreetingsServiceImpl.java](https://github.com/apache/dubbo-samples/blob/389cd612f1ea57ee6e575005b32f195c442c35a2/1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/GreetingsServiceImpl.java) on GitHub.*
|
*See [provider/GreetingsServiceImpl.java](https://github.com/apache/dubbo-samples/blob/master/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/GreetingsServiceImpl.java) on GitHub.*
|
||||||
|
|
||||||
### Start service provider
|
### Start service provider
|
||||||
|
|
||||||
|
|
@ -116,7 +119,7 @@ public class Application {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
*See [provider/Application.java](https://github.com/apache/dubbo-samples/blob/389cd612f1ea57ee6e575005b32f195c442c35a2/1-basic/dubbo-samples-spring-xml/src/main/java/org/apache/dubbo/samples/provider/Application.java) on GitHub.*
|
*See [provider/Application.java](https://github.com/apache/dubbo-samples/blob/master/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/Application.java) on GitHub.*
|
||||||
|
|
||||||
### Build and run the provider
|
### Build and run the provider
|
||||||
|
|
||||||
|
|
@ -150,7 +153,7 @@ public class Application {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
*See [client/Application.java](https://github.com/apache/dubbo-samples/blob/389cd612f1ea57ee6e575005b32f195c442c35a2/1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/client/Application.java) on GitHub.*
|
*See [consumer/Application.java](https://github.com/apache/dubbo-samples/blob/master/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/client/Application.java) on GitHub.*
|
||||||
|
|
||||||
### Build and run the consumer
|
### Build and run the consumer
|
||||||
|
|
||||||
|
|
@ -164,10 +167,10 @@ The consumer will print out `hi, dubbo` on the screen.
|
||||||
|
|
||||||
### Next steps
|
### Next steps
|
||||||
|
|
||||||
* [Your first Dubbo application](https://dubbo.apache.org/en/blog/2018/08/07/dubbo-101/) - A 101 tutorial to reveal more details, with the same code above.
|
* [Your first Dubbo application](https://dubbo.apache.org/blog/2018/08/07/dubbo-101/) - A 101 tutorial to reveal more details, with the same code above.
|
||||||
* [Dubbo user manual](https://dubbo.apache.org/en/overview/what/) - How to use Dubbo and all its features.
|
* [Dubbo user manual](https://dubbo.apache.org/docs/v2.7/user/preface/background/) - How to use Dubbo and all its features.
|
||||||
* [Dubbo developer guide](https://dubbo.apache.org/en/docs3-v2/java-sdk/) - How to involve in Dubbo development.
|
* [Dubbo developer guide](https://dubbo.apache.org/docs/v2.7/dev/build/) - How to involve in Dubbo development.
|
||||||
* [Dubbo admin manual](https://dubbo.apache.org/en/docs/v2.7/admin/ops/) - How to admin and manage Dubbo services.
|
* [Dubbo admin manual](https://dubbo.apache.org/docs/v2.7/admin/install/provider-demo/) - How to admin and manage Dubbo services.
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
|
|
@ -177,91 +180,55 @@ If you want to try out the cutting-edge features, you can build with the followi
|
||||||
mvn clean install
|
mvn clean install
|
||||||
```
|
```
|
||||||
|
|
||||||
## Recommended Test Environment
|
|
||||||
To avoid intermittent test failures (i.e., flaky tests), it is recommended to have a machine or virtual machine with the following specifications:
|
|
||||||
|
|
||||||
* Minimum of 2CPUs.
|
|
||||||
* Minimum of 2Gb of RAM.
|
|
||||||
|
|
||||||
### How does the Dubbo Community collaborate?
|
|
||||||
|
|
||||||
The Dubbo Community primarily communicates on GitHub through issues, discussions, and pull requests.
|
|
||||||
|
|
||||||
- Issues: We use issues to track bugs and tasks. Any **work-related** item is associated with an issue.
|
|
||||||
- Discussions: We use discussions for questions, early proposals, and announcements. Any **idea-related** item is associated with a discussion.
|
|
||||||
- Pull Requests: We use pull requests to merge a set of changes from contributors into Dubbo.
|
|
||||||
|
|
||||||
We have also implemented [a project board](https://github.com/orgs/apache/projects/337) to monitor all the items.
|
|
||||||
|
|
||||||
Any essential changes should be discussed on the mailing list before they happen.
|
|
||||||
|
|
||||||
### Seeking for help
|
|
||||||
|
|
||||||
If you have questions such as:
|
|
||||||
|
|
||||||
- What is Dubbo?
|
|
||||||
- How do I use Dubbo?
|
|
||||||
- Why did an unexpected result occur?
|
|
||||||
|
|
||||||
Please start a discussion at https://github.com/apache/dubbo/discussions.
|
|
||||||
|
|
||||||
However, if you encounter the following situations:
|
|
||||||
|
|
||||||
- You're certain there's a bug that Dubbo needs to fix,
|
|
||||||
- You believe a feature could be enhanced,
|
|
||||||
- You have a detailed proposal for improving Dubbo,
|
|
||||||
|
|
||||||
Please open an issue at https://github.com/apache/dubbo/issues.
|
|
||||||
|
|
||||||
To ask effective questions, we recommend reading **[How To Ask Questions The Smart Way](https://github.com/selfteaching/How-To-Ask-Questions-The-Smart-Way/blob/master/How-To-Ask-Questions-The-Smart-Way.md)** first.
|
|
||||||
|
|
||||||
### Contribution
|
|
||||||
|
|
||||||
- Browse the "help wanted" tasks in the [Dubbo project board](https://github.com/orgs/apache/projects/337).
|
|
||||||
- Participate in discussions on the mailing list. See the subscription [guide](https://github.com/apache/dubbo/wiki/Mailing-list-subscription-guide).
|
|
||||||
- Respond to queries in the [discussions](https://github.com/apache/dubbo/issues).
|
|
||||||
- Resolve bugs reported in [issues](https://github.com/apache/dubbo/issues) and send us a pull request.
|
|
||||||
- Review existing [pull requests](https://github.com/apache/dubbo/pulls).
|
|
||||||
- Enhance the [website](https://github.com/apache/dubbo-website). We typically need:
|
|
||||||
- Blog posts
|
|
||||||
- Translations for documentation
|
|
||||||
- Use cases showcasing Dubbo integration in enterprise systems.
|
|
||||||
- Improve the [dubbo-admin](https://github.com/apache/dubbo-admin).
|
|
||||||
- Contribute to the projects listed in the [ecosystem](https://github.com/apache/?q=dubbo&type=all&language=&sort=).
|
|
||||||
- Any other forms of contribution not listed above are also welcome.
|
|
||||||
- If you're interested in contributing, please send an email to [dev@dubbo.apache.org](mailto:dev@dubbo.apache.org) to let us know!
|
|
||||||
|
|
||||||
For further details, please refer our [guide](https://github.com/apache/dubbo/blob/master/CONTRIBUTING.md) about how to contribute Dubbo.
|
|
||||||
|
|
||||||
## Reporting bugs
|
|
||||||
|
|
||||||
Please follow the [template](https://github.com/apache/dubbo/issues/new?template=dubbo-issue-report-template.md) for reporting any issues.
|
|
||||||
|
|
||||||
## Reporting a security vulnerability
|
|
||||||
|
|
||||||
Please report security vulnerabilities to [us](mailto:security@dubbo.apache.org) privately.
|
|
||||||
|
|
||||||
## Contact
|
## Contact
|
||||||
|
|
||||||
* Mailing list:
|
* Mailing list:
|
||||||
* dev list: for dev/user discussion. [subscribe](mailto:dev-subscribe@dubbo.apache.org), [unsubscribe](mailto:dev-unsubscribe@dubbo.apache.org), [archive](https://lists.apache.org/list.html?dev@dubbo.apache.org), [guide](https://github.com/apache/dubbo/wiki/Mailing-list-subscription-guide)
|
* dev list: for dev/user discussion. [subscribe](mailto:dev-subscribe@dubbo.apache.org), [unsubscribe](mailto:dev-unsubscribe@dubbo.apache.org), [archive](https://lists.apache.org/list.html?dev@dubbo.apache.org), [guide](https://github.com/apache/dubbo/wiki/Mailing-list-subscription-guide)
|
||||||
|
|
||||||
* Bugs: [Issues](https://github.com/apache/dubbo/issues/new?template=dubbo-issue-report-template.md)
|
* Bugs: [Issues](https://github.com/apache/dubbo/issues/new?template=dubbo-issue-report-template.md)
|
||||||
* Gitter: [Gitter channel](https://gitter.im/alibaba/dubbo)
|
* Gitter: [Gitter channel](https://gitter.im/alibaba/dubbo)
|
||||||
* Twitter: [@ApacheDubbo](https://twitter.com/ApacheDubbo)
|
* Twitter: [@ApacheDubbo](https://twitter.com/ApacheDubbo)
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
See [CONTRIBUTING](https://github.com/apache/dubbo/blob/master/CONTRIBUTING.md) for details on submitting patches and the contribution workflow.
|
||||||
|
|
||||||
|
### How can I contribute?
|
||||||
|
|
||||||
|
* Take a look at issues with tags marked [`Good first issue`](https://github.com/apache/dubbo/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) or [`Help wanted`](https://github.com/apache/dubbo/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22).
|
||||||
|
* Join the discussion on the mailing list, subscription [guide](https://github.com/apache/dubbo/wiki/Mailing-list-subscription-guide).
|
||||||
|
* Answer questions on [issues](https://github.com/apache/dubbo/issues).
|
||||||
|
* Fix bugs reported on [issues](https://github.com/apache/dubbo/issues), and send us a pull request.
|
||||||
|
* Review the existing [pull request](https://github.com/apache/dubbo/pulls).
|
||||||
|
* Improve the [website](https://github.com/apache/dubbo-website), typically we need
|
||||||
|
* blog post
|
||||||
|
* translation on documentation
|
||||||
|
* use cases around the integration of Dubbo in enterprise systems.
|
||||||
|
* Improve the [dubbo-admin/dubbo-monitor](https://github.com/apache/dubbo-admin).
|
||||||
|
* Contribute to the projects listed in [ecosystem](https://github.com/dubbo).
|
||||||
|
* Other forms of contribution not explicitly enumerated above.
|
||||||
|
* If you would like to contribute, please send an email to dev@dubbo.apache.org to let us know!
|
||||||
|
|
||||||
|
## Reporting bugs
|
||||||
|
|
||||||
|
Please follow the [template](https://github.com/apache/dubbo/issues/new?template=dubbo-issue-report-template.md) for reporting any issues.
|
||||||
|
|
||||||
|
## Reporting a security vulnerability
|
||||||
|
|
||||||
|
Please report security vulnerabilities to [us](mailto:security@dubbo.apache.org) privately.
|
||||||
|
|
||||||
## Dubbo ecosystem
|
## Dubbo ecosystem
|
||||||
|
|
||||||
* [Dubbo Ecosystem Entry](https://github.com/apache?utf8=%E2%9C%93&q=dubbo&type=&language=) - A GitHub group `dubbo` to gather all Dubbo relevant projects not appropriate in [apache](https://github.com/apache) group yet
|
* [Dubbo Ecosystem Entry](https://github.com/apache?utf8=%E2%9C%93&q=dubbo&type=&language=) - A GitHub group `dubbo` to gather all Dubbo relevant projects not appropriate in [apache](https://github.com/apache) group yet
|
||||||
* [Dubbo Website](https://github.com/apache/dubbo-website) - Apache Dubbo official website
|
* [Dubbo Website](https://github.com/apache/dubbo-website) - Apache Dubbo official website
|
||||||
* [Dubbo Samples](https://github.com/apache/dubbo-samples) - samples for Apache Dubbo
|
* [Dubbo Samples](https://github.com/apache/dubbo-samples) - samples for Apache Dubbo
|
||||||
|
* [Dubbo Spring Boot](https://github.com/apache/dubbo-spring-boot-project) - Spring Boot Project for Dubbo
|
||||||
* [Dubbo Admin](https://github.com/apache/dubbo-admin) - The reference implementation for Dubbo admin
|
* [Dubbo Admin](https://github.com/apache/dubbo-admin) - The reference implementation for Dubbo admin
|
||||||
* [Dubbo Awesome](https://github.com/apache/dubbo-awesome) - Dubbo's slides and video links in Meetup
|
* [Dubbo Awesome](https://github.com/apache/dubbo-awesome) - Dubbo's slides and video links in Meetup
|
||||||
|
|
||||||
#### Language
|
#### Language
|
||||||
|
|
||||||
* [Go](https://github.com/apache/dubbo-go) (recommended)
|
* [Go](https://github.com/dubbo/dubbo-go) (recommended)
|
||||||
* [Rust](https://github.com/apache/dubbo-rust)
|
|
||||||
* [Node.js](https://github.com/apache/dubbo-js)
|
* [Node.js](https://github.com/apache/dubbo-js)
|
||||||
* [Python](https://github.com/dubbo/py-client-for-apache-dubbo)
|
* [Python](https://github.com/dubbo/py-client-for-apache-dubbo)
|
||||||
* [PHP](https://github.com/apache/dubbo-php-framework)
|
* [PHP](https://github.com/apache/dubbo-php-framework)
|
||||||
|
|
@ -269,4 +236,4 @@ Please report security vulnerabilities to [us](mailto:security@dubbo.apache.org)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Apache Dubbo software is licensed under the Apache License Version 2.0. See the [LICENSE](https://github.com/apache/dubbo/blob/master/LICENSE) file for details.
|
Apache Dubbo software is licenced under the Apache License Version 2.0. See the [LICENSE](https://github.com/apache/dubbo/blob/master/LICENSE) file for details.
|
||||||
|
|
|
||||||
12
SECURITY.md
12
SECURITY.md
|
|
@ -5,15 +5,13 @@
|
||||||
Below is a table that shows versions that we accept security fixes.
|
Below is a table that shows versions that we accept security fixes.
|
||||||
|
|
||||||
| Version | Supported |
|
| Version | Supported |
|
||||||
|---------| ------------------ |
|
| ------- | ------------------ |
|
||||||
| 3.3.x | :white_check_mark: |
|
| 3.0.x | :white_check_mark: |
|
||||||
| 3.2.x | :white_check_mark: |
|
| 2.7.x | :white_check_mark: |
|
||||||
| 3.1.x | :white_check_mark: |
|
| 2.6.x | :white_check_mark: |
|
||||||
| 3.0.x | :x: |
|
|
||||||
| 2.7.x | :x: |
|
|
||||||
| 2.6.x | :x: |
|
|
||||||
| 2.5.x | :x: |
|
| 2.5.x | :x: |
|
||||||
|
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
The Apache Software Foundation takes a rigorous standpoint in annihilating the security issues in its software projects. Apache Dubbo is highly sensitive and forthcoming to issues pertaining to its features and functionality.
|
The Apache Software Foundation takes a rigorous standpoint in annihilating the security issues in its software projects. Apache Dubbo is highly sensitive and forthcoming to issues pertaining to its features and functionality.
|
||||||
|
|
|
||||||
34
codecov.yml
34
codecov.yml
|
|
@ -1,34 +0,0 @@
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
codecov:
|
|
||||||
require_ci_to_pass: false
|
|
||||||
notify:
|
|
||||||
wait_for_ci: false
|
|
||||||
coverage:
|
|
||||||
status:
|
|
||||||
# pull-requests only
|
|
||||||
patch:
|
|
||||||
default:
|
|
||||||
threshold: 0.1%
|
|
||||||
ignore:
|
|
||||||
- "**/dubbo-demo/**"
|
|
||||||
- "**/dubbo-compiler/**"
|
|
||||||
- "**/dubbo-test/**"
|
|
||||||
- "**/dubbo-compatible/**"
|
|
||||||
- "**/dubbo-native/**"
|
|
||||||
- "**/dubbo-native-plugin/**"
|
|
||||||
- "**/dubbo-common/src/main/java/org/apache/dubbo/common/json/*.java" # internal JSON impl is deprecate, ignore test coverage for them
|
|
||||||
- "**/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/AnnotationBean.java" # Deprecated
|
|
||||||
|
|
@ -5,6 +5,5 @@
|
||||||
<suppressions>
|
<suppressions>
|
||||||
<suppress files="[\\/]src[\\/]main[\\/]java[\\/]com[\\/]alibaba[\\/]com[\\/]caucho[\\/]hessian" checks=".*"/>
|
<suppress files="[\\/]src[\\/]main[\\/]java[\\/]com[\\/]alibaba[\\/]com[\\/]caucho[\\/]hessian" checks=".*"/>
|
||||||
<suppress files="[\\/]build[\\/]generated[\\/]source[\\/]proto" checks=".*"/>
|
<suppress files="[\\/]build[\\/]generated[\\/]source[\\/]proto" checks=".*"/>
|
||||||
<suppress files="[\\/]target[\\/]generated-sources[\\/]protobuf" checks=".*"/>
|
|
||||||
<suppress files="Yylex\.java" checks="AvoidEscapedUnicodeCharacters"/>
|
<suppress files="Yylex\.java" checks="AvoidEscapedUnicodeCharacters"/>
|
||||||
</suppressions>
|
</suppressions>
|
||||||
|
|
@ -13,77 +13,69 @@
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
<modelVersion>4.0.0</modelVersion>
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>org.apache.dubbo</groupId>
|
<groupId>org.apache.dubbo</groupId>
|
||||||
<artifactId>dubbo-build-tools</artifactId>
|
<artifactId>dubbo-build-tools</artifactId>
|
||||||
<version>1.0.0</version>
|
<version>1.0.0</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<maven.deploy.skip>true</maven.deploy.skip>
|
<maven.deploy.skip>true</maven.deploy.skip>
|
||||||
<spotless-maven-plugin.version>2.43.0</spotless-maven-plugin.version>
|
</properties>
|
||||||
<spotless.action>check</spotless.action>
|
|
||||||
<dubbo-shared-resources.version>1.0.0</dubbo-shared-resources.version>
|
|
||||||
<palantirJavaFormat.version>2.38.0</palantirJavaFormat.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<profiles>
|
<build>
|
||||||
<profile>
|
|
||||||
<id>java11+</id>
|
|
||||||
<activation>
|
|
||||||
<jdk>[11,)</jdk>
|
|
||||||
</activation>
|
|
||||||
<build>
|
|
||||||
<!--- newer versions of plugins requires JDK 11 -->
|
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>com.diffplug.spotless</groupId>
|
<groupId>org.apache.rat</groupId>
|
||||||
<artifactId>spotless-maven-plugin</artifactId>
|
<artifactId>apache-rat-plugin</artifactId>
|
||||||
<version>${spotless-maven-plugin.version}</version>
|
<version>0.13</version>
|
||||||
<configuration>
|
<executions>
|
||||||
<java>
|
<execution>
|
||||||
<palantirJavaFormat>
|
<id>verify.rat</id>
|
||||||
<version>${palantirJavaFormat.version}</version>
|
<phase>verify</phase>
|
||||||
</palantirJavaFormat>
|
<goals>
|
||||||
<removeUnusedImports />
|
<goal>check</goal>
|
||||||
<importOrder>
|
</goals>
|
||||||
<file>dubbo-importorder.txt</file>
|
</execution>
|
||||||
</importOrder>
|
</executions>
|
||||||
<licenseHeader>
|
<configuration>
|
||||||
<file>checkstyle-header.txt</file>
|
<excludes>
|
||||||
</licenseHeader>
|
<exclude>**/*.versionsBackup</exclude>
|
||||||
</java>
|
<exclude>**/.idea/</exclude>
|
||||||
<pom>
|
<exclude>**/*.iml</exclude>
|
||||||
<sortPom>
|
<exclude>**/*.txt</exclude>
|
||||||
<expandEmptyElements>false</expandEmptyElements>
|
<exclude>**/*.load</exclude>
|
||||||
<spaceBeforeCloseEmptyElement>true</spaceBeforeCloseEmptyElement>
|
<exclude>**/*.flex</exclude>
|
||||||
</sortPom>
|
<exclude>**/*.fc</exclude>
|
||||||
</pom>
|
<exclude>**/*.javascript</exclude>
|
||||||
<upToDateChecking>
|
<exclude>**/*.properties</exclude>
|
||||||
<enabled>true</enabled>
|
<exclude>**/*.thrift</exclude>
|
||||||
</upToDateChecking>
|
<exclude>**/*.sh</exclude>
|
||||||
</configuration>
|
<exclude>**/*.bat</exclude>
|
||||||
<dependencies>
|
<exclude>**/*.md</exclude>
|
||||||
<dependency>
|
<exclude>.git/</exclude>
|
||||||
<groupId>com.alibaba</groupId>
|
<exclude>.gitignore</exclude>
|
||||||
<artifactId>dubbo-shared-resources</artifactId>
|
<exclude>.repository/</exclude>
|
||||||
<version>${dubbo-shared-resources.version}</version>
|
<exclude>**/.settings/*</exclude>
|
||||||
</dependency>
|
<exclude>**/.classpath</exclude>
|
||||||
</dependencies>
|
<exclude>**/.project</exclude>
|
||||||
<executions>
|
<exclude>**/target/**</exclude>
|
||||||
<execution>
|
<exclude>**/generated/**</exclude>
|
||||||
<goals>
|
<exclude>**/*.log</exclude>
|
||||||
<goal>${spotless.action}</goal>
|
<exclude>CONTRIBUTING.md</exclude>
|
||||||
</goals>
|
<exclude>README.md</exclude>
|
||||||
<phase>process-sources</phase>
|
<exclude>**/codestyle/*</exclude>
|
||||||
</execution>
|
<exclude>**/resources/META-INF/**</exclude>
|
||||||
</executions>
|
<exclude>.github/**</exclude>
|
||||||
</plugin>
|
<exclude>compiler/**</exclude>
|
||||||
|
</excludes>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</profile>
|
|
||||||
</profiles>
|
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
<!--
|
||||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
contributor license agreements. See the NOTICE file distributed with
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
|
@ -15,104 +14,53 @@
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
<modelVersion>4.0.0</modelVersion>
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
<parent>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.apache.dubbo</groupId>
|
<parent>
|
||||||
<artifactId>dubbo-parent</artifactId>
|
<groupId>org.apache.dubbo</groupId>
|
||||||
<version>${revision}</version>
|
<artifactId>dubbo-parent</artifactId>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<version>${revision}</version>
|
||||||
</parent>
|
<relativePath>../pom.xml</relativePath>
|
||||||
<artifactId>dubbo-cluster</artifactId>
|
</parent>
|
||||||
<packaging>jar</packaging>
|
<artifactId>dubbo-cluster</artifactId>
|
||||||
<name>${project.artifactId}</name>
|
<packaging>jar</packaging>
|
||||||
<description>The cluster module of dubbo project</description>
|
<name>${project.artifactId}</name>
|
||||||
<properties>
|
<description>The cluster module of dubbo project</description>
|
||||||
<skip_maven_deploy>false</skip_maven_deploy>
|
<properties>
|
||||||
<nashorn-core.version>15.4</nashorn-core.version>
|
<skip_maven_deploy>false</skip_maven_deploy>
|
||||||
</properties>
|
</properties>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.dubbo</groupId>
|
|
||||||
<artifactId>dubbo-rpc-api</artifactId>
|
|
||||||
<version>${project.parent.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.yaml</groupId>
|
|
||||||
<artifactId>snakeyaml</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.dubbo</groupId>
|
|
||||||
<artifactId>dubbo-rpc-injvm</artifactId>
|
|
||||||
<version>${project.parent.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.curator</groupId>
|
|
||||||
<artifactId>curator-framework</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.zookeeper</groupId>
|
|
||||||
<artifactId>zookeeper</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.dubbo</groupId>
|
|
||||||
<artifactId>dubbo-serialization-hessian2</artifactId>
|
|
||||||
<version>${project.parent.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.dubbo</groupId>
|
|
||||||
<artifactId>dubbo-serialization-fastjson2</artifactId>
|
|
||||||
<version>${project.parent.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.dubbo</groupId>
|
|
||||||
<artifactId>dubbo-test-check</artifactId>
|
|
||||||
<version>${project.parent.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.dubbo</groupId>
|
|
||||||
<artifactId>dubbo-metrics-registry</artifactId>
|
|
||||||
<version>${project.parent.version}</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.dubbo</groupId>
|
|
||||||
<artifactId>dubbo-metrics-default</artifactId>
|
|
||||||
<version>${project.parent.version}</version>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.micrometer</groupId>
|
|
||||||
<artifactId>micrometer-tracing-integration-test</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<profiles>
|
|
||||||
<!--
|
|
||||||
https://github.com/openjdk/nashorn
|
|
||||||
Nashorn used to be part of the JDK until Java 14.
|
|
||||||
This project provides a standalone version of Nashorn suitable for use with Java 11 and later.
|
|
||||||
-->
|
|
||||||
<profile>
|
|
||||||
<id>nashorn-jdk11</id>
|
|
||||||
<activation>
|
|
||||||
<jdk>[11,)</jdk>
|
|
||||||
</activation>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.openjdk.nashorn</groupId>
|
<groupId>org.apache.dubbo</groupId>
|
||||||
<artifactId>nashorn-core</artifactId>
|
<artifactId>dubbo-rpc-api</artifactId>
|
||||||
<version>${nashorn-core.version}</version>
|
<version>${project.parent.version}</version>
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
<dependency>
|
||||||
</profile>
|
<groupId>org.yaml</groupId>
|
||||||
</profiles>
|
<artifactId>snakeyaml</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.curator</groupId>
|
||||||
|
<artifactId>curator-framework</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.zookeeper</groupId>
|
||||||
|
<artifactId>zookeeper</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.dubbo</groupId>
|
||||||
|
<artifactId>dubbo-serialization-hessian2</artifactId>
|
||||||
|
<version>${project.parent.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.dubbo</groupId>
|
||||||
|
<artifactId>dubbo-test-check</artifactId>
|
||||||
|
<version>${project.parent.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
||||||
|
|
@ -35,5 +35,8 @@ public interface AddressListener {
|
||||||
*/
|
*/
|
||||||
List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
|
List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
|
||||||
|
|
||||||
default void destroy(URL consumerUrl, Directory registryDirectory) {}
|
default void destroy(URL consumerUrl, Directory registryDirectory) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
package org.apache.dubbo.rpc.cluster;
|
package org.apache.dubbo.rpc.cluster;
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
|
|
||||||
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
@ -31,7 +30,7 @@ public abstract class CacheableRouterFactory implements RouterFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Router getRouter(URL url) {
|
public Router getRouter(URL url) {
|
||||||
return ConcurrentHashMapUtils.computeIfAbsent(routerMap, url.getServiceKey(), k -> createRouter(url));
|
return routerMap.computeIfAbsent(url.getServiceKey(), k -> createRouter(url));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract Router createRouter(URL url);
|
protected abstract Router createRouter(URL url);
|
||||||
|
|
|
||||||
|
|
@ -55,8 +55,6 @@ public interface Cluster {
|
||||||
if (StringUtils.isEmpty(name)) {
|
if (StringUtils.isEmpty(name)) {
|
||||||
name = Cluster.DEFAULT;
|
name = Cluster.DEFAULT;
|
||||||
}
|
}
|
||||||
return ScopeModelUtil.getApplicationModel(scopeModel)
|
return ScopeModelUtil.getApplicationModel(scopeModel).getExtensionLoader(Cluster.class).getExtension(name, wrap);
|
||||||
.getExtensionLoader(Cluster.class)
|
|
||||||
.getExtension(name, wrap);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
package org.apache.dubbo.rpc.cluster;
|
package org.apache.dubbo.rpc.cluster;
|
||||||
|
|
||||||
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
|
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
|
||||||
import org.apache.dubbo.rpc.AdaptiveMetrics;
|
|
||||||
import org.apache.dubbo.rpc.cluster.merger.MergerFactory;
|
import org.apache.dubbo.rpc.cluster.merger.MergerFactory;
|
||||||
import org.apache.dubbo.rpc.cluster.router.RouterSnapshotSwitcher;
|
import org.apache.dubbo.rpc.cluster.router.RouterSnapshotSwitcher;
|
||||||
import org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleManager;
|
import org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleManager;
|
||||||
|
|
@ -39,7 +38,6 @@ public class ClusterScopeModelInitializer implements ScopeModelInitializer {
|
||||||
ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
|
ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
|
||||||
beanFactory.registerBean(MergerFactory.class);
|
beanFactory.registerBean(MergerFactory.class);
|
||||||
beanFactory.registerBean(ClusterUtils.class);
|
beanFactory.registerBean(ClusterUtils.class);
|
||||||
beanFactory.registerBean(AdaptiveMetrics.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ public interface Configurator extends Comparable<Configurator> {
|
||||||
*/
|
*/
|
||||||
URL configure(URL url);
|
URL configure(URL url);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert override urls to map for use when re-refer. Send all rules every time, the urls will be reassembled and
|
* Convert override urls to map for use when re-refer. Send all rules every time, the urls will be reassembled and
|
||||||
* calculated
|
* calculated
|
||||||
|
|
@ -72,9 +73,7 @@ public interface Configurator extends Comparable<Configurator> {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfiguratorFactory configuratorFactory = urls.get(0)
|
ConfiguratorFactory configuratorFactory = urls.get(0).getOrDefaultApplicationModel().getExtensionLoader(ConfiguratorFactory.class)
|
||||||
.getOrDefaultApplicationModel()
|
|
||||||
.getExtensionLoader(ConfiguratorFactory.class)
|
|
||||||
.getAdaptiveExtension();
|
.getAdaptiveExtension();
|
||||||
|
|
||||||
List<Configurator> configurators = new ArrayList<>(urls.size());
|
List<Configurator> configurators = new ArrayList<>(urls.size());
|
||||||
|
|
@ -84,8 +83,7 @@ public interface Configurator extends Comparable<Configurator> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Map<String, String> override = new HashMap<>(url.getParameters());
|
Map<String, String> override = new HashMap<>(url.getParameters());
|
||||||
// The anyhost parameter of override may be added automatically, it can't change the judgement of changing
|
//The anyhost parameter of override may be added automatically, it can't change the judgement of changing url
|
||||||
// url
|
|
||||||
override.remove(ANYHOST_KEY);
|
override.remove(ANYHOST_KEY);
|
||||||
if (CollectionUtils.isEmptyMap(override)) {
|
if (CollectionUtils.isEmptyMap(override)) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
package org.apache.dubbo.rpc.cluster;
|
package org.apache.dubbo.rpc.cluster;
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
import org.apache.dubbo.common.constants.CommonConstants;
|
|
||||||
import org.apache.dubbo.common.extension.Adaptive;
|
import org.apache.dubbo.common.extension.Adaptive;
|
||||||
import org.apache.dubbo.common.extension.SPI;
|
import org.apache.dubbo.common.extension.SPI;
|
||||||
|
|
||||||
|
|
@ -34,6 +33,7 @@ public interface ConfiguratorFactory {
|
||||||
* @param url - configurator url.
|
* @param url - configurator url.
|
||||||
* @return configurator instance.
|
* @return configurator instance.
|
||||||
*/
|
*/
|
||||||
@Adaptive(CommonConstants.PROTOCOL_KEY)
|
@Adaptive("protocol")
|
||||||
Configurator getConfigurator(URL url);
|
Configurator getConfigurator(URL url);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,8 @@ public interface Constants {
|
||||||
*/
|
*/
|
||||||
boolean DEFAULT_CLUSTER_STICKY = false;
|
boolean DEFAULT_CLUSTER_STICKY = false;
|
||||||
|
|
||||||
|
String ADDRESS_KEY = "address";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When this attribute appears in invocation's attachment, mock invoker will be used
|
* When this attribute appears in invocation's attachment, mock invoker will be used
|
||||||
*/
|
*/
|
||||||
|
|
@ -100,6 +102,7 @@ public interface Constants {
|
||||||
|
|
||||||
String OVERRIDE_PROVIDERS_KEY = "providerAddresses";
|
String OVERRIDE_PROVIDERS_KEY = "providerAddresses";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* key for router type, for e.g., "script"/"file", corresponding to ScriptRouterFactory.NAME, FileRouterFactory.NAME
|
* key for router type, for e.g., "script"/"file", corresponding to ScriptRouterFactory.NAME, FileRouterFactory.NAME
|
||||||
*/
|
*/
|
||||||
|
|
@ -134,8 +137,4 @@ public interface Constants {
|
||||||
String SHORTEST_RESPONSE_SLIDE_PERIOD = "shortestResponseSlidePeriod";
|
String SHORTEST_RESPONSE_SLIDE_PERIOD = "shortestResponseSlidePeriod";
|
||||||
|
|
||||||
String SHOULD_FAIL_FAST_KEY = "dubbo.router.should-fail-fast";
|
String SHOULD_FAIL_FAST_KEY = "dubbo.router.should-fail-fast";
|
||||||
|
|
||||||
String RULE_VERSION_V27 = "v2.7";
|
|
||||||
|
|
||||||
String RULE_VERSION_V30 = "v3.0";
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,4 +46,5 @@ public interface LoadBalance {
|
||||||
*/
|
*/
|
||||||
@Adaptive("loadbalance")
|
@Adaptive("loadbalance")
|
||||||
<T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException;
|
<T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,4 +22,5 @@ import org.apache.dubbo.common.extension.SPI;
|
||||||
public interface Merger<T> {
|
public interface Merger<T> {
|
||||||
|
|
||||||
T merge(T... items);
|
T merge(T... items);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,7 @@ public interface ProviderURLMergeProcessor {
|
||||||
*/
|
*/
|
||||||
URL mergeUrl(URL remoteUrl, Map<String, String> localParametersMap);
|
URL mergeUrl(URL remoteUrl, Map<String, String> localParametersMap);
|
||||||
|
|
||||||
default Map<String, String> mergeLocalParams(Map<String, String> localMap) {
|
default Map<String, String> mergeLocalParams(Map<String, String> localMap) { return localMap; }
|
||||||
return localMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean accept(URL providerUrl, Map<String, String> localParametersMap) {
|
default boolean accept(URL providerUrl, Map<String, String> localParametersMap) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -68,8 +68,8 @@ public interface Router extends Comparable<Router> {
|
||||||
* @return state with route result
|
* @return state with route result
|
||||||
* @throws RpcException
|
* @throws RpcException
|
||||||
*/
|
*/
|
||||||
default <T> RouterResult<Invoker<T>> route(
|
default <T> RouterResult<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation,
|
||||||
List<Invoker<T>> invokers, URL url, Invocation invocation, boolean needToPrintMessage) throws RpcException {
|
boolean needToPrintMessage) throws RpcException {
|
||||||
return new RouterResult<>(route(invokers, url, invocation));
|
return new RouterResult<>(route(invokers, url, invocation));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,7 +80,9 @@ public interface Router extends Comparable<Router> {
|
||||||
* @param invokers invoker list
|
* @param invokers invoker list
|
||||||
* @param <T> invoker's type
|
* @param <T> invoker's type
|
||||||
*/
|
*/
|
||||||
default <T> void notify(List<Invoker<T>> invokers) {}
|
default <T> void notify(List<Invoker<T>> invokers) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To decide whether this router need to execute every time an RPC comes or should only execute when addresses or
|
* To decide whether this router need to execute every time an RPC comes or should only execute when addresses or
|
||||||
|
|
@ -107,7 +109,7 @@ public interface Router extends Comparable<Router> {
|
||||||
int getPriority();
|
int getPriority();
|
||||||
|
|
||||||
default void stop() {
|
default void stop() {
|
||||||
// do nothing by default
|
//do nothing by default
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -17,23 +17,30 @@
|
||||||
package org.apache.dubbo.rpc.cluster;
|
package org.apache.dubbo.rpc.cluster;
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
|
import org.apache.dubbo.common.Version;
|
||||||
import org.apache.dubbo.common.config.ConfigurationUtils;
|
import org.apache.dubbo.common.config.ConfigurationUtils;
|
||||||
import org.apache.dubbo.common.constants.LoggerCodeConstants;
|
import org.apache.dubbo.common.logger.Logger;
|
||||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||||
|
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||||
|
import org.apache.dubbo.common.utils.Holder;
|
||||||
|
import org.apache.dubbo.common.utils.NetUtils;
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
import org.apache.dubbo.rpc.Invocation;
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
import org.apache.dubbo.rpc.Invoker;
|
||||||
|
import org.apache.dubbo.rpc.RpcContext;
|
||||||
|
import org.apache.dubbo.rpc.cluster.router.RouterResult;
|
||||||
|
import org.apache.dubbo.rpc.cluster.router.RouterSnapshotNode;
|
||||||
import org.apache.dubbo.rpc.cluster.router.RouterSnapshotSwitcher;
|
import org.apache.dubbo.rpc.cluster.router.RouterSnapshotSwitcher;
|
||||||
import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
||||||
import org.apache.dubbo.rpc.cluster.router.state.StateRouter;
|
import org.apache.dubbo.rpc.cluster.router.state.StateRouter;
|
||||||
import org.apache.dubbo.rpc.cluster.router.state.StateRouterFactory;
|
import org.apache.dubbo.rpc.cluster.router.state.StateRouterFactory;
|
||||||
|
import org.apache.dubbo.rpc.cluster.router.state.TailStateRouter;
|
||||||
import org.apache.dubbo.rpc.model.ModuleModel;
|
import org.apache.dubbo.rpc.model.ModuleModel;
|
||||||
import org.apache.dubbo.rpc.model.ScopeModelUtil;
|
import org.apache.dubbo.rpc.model.ScopeModelUtil;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
import java.util.concurrent.locks.ReadWriteLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.apache.dubbo.rpc.cluster.Constants.ROUTER_KEY;
|
import static org.apache.dubbo.rpc.cluster.Constants.ROUTER_KEY;
|
||||||
|
|
@ -42,205 +49,315 @@ import static org.apache.dubbo.rpc.cluster.Constants.ROUTER_KEY;
|
||||||
* Router chain
|
* Router chain
|
||||||
*/
|
*/
|
||||||
public class RouterChain<T> {
|
public class RouterChain<T> {
|
||||||
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(RouterChain.class);
|
private static final Logger logger = LoggerFactory.getLogger(RouterChain.class);
|
||||||
|
|
||||||
private volatile SingleRouterChain<T> mainChain;
|
/**
|
||||||
private volatile SingleRouterChain<T> backupChain;
|
* full list of addresses from registry, classified by method name.
|
||||||
private volatile SingleRouterChain<T> currentChain;
|
*/
|
||||||
|
private volatile BitList<Invoker<T>> invokers = BitList.emptyList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* containing all routers, reconstruct every time 'route://' urls change.
|
||||||
|
*/
|
||||||
|
private volatile List<Router> routers = Collections.emptyList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fixed router instances: ConfigConditionRouter, TagRouter, e.g.,
|
||||||
|
* the rule for each instance may change but the instance will never delete or recreate.
|
||||||
|
*/
|
||||||
|
private volatile List<Router> builtinRouters = Collections.emptyList();
|
||||||
|
|
||||||
|
private volatile StateRouter<T> headStateRouter;
|
||||||
|
|
||||||
|
private volatile List<StateRouter<T>> stateRouters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should continue route if current router's result is empty
|
||||||
|
*/
|
||||||
|
private final boolean shouldFailFast;
|
||||||
|
|
||||||
|
private final RouterSnapshotSwitcher routerSnapshotSwitcher;
|
||||||
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public static <T> RouterChain<T> buildChain(Class<T> interfaceClass, URL url) {
|
public static <T> RouterChain<T> buildChain(Class<T> interfaceClass, URL url) {
|
||||||
SingleRouterChain<T> chain1 = buildSingleChain(interfaceClass, url);
|
|
||||||
SingleRouterChain<T> chain2 = buildSingleChain(interfaceClass, url);
|
|
||||||
return new RouterChain<>(new SingleRouterChain[] {chain1, chain2});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> SingleRouterChain<T> buildSingleChain(Class<T> interfaceClass, URL url) {
|
|
||||||
ModuleModel moduleModel = url.getOrDefaultModuleModel();
|
ModuleModel moduleModel = url.getOrDefaultModuleModel();
|
||||||
|
|
||||||
List<RouterFactory> extensionFactories =
|
List<RouterFactory> extensionFactories = moduleModel.getExtensionLoader(RouterFactory.class)
|
||||||
moduleModel.getExtensionLoader(RouterFactory.class).getActivateExtension(url, ROUTER_KEY);
|
.getActivateExtension(url, ROUTER_KEY);
|
||||||
|
|
||||||
List<Router> routers = extensionFactories.stream()
|
List<Router> routers = extensionFactories.stream()
|
||||||
.map(factory -> factory.getRouter(url))
|
.map(factory -> factory.getRouter(url))
|
||||||
.sorted(Router::compareTo)
|
.sorted(Router::compareTo)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
List<StateRouter<T>> stateRouters =
|
List<StateRouter<T>> stateRouters = moduleModel
|
||||||
moduleModel.getExtensionLoader(StateRouterFactory.class).getActivateExtension(url, ROUTER_KEY).stream()
|
.getExtensionLoader(StateRouterFactory.class)
|
||||||
.map(factory -> factory.getRouter(interfaceClass, url))
|
.getActivateExtension(url, ROUTER_KEY)
|
||||||
.collect(Collectors.toList());
|
.stream()
|
||||||
|
.map(factory -> factory.getRouter(interfaceClass, url))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
boolean shouldFailFast = Boolean.parseBoolean(
|
|
||||||
ConfigurationUtils.getProperty(moduleModel, Constants.SHOULD_FAIL_FAST_KEY, "true"));
|
|
||||||
|
|
||||||
RouterSnapshotSwitcher routerSnapshotSwitcher =
|
boolean shouldFailFast = Boolean.parseBoolean(ConfigurationUtils.getProperty(moduleModel, Constants.SHOULD_FAIL_FAST_KEY, "true"));
|
||||||
ScopeModelUtil.getFrameworkModel(moduleModel).getBeanFactory().getBean(RouterSnapshotSwitcher.class);
|
|
||||||
|
|
||||||
return new SingleRouterChain<>(routers, stateRouters, shouldFailFast, routerSnapshotSwitcher);
|
RouterSnapshotSwitcher routerSnapshotSwitcher = ScopeModelUtil.getFrameworkModel(moduleModel).getBeanFactory().getBean(RouterSnapshotSwitcher.class);
|
||||||
|
|
||||||
|
return new RouterChain<>(routers, stateRouters, shouldFailFast, routerSnapshotSwitcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RouterChain(SingleRouterChain<T>[] chains) {
|
public RouterChain(List<Router> routers, List<StateRouter<T>> stateRouters, boolean shouldFailFast, RouterSnapshotSwitcher routerSnapshotSwitcher) {
|
||||||
if (chains.length != 2) {
|
initWithRouters(routers);
|
||||||
throw new IllegalArgumentException("chains' size should be 2.");
|
|
||||||
|
initWithStateRouters(stateRouters);
|
||||||
|
|
||||||
|
this.shouldFailFast = shouldFailFast;
|
||||||
|
this.routerSnapshotSwitcher = routerSnapshotSwitcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initWithStateRouters(List<StateRouter<T>> stateRouters) {
|
||||||
|
StateRouter<T> stateRouter = TailStateRouter.getInstance();
|
||||||
|
for (int i = stateRouters.size() - 1; i >= 0; i--) {
|
||||||
|
StateRouter<T> nextStateRouter = stateRouters.get(i);
|
||||||
|
nextStateRouter.setNextRouter(stateRouter);
|
||||||
|
stateRouter = nextStateRouter;
|
||||||
}
|
}
|
||||||
this.mainChain = chains[0];
|
this.headStateRouter = stateRouter;
|
||||||
this.backupChain = chains[1];
|
this.stateRouters = Collections.unmodifiableList(stateRouters);
|
||||||
this.currentChain = this.mainChain;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final AtomicReference<BitList<Invoker<T>>> notifyingInvokers = new AtomicReference<>();
|
|
||||||
|
|
||||||
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
|
||||||
|
|
||||||
public ReadWriteLock getLock() {
|
|
||||||
return lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SingleRouterChain<T> getSingleChain(URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
|
|
||||||
// If current is in:
|
|
||||||
// 1. `setInvokers` is in progress
|
|
||||||
// 2. Most of the invocation should use backup chain => currentChain == backupChain
|
|
||||||
// 3. Main chain has been update success => notifyingInvokers.get() != null
|
|
||||||
// If `availableInvokers` is created from origin invokers => use backup chain
|
|
||||||
// If `availableInvokers` is created from newly invokers => use main chain
|
|
||||||
BitList<Invoker<T>> notifying = notifyingInvokers.get();
|
|
||||||
if (notifying != null
|
|
||||||
&& currentChain == backupChain
|
|
||||||
&& availableInvokers.getOriginList() == notifying.getOriginList()) {
|
|
||||||
return mainChain;
|
|
||||||
}
|
|
||||||
return currentChain;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated use {@link RouterChain#getSingleChain(URL, BitList, Invocation)} and {@link SingleRouterChain#route(URL, BitList, Invocation)} instead
|
* the resident routers must being initialized before address notification.
|
||||||
|
* only for ut
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
public void initWithRouters(List<Router> builtinRouters) {
|
||||||
|
this.builtinRouters = builtinRouters;
|
||||||
|
this.routers = new LinkedList<>(builtinRouters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If we use route:// protocol in version before 2.7.0, each URL will generate a Router instance, so we should
|
||||||
|
* keep the routers up to date, that is, each time router URLs changes, we should update the routers list, only
|
||||||
|
* keep the builtinRouters which are available all the time and the latest notified routers which are generated
|
||||||
|
* from URLs.
|
||||||
|
*
|
||||||
|
* @param routers routers from 'router://' rules in 2.6.x or before.
|
||||||
|
*/
|
||||||
|
public void addRouters(List<Router> routers) {
|
||||||
|
List<Router> newRouters = new LinkedList<>();
|
||||||
|
newRouters.addAll(builtinRouters);
|
||||||
|
newRouters.addAll(routers);
|
||||||
|
CollectionUtils.sort(newRouters);
|
||||||
|
this.routers = newRouters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Router> getRouters() {
|
||||||
|
return routers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StateRouter<T> getHeadStateRouter() {
|
||||||
|
return headStateRouter;
|
||||||
|
}
|
||||||
|
|
||||||
public List<Invoker<T>> route(URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
|
public List<Invoker<T>> route(URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
|
||||||
return getSingleChain(url, availableInvokers, invocation).route(url, availableInvokers, invocation);
|
if (RpcContext.getServiceContext().isNeedPrintRouterSnapshot()) {
|
||||||
|
return routeAndPrint(url, availableInvokers, invocation);
|
||||||
|
} else {
|
||||||
|
return simpleRoute(url, availableInvokers, invocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Invoker<T>> routeAndPrint(URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
|
||||||
|
RouterSnapshotNode<T> snapshot = buildRouterSnapshot(url, availableInvokers, invocation);
|
||||||
|
logRouterSnapshot(url, invocation, snapshot);
|
||||||
|
return snapshot.getChainOutputInvokers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Invoker<T>> simpleRoute(URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
|
||||||
|
BitList<Invoker<T>> resultInvokers = availableInvokers.clone();
|
||||||
|
|
||||||
|
// 1. route state router
|
||||||
|
resultInvokers = headStateRouter.route(resultInvokers, url, invocation, false, null);
|
||||||
|
if (resultInvokers.isEmpty() && (shouldFailFast || routers.isEmpty())) {
|
||||||
|
printRouterSnapshot(url, availableInvokers, invocation);
|
||||||
|
return BitList.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (routers.isEmpty()) {
|
||||||
|
return resultInvokers;
|
||||||
|
}
|
||||||
|
List<Invoker<T>> commonRouterResult = resultInvokers.cloneToArrayList();
|
||||||
|
// 2. route common router
|
||||||
|
for (Router router : routers) {
|
||||||
|
// Copy resultInvokers to a arrayList. BitList not support
|
||||||
|
RouterResult<Invoker<T>> routeResult = router.route(commonRouterResult, url, invocation, false);
|
||||||
|
commonRouterResult = routeResult.getResult();
|
||||||
|
if (CollectionUtils.isEmpty(commonRouterResult) && shouldFailFast) {
|
||||||
|
printRouterSnapshot(url, availableInvokers, invocation);
|
||||||
|
return BitList.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop continue routing
|
||||||
|
if (!routeResult.isNeedContinueRoute()) {
|
||||||
|
return commonRouterResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commonRouterResult.isEmpty()) {
|
||||||
|
printRouterSnapshot(url, availableInvokers, invocation);
|
||||||
|
return BitList.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return commonRouterResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* store each router's input and output, log out if empty
|
||||||
|
*/
|
||||||
|
private void printRouterSnapshot(URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
|
||||||
|
if (logger.isWarnEnabled()) {
|
||||||
|
logRouterSnapshot(url, invocation, buildRouterSnapshot(url, availableInvokers, invocation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build each router's result
|
||||||
|
*/
|
||||||
|
public RouterSnapshotNode<T> buildRouterSnapshot(URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
|
||||||
|
BitList<Invoker<T>> resultInvokers = availableInvokers.clone();
|
||||||
|
RouterSnapshotNode<T> parentNode = new RouterSnapshotNode<T>("Parent", resultInvokers.clone());
|
||||||
|
parentNode.setNodeOutputInvokers(resultInvokers.clone());
|
||||||
|
|
||||||
|
// 1. route state router
|
||||||
|
Holder<RouterSnapshotNode<T>> nodeHolder = new Holder<>();
|
||||||
|
nodeHolder.set(parentNode);
|
||||||
|
|
||||||
|
resultInvokers = headStateRouter.route(resultInvokers, url, invocation, true, nodeHolder);
|
||||||
|
|
||||||
|
// result is empty, log out
|
||||||
|
if (routers.isEmpty() || (resultInvokers.isEmpty() && shouldFailFast)) {
|
||||||
|
parentNode.setChainOutputInvokers(resultInvokers.clone());
|
||||||
|
return parentNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
RouterSnapshotNode<T> commonRouterNode = new RouterSnapshotNode<T>("CommonRouter", resultInvokers.clone());
|
||||||
|
parentNode.appendNode(commonRouterNode);
|
||||||
|
List<Invoker<T>> commonRouterResult = resultInvokers;
|
||||||
|
// 2. route common router
|
||||||
|
for (Router router : routers) {
|
||||||
|
// Copy resultInvokers to a arrayList. BitList not support
|
||||||
|
List<Invoker<T>> inputInvokers = new ArrayList<>(commonRouterResult);
|
||||||
|
|
||||||
|
RouterSnapshotNode<T> currentNode = new RouterSnapshotNode<T>(router.getClass().getSimpleName(), inputInvokers);
|
||||||
|
|
||||||
|
// append to router node chain
|
||||||
|
commonRouterNode.appendNode(currentNode);
|
||||||
|
commonRouterNode = currentNode;
|
||||||
|
|
||||||
|
RouterResult<Invoker<T>> routeStateResult = router.route(inputInvokers, url, invocation, true);
|
||||||
|
List<Invoker<T>> routeResult = routeStateResult.getResult();
|
||||||
|
String routerMessage = routeStateResult.getMessage();
|
||||||
|
|
||||||
|
currentNode.setNodeOutputInvokers(routeResult);
|
||||||
|
currentNode.setRouterMessage(routerMessage);
|
||||||
|
|
||||||
|
commonRouterResult = routeResult;
|
||||||
|
|
||||||
|
// result is empty, log out
|
||||||
|
if (CollectionUtils.isEmpty(routeResult) && shouldFailFast) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!routeStateResult.isNeedContinueRoute()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
commonRouterNode.setChainOutputInvokers(commonRouterNode.getNodeOutputInvokers());
|
||||||
|
|
||||||
|
// 3. set router chain output reverse
|
||||||
|
RouterSnapshotNode<T> currentNode = commonRouterNode;
|
||||||
|
while (currentNode != null){
|
||||||
|
RouterSnapshotNode<T> parent = currentNode.getParentNode();
|
||||||
|
if (parent != null) {
|
||||||
|
// common router only has one child invoke
|
||||||
|
parent.setChainOutputInvokers(currentNode.getChainOutputInvokers());
|
||||||
|
}
|
||||||
|
currentNode = parent;
|
||||||
|
}
|
||||||
|
return parentNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void logRouterSnapshot(URL url, Invocation invocation, RouterSnapshotNode<T> snapshotNode) {
|
||||||
|
if (snapshotNode.getChainOutputInvokers() == null ||
|
||||||
|
snapshotNode.getChainOutputInvokers().isEmpty()) {
|
||||||
|
if (logger.isWarnEnabled()) {
|
||||||
|
String message = "No provider available after route for the service " + url.getServiceKey()
|
||||||
|
+ " from registry " + url.getAddress()
|
||||||
|
+ " on the consumer " + NetUtils.getLocalHost()
|
||||||
|
+ " using the dubbo version " + Version.getVersion() + ". Router snapshot is below: \n" + snapshotNode.toString();
|
||||||
|
if (routerSnapshotSwitcher.isEnable()) {
|
||||||
|
routerSnapshotSwitcher.setSnapshot(message);
|
||||||
|
}
|
||||||
|
logger.warn(message);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (logger.isInfoEnabled()) {
|
||||||
|
String message = "Router snapshot service " + url.getServiceKey()
|
||||||
|
+ " from registry " + url.getAddress()
|
||||||
|
+ " on the consumer " + NetUtils.getLocalHost()
|
||||||
|
+ " using the dubbo version " + Version.getVersion() + " is below: \n" + snapshotNode.toString();
|
||||||
|
if (routerSnapshotSwitcher.isEnable()) {
|
||||||
|
routerSnapshotSwitcher.setSnapshot(message);
|
||||||
|
}
|
||||||
|
logger.info(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify router chain of the initial addresses from registry at the first time.
|
* Notify router chain of the initial addresses from registry at the first time.
|
||||||
* Notify whenever addresses in registry change.
|
* Notify whenever addresses in registry change.
|
||||||
*/
|
*/
|
||||||
public synchronized void setInvokers(BitList<Invoker<T>> invokers, Runnable switchAction) {
|
public void setInvokers(BitList<Invoker<T>> invokers) {
|
||||||
try {
|
this.invokers = (invokers == null ? BitList.emptyList() : invokers);
|
||||||
// Lock to prevent directory continue list
|
routers.forEach(router -> router.notify(this.invokers));
|
||||||
lock.writeLock().lock();
|
stateRouters.forEach(router -> router.notify(this.invokers));
|
||||||
|
|
||||||
// Switch to back up chain. Will update main chain first.
|
|
||||||
currentChain = backupChain;
|
|
||||||
} finally {
|
|
||||||
// Release lock to minimize the impact for each newly created invocations as much as possible.
|
|
||||||
// Should not release lock until main chain update finished. Or this may cause long hang.
|
|
||||||
lock.writeLock().unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refresh main chain.
|
|
||||||
// No one can request to use main chain. `currentChain` is backup chain. `route` method cannot access main
|
|
||||||
// chain.
|
|
||||||
try {
|
|
||||||
// Lock main chain to wait all invocation end
|
|
||||||
// To wait until no one is using main chain.
|
|
||||||
mainChain.getLock().writeLock().lock();
|
|
||||||
|
|
||||||
// refresh
|
|
||||||
mainChain.setInvokers(invokers);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
logger.error(LoggerCodeConstants.INTERNAL_ERROR, "", "", "Error occurred when refreshing router chain.", t);
|
|
||||||
throw t;
|
|
||||||
} finally {
|
|
||||||
// Unlock main chain
|
|
||||||
mainChain.getLock().writeLock().unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the reference of newly invokers to temp variable.
|
|
||||||
// Reason: The next step will switch the invokers reference in directory, so we should check the
|
|
||||||
// `availableInvokers`
|
|
||||||
// argument when `route`. If the current invocation use newly invokers, we should use main chain to
|
|
||||||
// route, and
|
|
||||||
// this can prevent use newly invokers to route backup chain, which can only route origin invokers now.
|
|
||||||
notifyingInvokers.set(invokers);
|
|
||||||
|
|
||||||
// Switch the invokers reference in directory.
|
|
||||||
// Cannot switch before update main chain or after backup chain update success. Or that will cause state
|
|
||||||
// inconsistent.
|
|
||||||
switchAction.run();
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Lock to prevent directory continue list
|
|
||||||
// The invokers reference in directory now should be the newly one and should always use the newly one once
|
|
||||||
// lock released.
|
|
||||||
lock.writeLock().lock();
|
|
||||||
|
|
||||||
// Switch to main chain. Will update backup chain later.
|
|
||||||
currentChain = mainChain;
|
|
||||||
|
|
||||||
// Clean up temp variable.
|
|
||||||
// `availableInvokers` check is useless now, because `route` method will no longer receive any
|
|
||||||
// `availableInvokers` related
|
|
||||||
// with the origin invokers. The getter of invokers reference in directory is locked now, and will return
|
|
||||||
// newly invokers
|
|
||||||
// once lock released.
|
|
||||||
notifyingInvokers.set(null);
|
|
||||||
} finally {
|
|
||||||
// Release lock to minimize the impact for each newly created invocations as much as possible.
|
|
||||||
// Will use newly invokers and main chain now.
|
|
||||||
lock.writeLock().unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refresh main chain.
|
|
||||||
// No one can request to use main chain. `currentChain` is main chain. `route` method cannot access backup
|
|
||||||
// chain.
|
|
||||||
try {
|
|
||||||
// Lock main chain to wait all invocation end
|
|
||||||
backupChain.getLock().writeLock().lock();
|
|
||||||
|
|
||||||
// refresh
|
|
||||||
backupChain.setInvokers(invokers);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
logger.error(LoggerCodeConstants.INTERNAL_ERROR, "", "", "Error occurred when refreshing router chain.", t);
|
|
||||||
throw t;
|
|
||||||
} finally {
|
|
||||||
// Unlock backup chain
|
|
||||||
backupChain.getLock().writeLock().unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void destroy() {
|
/**
|
||||||
// 1. destroy another
|
* for uts only
|
||||||
backupChain.destroy();
|
*/
|
||||||
|
@Deprecated
|
||||||
// 2. switch
|
public void setHeadStateRouter(StateRouter<T> headStateRouter) {
|
||||||
lock.writeLock().lock();
|
this.headStateRouter = headStateRouter;
|
||||||
currentChain = backupChain;
|
|
||||||
lock.writeLock().unlock();
|
|
||||||
|
|
||||||
// 4. destroy
|
|
||||||
mainChain.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addRouters(List<Router> routers) {
|
|
||||||
mainChain.addRouters(routers);
|
|
||||||
backupChain.addRouters(routers);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SingleRouterChain<T> getCurrentChain() {
|
|
||||||
return currentChain;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Router> getRouters() {
|
|
||||||
return currentChain.getRouters();
|
|
||||||
}
|
|
||||||
|
|
||||||
public StateRouter<T> getHeadStateRouter() {
|
|
||||||
return currentChain.getHeadStateRouter();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for uts only
|
||||||
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public List<StateRouter<T>> getStateRouters() {
|
public List<StateRouter<T>> getStateRouters() {
|
||||||
return currentChain.getStateRouters();
|
return stateRouters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy() {
|
||||||
|
invokers = BitList.emptyList();
|
||||||
|
for (Router router : routers) {
|
||||||
|
try {
|
||||||
|
router.stop();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Error trying to stop router " + router.getClass(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
routers = Collections.emptyList();
|
||||||
|
builtinRouters = Collections.emptyList();
|
||||||
|
|
||||||
|
for (StateRouter<T> router : stateRouters) {
|
||||||
|
try {
|
||||||
|
router.stop();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Error trying to stop stateRouter " + router.getClass(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stateRouters = Collections.emptyList();
|
||||||
|
headStateRouter = TailStateRouter.getInstance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
package org.apache.dubbo.rpc.cluster;
|
package org.apache.dubbo.rpc.cluster;
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
import org.apache.dubbo.common.constants.CommonConstants;
|
|
||||||
import org.apache.dubbo.common.extension.Adaptive;
|
import org.apache.dubbo.common.extension.Adaptive;
|
||||||
import org.apache.dubbo.common.extension.SPI;
|
import org.apache.dubbo.common.extension.SPI;
|
||||||
|
|
||||||
|
|
@ -43,6 +42,6 @@ public interface RouterFactory {
|
||||||
* @param url url
|
* @param url url
|
||||||
* @return router instance
|
* @return router instance
|
||||||
*/
|
*/
|
||||||
@Adaptive(CommonConstants.PROTOCOL_KEY)
|
@Adaptive("protocol")
|
||||||
Router getRouter(URL url);
|
Router getRouter(URL url);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.apache.dubbo.rpc.cluster;
|
package org.apache.dubbo.rpc.cluster;
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
|
|
@ -25,4 +26,5 @@ import java.util.List;
|
||||||
public interface RuleConverter {
|
public interface RuleConverter {
|
||||||
|
|
||||||
List<URL> convert(URL subscribeUrl, Object source);
|
List<URL> convert(URL subscribeUrl, Object source);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,371 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
package org.apache.dubbo.rpc.cluster;
|
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
|
||||||
import org.apache.dubbo.common.Version;
|
|
||||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
|
||||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
|
||||||
import org.apache.dubbo.common.utils.Holder;
|
|
||||||
import org.apache.dubbo.common.utils.NetUtils;
|
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
|
||||||
import org.apache.dubbo.rpc.RpcContext;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.RouterResult;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.RouterSnapshotNode;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.RouterSnapshotSwitcher;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.state.StateRouter;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.state.TailStateRouter;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.locks.ReadWriteLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_FAILED_STOP;
|
|
||||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_NO_VALID_PROVIDER;
|
|
||||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_ERROR;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Router chain
|
|
||||||
*/
|
|
||||||
public class SingleRouterChain<T> {
|
|
||||||
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(SingleRouterChain.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* full list of addresses from registry, classified by method name.
|
|
||||||
*/
|
|
||||||
private volatile BitList<Invoker<T>> invokers = BitList.emptyList();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* containing all routers, reconstruct every time 'route://' urls change.
|
|
||||||
*/
|
|
||||||
private volatile List<Router> routers = Collections.emptyList();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fixed router instances: ConfigConditionRouter, TagRouter, e.g.,
|
|
||||||
* the rule for each instance may change but the instance will never delete or recreate.
|
|
||||||
*/
|
|
||||||
private volatile List<Router> builtinRouters = Collections.emptyList();
|
|
||||||
|
|
||||||
private volatile StateRouter<T> headStateRouter;
|
|
||||||
|
|
||||||
private volatile List<StateRouter<T>> stateRouters;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Should continue route if current router's result is empty
|
|
||||||
*/
|
|
||||||
private final boolean shouldFailFast;
|
|
||||||
|
|
||||||
private final RouterSnapshotSwitcher routerSnapshotSwitcher;
|
|
||||||
|
|
||||||
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
|
||||||
|
|
||||||
public SingleRouterChain(
|
|
||||||
List<Router> routers,
|
|
||||||
List<StateRouter<T>> stateRouters,
|
|
||||||
boolean shouldFailFast,
|
|
||||||
RouterSnapshotSwitcher routerSnapshotSwitcher) {
|
|
||||||
initWithRouters(routers);
|
|
||||||
|
|
||||||
initWithStateRouters(stateRouters);
|
|
||||||
|
|
||||||
this.shouldFailFast = shouldFailFast;
|
|
||||||
this.routerSnapshotSwitcher = routerSnapshotSwitcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initWithStateRouters(List<StateRouter<T>> stateRouters) {
|
|
||||||
StateRouter<T> stateRouter = TailStateRouter.getInstance();
|
|
||||||
for (int i = stateRouters.size() - 1; i >= 0; i--) {
|
|
||||||
StateRouter<T> nextStateRouter = stateRouters.get(i);
|
|
||||||
nextStateRouter.setNextRouter(stateRouter);
|
|
||||||
stateRouter = nextStateRouter;
|
|
||||||
}
|
|
||||||
this.headStateRouter = stateRouter;
|
|
||||||
this.stateRouters = Collections.unmodifiableList(stateRouters);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the resident routers must being initialized before address notification.
|
|
||||||
* only for ut
|
|
||||||
*/
|
|
||||||
public void initWithRouters(List<Router> builtinRouters) {
|
|
||||||
this.builtinRouters = builtinRouters;
|
|
||||||
this.routers = new LinkedList<>(builtinRouters);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If we use route:// protocol in version before 2.7.0, each URL will generate a Router instance, so we should
|
|
||||||
* keep the routers up to date, that is, each time router URLs changes, we should update the routers list, only
|
|
||||||
* keep the builtinRouters which are available all the time and the latest notified routers which are generated
|
|
||||||
* from URLs.
|
|
||||||
*
|
|
||||||
* @param routers routers from 'router://' rules in 2.6.x or before.
|
|
||||||
*/
|
|
||||||
public void addRouters(List<Router> routers) {
|
|
||||||
List<Router> newRouters = new LinkedList<>();
|
|
||||||
newRouters.addAll(builtinRouters);
|
|
||||||
newRouters.addAll(routers);
|
|
||||||
CollectionUtils.sort(newRouters);
|
|
||||||
this.routers = newRouters;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Router> getRouters() {
|
|
||||||
return routers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StateRouter<T> getHeadStateRouter() {
|
|
||||||
return headStateRouter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Invoker<T>> route(URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
|
|
||||||
if (invokers.getOriginList() != availableInvokers.getOriginList()) {
|
|
||||||
logger.error(
|
|
||||||
INTERNAL_ERROR,
|
|
||||||
"",
|
|
||||||
"Router's invoker size: " + invokers.getOriginList().size() + " Invocation's invoker size: "
|
|
||||||
+ availableInvokers.getOriginList().size(),
|
|
||||||
"Reject to route, because the invokers has changed.");
|
|
||||||
throw new IllegalStateException("reject to route, because the invokers has changed.");
|
|
||||||
}
|
|
||||||
if (RpcContext.getServiceContext().isNeedPrintRouterSnapshot()) {
|
|
||||||
return routeAndPrint(url, availableInvokers, invocation);
|
|
||||||
} else {
|
|
||||||
return simpleRoute(url, availableInvokers, invocation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Invoker<T>> routeAndPrint(URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
|
|
||||||
RouterSnapshotNode<T> snapshot = buildRouterSnapshot(url, availableInvokers, invocation);
|
|
||||||
logRouterSnapshot(url, invocation, snapshot);
|
|
||||||
return snapshot.getChainOutputInvokers();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Invoker<T>> simpleRoute(URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
|
|
||||||
BitList<Invoker<T>> resultInvokers = availableInvokers.clone();
|
|
||||||
|
|
||||||
// 1. route state router
|
|
||||||
resultInvokers = headStateRouter.route(resultInvokers, url, invocation, false, null);
|
|
||||||
if (resultInvokers.isEmpty() && (shouldFailFast || routers.isEmpty())) {
|
|
||||||
printRouterSnapshot(url, availableInvokers, invocation);
|
|
||||||
return BitList.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (routers.isEmpty()) {
|
|
||||||
return resultInvokers;
|
|
||||||
}
|
|
||||||
List<Invoker<T>> commonRouterResult = resultInvokers.cloneToArrayList();
|
|
||||||
// 2. route common router
|
|
||||||
for (Router router : routers) {
|
|
||||||
// Copy resultInvokers to a arrayList. BitList not support
|
|
||||||
RouterResult<Invoker<T>> routeResult = router.route(commonRouterResult, url, invocation, false);
|
|
||||||
commonRouterResult = routeResult.getResult();
|
|
||||||
if (CollectionUtils.isEmpty(commonRouterResult) && shouldFailFast) {
|
|
||||||
printRouterSnapshot(url, availableInvokers, invocation);
|
|
||||||
return BitList.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
// stop continue routing
|
|
||||||
if (!routeResult.isNeedContinueRoute()) {
|
|
||||||
return commonRouterResult;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (commonRouterResult.isEmpty()) {
|
|
||||||
printRouterSnapshot(url, availableInvokers, invocation);
|
|
||||||
return BitList.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return commonRouterResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* store each router's input and output, log out if empty
|
|
||||||
*/
|
|
||||||
private void printRouterSnapshot(URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
|
|
||||||
if (logger.isWarnEnabled()) {
|
|
||||||
logRouterSnapshot(url, invocation, buildRouterSnapshot(url, availableInvokers, invocation));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build each router's result
|
|
||||||
*/
|
|
||||||
public RouterSnapshotNode<T> buildRouterSnapshot(
|
|
||||||
URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
|
|
||||||
BitList<Invoker<T>> resultInvokers = availableInvokers.clone();
|
|
||||||
RouterSnapshotNode<T> parentNode = new RouterSnapshotNode<>("Parent", resultInvokers.clone());
|
|
||||||
parentNode.setNodeOutputInvokers(resultInvokers.clone());
|
|
||||||
|
|
||||||
// 1. route state router
|
|
||||||
Holder<RouterSnapshotNode<T>> nodeHolder = new Holder<>();
|
|
||||||
nodeHolder.set(parentNode);
|
|
||||||
|
|
||||||
resultInvokers = headStateRouter.route(resultInvokers, url, invocation, true, nodeHolder);
|
|
||||||
|
|
||||||
// result is empty, log out
|
|
||||||
if (routers.isEmpty() || (resultInvokers.isEmpty() && shouldFailFast)) {
|
|
||||||
parentNode.setChainOutputInvokers(resultInvokers.clone());
|
|
||||||
return parentNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
RouterSnapshotNode<T> commonRouterNode = new RouterSnapshotNode<>("CommonRouter", resultInvokers.clone());
|
|
||||||
parentNode.appendNode(commonRouterNode);
|
|
||||||
List<Invoker<T>> commonRouterResult = resultInvokers;
|
|
||||||
|
|
||||||
// 2. route common router
|
|
||||||
for (Router router : routers) {
|
|
||||||
// Copy resultInvokers to a arrayList. BitList not support
|
|
||||||
List<Invoker<T>> inputInvokers = new ArrayList<>(commonRouterResult);
|
|
||||||
|
|
||||||
RouterSnapshotNode<T> currentNode =
|
|
||||||
new RouterSnapshotNode<>(router.getClass().getSimpleName(), inputInvokers);
|
|
||||||
|
|
||||||
// append to router node chain
|
|
||||||
commonRouterNode.appendNode(currentNode);
|
|
||||||
commonRouterNode = currentNode;
|
|
||||||
|
|
||||||
RouterResult<Invoker<T>> routeStateResult = router.route(inputInvokers, url, invocation, true);
|
|
||||||
List<Invoker<T>> routeResult = routeStateResult.getResult();
|
|
||||||
String routerMessage = routeStateResult.getMessage();
|
|
||||||
|
|
||||||
currentNode.setNodeOutputInvokers(routeResult);
|
|
||||||
currentNode.setRouterMessage(routerMessage);
|
|
||||||
|
|
||||||
commonRouterResult = routeResult;
|
|
||||||
|
|
||||||
// result is empty, log out
|
|
||||||
if (CollectionUtils.isEmpty(routeResult) && shouldFailFast) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!routeStateResult.isNeedContinueRoute()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
commonRouterNode.setChainOutputInvokers(commonRouterNode.getNodeOutputInvokers());
|
|
||||||
|
|
||||||
// 3. set router chain output reverse
|
|
||||||
RouterSnapshotNode<T> currentNode = commonRouterNode;
|
|
||||||
while (currentNode != null) {
|
|
||||||
RouterSnapshotNode<T> parent = currentNode.getParentNode();
|
|
||||||
if (parent != null) {
|
|
||||||
// common router only has one child invoke
|
|
||||||
parent.setChainOutputInvokers(currentNode.getChainOutputInvokers());
|
|
||||||
}
|
|
||||||
currentNode = parent;
|
|
||||||
}
|
|
||||||
return parentNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void logRouterSnapshot(URL url, Invocation invocation, RouterSnapshotNode<T> snapshotNode) {
|
|
||||||
if (snapshotNode.getChainOutputInvokers() == null
|
|
||||||
|| snapshotNode.getChainOutputInvokers().isEmpty()) {
|
|
||||||
if (logger.isWarnEnabled()) {
|
|
||||||
String message = "No provider available after route for the service " + url.getServiceKey()
|
|
||||||
+ " from registry " + url.getAddress()
|
|
||||||
+ " on the consumer " + NetUtils.getLocalHost()
|
|
||||||
+ " using the dubbo version " + Version.getVersion() + ". Router snapshot is below: \n"
|
|
||||||
+ snapshotNode.toString();
|
|
||||||
if (routerSnapshotSwitcher.isEnable()) {
|
|
||||||
routerSnapshotSwitcher.setSnapshot(message);
|
|
||||||
}
|
|
||||||
logger.warn(
|
|
||||||
CLUSTER_NO_VALID_PROVIDER, "No provider available after route for the service", "", message);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (logger.isInfoEnabled()) {
|
|
||||||
String message = "Router snapshot service " + url.getServiceKey()
|
|
||||||
+ " from registry " + url.getAddress()
|
|
||||||
+ " on the consumer " + NetUtils.getLocalHost()
|
|
||||||
+ " using the dubbo version " + Version.getVersion() + " is below: \n"
|
|
||||||
+ snapshotNode.toString();
|
|
||||||
if (routerSnapshotSwitcher.isEnable()) {
|
|
||||||
routerSnapshotSwitcher.setSnapshot(message);
|
|
||||||
}
|
|
||||||
logger.info(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify router chain of the initial addresses from registry at the first time.
|
|
||||||
* Notify whenever addresses in registry change.
|
|
||||||
*/
|
|
||||||
public void setInvokers(BitList<Invoker<T>> invokers) {
|
|
||||||
this.invokers = (invokers == null ? BitList.emptyList() : invokers);
|
|
||||||
routers.forEach(router -> router.notify(this.invokers));
|
|
||||||
stateRouters.forEach(router -> router.notify(this.invokers));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* for uts only
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public void setHeadStateRouter(StateRouter<T> headStateRouter) {
|
|
||||||
this.headStateRouter = headStateRouter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* for uts only
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public List<StateRouter<T>> getStateRouters() {
|
|
||||||
return stateRouters;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReadWriteLock getLock() {
|
|
||||||
return lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void destroy() {
|
|
||||||
invokers = BitList.emptyList();
|
|
||||||
for (Router router : routers) {
|
|
||||||
try {
|
|
||||||
router.stop();
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(
|
|
||||||
CLUSTER_FAILED_STOP,
|
|
||||||
"route stop failed",
|
|
||||||
"",
|
|
||||||
"Error trying to stop router " + router.getClass(),
|
|
||||||
e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
routers = Collections.emptyList();
|
|
||||||
builtinRouters = Collections.emptyList();
|
|
||||||
|
|
||||||
for (StateRouter<T> router : stateRouters) {
|
|
||||||
try {
|
|
||||||
router.stop();
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(
|
|
||||||
CLUSTER_FAILED_STOP,
|
|
||||||
"StateRouter stop failed",
|
|
||||||
"",
|
|
||||||
"Error trying to stop StateRouter " + router.getClass(),
|
|
||||||
e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stateRouters = Collections.emptyList();
|
|
||||||
headStateRouter = TailStateRouter.getInstance();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -17,14 +17,10 @@
|
||||||
package org.apache.dubbo.rpc.cluster.configurator;
|
package org.apache.dubbo.rpc.cluster.configurator;
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
import org.apache.dubbo.common.constants.CommonConstants;
|
|
||||||
import org.apache.dubbo.common.logger.Logger;
|
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
|
||||||
import org.apache.dubbo.common.utils.NetUtils;
|
import org.apache.dubbo.common.utils.NetUtils;
|
||||||
import org.apache.dubbo.common.utils.StringUtils;
|
import org.apache.dubbo.common.utils.StringUtils;
|
||||||
import org.apache.dubbo.remoting.Constants;
|
import org.apache.dubbo.remoting.Constants;
|
||||||
import org.apache.dubbo.rpc.cluster.Configurator;
|
import org.apache.dubbo.rpc.cluster.Configurator;
|
||||||
import org.apache.dubbo.rpc.cluster.configurator.parser.model.ConditionMatch;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
@ -45,14 +41,12 @@ import static org.apache.dubbo.common.constants.RegistryConstants.COMPATIBLE_CON
|
||||||
import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_KEY;
|
import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_KEY;
|
||||||
import static org.apache.dubbo.rpc.cluster.Constants.CONFIG_VERSION_KEY;
|
import static org.apache.dubbo.rpc.cluster.Constants.CONFIG_VERSION_KEY;
|
||||||
import static org.apache.dubbo.rpc.cluster.Constants.OVERRIDE_PROVIDERS_KEY;
|
import static org.apache.dubbo.rpc.cluster.Constants.OVERRIDE_PROVIDERS_KEY;
|
||||||
import static org.apache.dubbo.rpc.cluster.Constants.RULE_VERSION_V30;
|
|
||||||
import static org.apache.dubbo.rpc.cluster.configurator.parser.model.ConfiguratorConfig.MATCH_CONDITION;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AbstractConfigurator
|
* AbstractConfigurator
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractConfigurator implements Configurator {
|
public abstract class AbstractConfigurator implements Configurator {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(AbstractConfigurator.class);
|
|
||||||
private static final String TILDE = "~";
|
private static final String TILDE = "~";
|
||||||
|
|
||||||
private final URL configuratorUrl;
|
private final URL configuratorUrl;
|
||||||
|
|
@ -72,21 +66,20 @@ public abstract class AbstractConfigurator implements Configurator {
|
||||||
@Override
|
@Override
|
||||||
public URL configure(URL url) {
|
public URL configure(URL url) {
|
||||||
// If override url is not enabled or is invalid, just return.
|
// If override url is not enabled or is invalid, just return.
|
||||||
if (!configuratorUrl.getParameter(ENABLED_KEY, true)
|
if (!configuratorUrl.getParameter(ENABLED_KEY, true) || configuratorUrl.getHost() == null || url == null || url.getHost() == null) {
|
||||||
|| configuratorUrl.getHost() == null
|
|
||||||
|| url == null
|
|
||||||
|| url.getHost() == null) {
|
|
||||||
logger.info("Cannot apply configurator rule, the rule is disabled or is invalid: \n" + configuratorUrl);
|
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* This if branch is created since 2.7.0.
|
||||||
|
*/
|
||||||
String apiVersion = configuratorUrl.getParameter(CONFIG_VERSION_KEY);
|
String apiVersion = configuratorUrl.getParameter(CONFIG_VERSION_KEY);
|
||||||
if (StringUtils.isNotEmpty(apiVersion)) { // v2.7 or above
|
if (StringUtils.isNotEmpty(apiVersion)) {
|
||||||
String currentSide = url.getSide();
|
String currentSide = url.getSide();
|
||||||
String configuratorSide = configuratorUrl.getSide();
|
String configuratorSide = configuratorUrl.getSide();
|
||||||
if (currentSide.equals(configuratorSide) && CONSUMER.equals(configuratorSide)) {
|
if (currentSide.equals(configuratorSide) && CONSUMER.equals(configuratorSide) && 0 == configuratorUrl.getPort()) {
|
||||||
url = configureIfMatch(NetUtils.getLocalHost(), url);
|
url = configureIfMatch(NetUtils.getLocalHost(), url);
|
||||||
} else if (currentSide.equals(configuratorSide) && PROVIDER.equals(configuratorSide)) {
|
} else if (currentSide.equals(configuratorSide) && PROVIDER.equals(configuratorSide) &&
|
||||||
|
url.getPort() == configuratorUrl.getPort()) {
|
||||||
url = configureIfMatch(url.getHost(), url);
|
url = configureIfMatch(url.getHost(), url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -101,9 +94,7 @@ public abstract class AbstractConfigurator implements Configurator {
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
private URL configureDeprecated(URL url) {
|
private URL configureDeprecated(URL url) {
|
||||||
// If override url has port, means it is a provider address. We want to control a specific provider with this
|
// If override url has port, means it is a provider address. We want to control a specific provider with this override url, it may take effect on the specific provider instance or on consumers holding this provider instance.
|
||||||
// override url, it may take effect on the specific provider instance or on consumers holding this provider
|
|
||||||
// instance.
|
|
||||||
if (configuratorUrl.getPort() != 0) {
|
if (configuratorUrl.getPort() != 0) {
|
||||||
if (url.getPort() == configuratorUrl.getPort()) {
|
if (url.getPort() == configuratorUrl.getPort()) {
|
||||||
return configureIfMatch(url.getHost(), url);
|
return configureIfMatch(url.getHost(), url);
|
||||||
|
|
@ -127,120 +118,53 @@ public abstract class AbstractConfigurator implements Configurator {
|
||||||
|
|
||||||
private URL configureIfMatch(String host, URL url) {
|
private URL configureIfMatch(String host, URL url) {
|
||||||
if (ANYHOST_VALUE.equals(configuratorUrl.getHost()) || host.equals(configuratorUrl.getHost())) {
|
if (ANYHOST_VALUE.equals(configuratorUrl.getHost()) || host.equals(configuratorUrl.getHost())) {
|
||||||
if (isV27ConditionMatchOrUnset(url)) {
|
// TODO, to support wildcards
|
||||||
Set<String> conditionKeys = genConditionKeys();
|
String providers = configuratorUrl.getParameter(OVERRIDE_PROVIDERS_KEY);
|
||||||
String apiVersion = configuratorUrl.getParameter(CONFIG_VERSION_KEY);
|
if (StringUtils.isEmpty(providers) || providers.contains(url.getAddress()) || providers.contains(ANYHOST_VALUE)) {
|
||||||
if (apiVersion != null && apiVersion.startsWith(RULE_VERSION_V30)) {
|
String configApplication = configuratorUrl.getApplication(configuratorUrl.getUsername());
|
||||||
ConditionMatch matcher = (ConditionMatch) configuratorUrl.getAttribute(MATCH_CONDITION);
|
String currentApplication = url.getApplication(url.getUsername());
|
||||||
if (matcher != null) {
|
if (configApplication == null || ANY_VALUE.equals(configApplication)
|
||||||
if (matcher.isMatch(host, url)) {
|
|| configApplication.equals(currentApplication)) {
|
||||||
return doConfigure(url, configuratorUrl.removeParameters(conditionKeys));
|
Set<String> conditionKeys = new HashSet<String>();
|
||||||
} else {
|
conditionKeys.add(CATEGORY_KEY);
|
||||||
logger.debug("Cannot apply configurator rule, param mismatch, current params are " + url
|
conditionKeys.add(Constants.CHECK_KEY);
|
||||||
+ ", params in rule is " + matcher);
|
conditionKeys.add(DYNAMIC_KEY);
|
||||||
|
conditionKeys.add(ENABLED_KEY);
|
||||||
|
conditionKeys.add(GROUP_KEY);
|
||||||
|
conditionKeys.add(VERSION_KEY);
|
||||||
|
conditionKeys.add(APPLICATION_KEY);
|
||||||
|
conditionKeys.add(SIDE_KEY);
|
||||||
|
conditionKeys.add(CONFIG_VERSION_KEY);
|
||||||
|
conditionKeys.add(COMPATIBLE_CONFIG_KEY);
|
||||||
|
conditionKeys.add(INTERFACES);
|
||||||
|
for (Map.Entry<String, String> entry : configuratorUrl.getParameters().entrySet()) {
|
||||||
|
String key = entry.getKey();
|
||||||
|
String value = entry.getValue();
|
||||||
|
boolean startWithTilde = startWithTilde(key);
|
||||||
|
if (startWithTilde || APPLICATION_KEY.equals(key) || SIDE_KEY.equals(key)) {
|
||||||
|
if (startWithTilde) {
|
||||||
|
conditionKeys.add(key);
|
||||||
|
}
|
||||||
|
if (value != null && !ANY_VALUE.equals(value)
|
||||||
|
&& !value.equals(url.getParameter(startWithTilde ? key.substring(1) : key))) {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return doConfigure(url, configuratorUrl.removeParameters(conditionKeys));
|
|
||||||
}
|
}
|
||||||
} else if (isDeprecatedConditionMatch(conditionKeys, url)) {
|
|
||||||
return doConfigure(url, configuratorUrl.removeParameters(conditionKeys));
|
return doConfigure(url, configuratorUrl.removeParameters(conditionKeys));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
logger.debug("Cannot apply configurator rule, host mismatch, current host is " + host + ", host in rule is "
|
|
||||||
+ configuratorUrl.getHost());
|
|
||||||
}
|
}
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if v2.7 configurator rule is set and can be matched.
|
|
||||||
*
|
|
||||||
* @param url the configurator rule url
|
|
||||||
* @return true if v2.7 configurator rule is not set or the rule can be matched.
|
|
||||||
*/
|
|
||||||
private boolean isV27ConditionMatchOrUnset(URL url) {
|
|
||||||
String providers = configuratorUrl.getParameter(OVERRIDE_PROVIDERS_KEY);
|
|
||||||
if (StringUtils.isNotEmpty(providers)) {
|
|
||||||
boolean match = false;
|
|
||||||
String[] providerAddresses = providers.split(CommonConstants.COMMA_SEPARATOR);
|
|
||||||
for (String address : providerAddresses) {
|
|
||||||
if (address.equals(url.getAddress())
|
|
||||||
|| address.equals(ANYHOST_VALUE)
|
|
||||||
|| address.equals(ANYHOST_VALUE + CommonConstants.GROUP_CHAR_SEPARATOR + ANY_VALUE)
|
|
||||||
|| address.equals(ANYHOST_VALUE + CommonConstants.GROUP_CHAR_SEPARATOR + url.getPort())
|
|
||||||
|| address.equals(url.getHost())) {
|
|
||||||
match = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!match) {
|
|
||||||
logger.debug("Cannot apply configurator rule, provider address mismatch, current address "
|
|
||||||
+ url.getAddress() + ", address in rule is " + providers);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String configApplication = configuratorUrl.getApplication(configuratorUrl.getUsername());
|
|
||||||
String currentApplication = url.getApplication(url.getUsername());
|
|
||||||
if (configApplication != null
|
|
||||||
&& !ANY_VALUE.equals(configApplication)
|
|
||||||
&& !configApplication.equals(currentApplication)) {
|
|
||||||
logger.debug("Cannot apply configurator rule, application name mismatch, current application is "
|
|
||||||
+ currentApplication + ", application in rule is " + configApplication);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
String configServiceKey = configuratorUrl.getServiceKey();
|
|
||||||
String currentServiceKey = url.getServiceKey();
|
|
||||||
if (!ANY_VALUE.equals(configServiceKey) && !configServiceKey.equals(currentServiceKey)) {
|
|
||||||
logger.debug("Cannot apply configurator rule, service mismatch, current service is " + currentServiceKey
|
|
||||||
+ ", service in rule is " + configServiceKey);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isDeprecatedConditionMatch(Set<String> conditionKeys, URL url) {
|
|
||||||
boolean result = true;
|
|
||||||
for (Map.Entry<String, String> entry : configuratorUrl.getParameters().entrySet()) {
|
|
||||||
String key = entry.getKey();
|
|
||||||
String value = entry.getValue();
|
|
||||||
boolean startWithTilde = startWithTilde(key);
|
|
||||||
if (startWithTilde || APPLICATION_KEY.equals(key) || SIDE_KEY.equals(key)) {
|
|
||||||
if (startWithTilde) {
|
|
||||||
conditionKeys.add(key);
|
|
||||||
}
|
|
||||||
if (value != null
|
|
||||||
&& !ANY_VALUE.equals(value)
|
|
||||||
&& !value.equals(url.getParameter(startWithTilde ? key.substring(1) : key))) {
|
|
||||||
result = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<String> genConditionKeys() {
|
|
||||||
Set<String> conditionKeys = new HashSet<>();
|
|
||||||
conditionKeys.add(CATEGORY_KEY);
|
|
||||||
conditionKeys.add(Constants.CHECK_KEY);
|
|
||||||
conditionKeys.add(DYNAMIC_KEY);
|
|
||||||
conditionKeys.add(ENABLED_KEY);
|
|
||||||
conditionKeys.add(GROUP_KEY);
|
|
||||||
conditionKeys.add(VERSION_KEY);
|
|
||||||
conditionKeys.add(APPLICATION_KEY);
|
|
||||||
conditionKeys.add(SIDE_KEY);
|
|
||||||
conditionKeys.add(CONFIG_VERSION_KEY);
|
|
||||||
conditionKeys.add(COMPATIBLE_CONFIG_KEY);
|
|
||||||
conditionKeys.add(INTERFACES);
|
|
||||||
return conditionKeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean startWithTilde(String key) {
|
private boolean startWithTilde(String key) {
|
||||||
return StringUtils.isNotEmpty(key) && key.startsWith(TILDE);
|
if (StringUtils.isNotEmpty(key) && key.startsWith(TILDE)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract URL doConfigure(URL currentUrl, URL configUrl);
|
protected abstract URL doConfigure(URL currentUrl, URL configUrl);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,4 +32,5 @@ public class AbsentConfigurator extends AbstractConfigurator {
|
||||||
public URL doConfigure(URL currentUrl, URL configUrl) {
|
public URL doConfigure(URL currentUrl, URL configUrl) {
|
||||||
return currentUrl.addParametersIfAbsent(configUrl.getParameters());
|
return currentUrl.addParametersIfAbsent(configUrl.getParameters());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,4 +30,5 @@ public class AbsentConfiguratorFactory implements ConfiguratorFactory {
|
||||||
public Configurator getConfigurator(URL url) {
|
public Configurator getConfigurator(URL url) {
|
||||||
return new AbsentConfigurator(url);
|
return new AbsentConfigurator(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,15 +17,12 @@
|
||||||
package org.apache.dubbo.rpc.cluster.configurator.override;
|
package org.apache.dubbo.rpc.cluster.configurator.override;
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
import org.apache.dubbo.common.logger.Logger;
|
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
|
||||||
import org.apache.dubbo.rpc.cluster.configurator.AbstractConfigurator;
|
import org.apache.dubbo.rpc.cluster.configurator.AbstractConfigurator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OverrideConfigurator
|
* OverrideConfigurator
|
||||||
*/
|
*/
|
||||||
public class OverrideConfigurator extends AbstractConfigurator {
|
public class OverrideConfigurator extends AbstractConfigurator {
|
||||||
public static final Logger logger = LoggerFactory.getLogger(OverrideConfigurator.class);
|
|
||||||
|
|
||||||
public OverrideConfigurator(URL url) {
|
public OverrideConfigurator(URL url) {
|
||||||
super(url);
|
super(url);
|
||||||
|
|
@ -33,7 +30,7 @@ public class OverrideConfigurator extends AbstractConfigurator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URL doConfigure(URL currentUrl, URL configUrl) {
|
public URL doConfigure(URL currentUrl, URL configUrl) {
|
||||||
logger.info("Start overriding url " + currentUrl + " with override url " + configUrl);
|
|
||||||
return currentUrl.addParameters(configUrl.getParameters());
|
return currentUrl.addParameters(configUrl.getParameters());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,4 +30,5 @@ public class OverrideConfiguratorFactory implements ConfiguratorFactory {
|
||||||
public Configurator getConfigurator(URL url) {
|
public Configurator getConfigurator(URL url) {
|
||||||
return new OverrideConfigurator(url);
|
return new OverrideConfigurator(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,20 +23,17 @@ import org.apache.dubbo.common.utils.StringUtils;
|
||||||
import org.apache.dubbo.rpc.cluster.configurator.parser.model.ConfigItem;
|
import org.apache.dubbo.rpc.cluster.configurator.parser.model.ConfigItem;
|
||||||
import org.apache.dubbo.rpc.cluster.configurator.parser.model.ConfiguratorConfig;
|
import org.apache.dubbo.rpc.cluster.configurator.parser.model.ConfiguratorConfig;
|
||||||
|
|
||||||
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
import org.yaml.snakeyaml.constructor.SafeConstructor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.yaml.snakeyaml.LoaderOptions;
|
|
||||||
import org.yaml.snakeyaml.Yaml;
|
|
||||||
import org.yaml.snakeyaml.constructor.SafeConstructor;
|
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
|
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER;
|
|
||||||
import static org.apache.dubbo.common.constants.RegistryConstants.APP_DYNAMIC_CONFIGURATORS_CATEGORY;
|
import static org.apache.dubbo.common.constants.RegistryConstants.APP_DYNAMIC_CONFIGURATORS_CATEGORY;
|
||||||
import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_CONFIGURATORS_CATEGORY;
|
import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_CONFIGURATORS_CATEGORY;
|
||||||
import static org.apache.dubbo.rpc.cluster.Constants.OVERRIDE_PROVIDERS_KEY;
|
import static org.apache.dubbo.rpc.cluster.Constants.OVERRIDE_PROVIDERS_KEY;
|
||||||
import static org.apache.dubbo.rpc.cluster.configurator.parser.model.ConfiguratorConfig.MATCH_CONDITION;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Config parser
|
* Config parser
|
||||||
|
|
@ -62,14 +59,13 @@ public class ConfigParser {
|
||||||
// service scope by default.
|
// service scope by default.
|
||||||
items.forEach(item -> urls.addAll(serviceItemToUrls(item, configuratorConfig)));
|
items.forEach(item -> urls.addAll(serviceItemToUrls(item, configuratorConfig)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return urls;
|
return urls;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<URL> parseJsonArray(String rawConfig) {
|
private static List<URL> parseJsonArray(String rawConfig) {
|
||||||
List<URL> urls = new ArrayList<>();
|
List<URL> urls = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
List<String> list = JsonUtils.toJavaList(rawConfig, String.class);
|
List<String> list = JsonUtils.getJson().toJavaList(rawConfig, String.class);
|
||||||
if (!CollectionUtils.isEmpty(list)) {
|
if (!CollectionUtils.isEmpty(list)) {
|
||||||
list.forEach(u -> urls.add(URL.valueOf(u)));
|
list.forEach(u -> urls.add(URL.valueOf(u)));
|
||||||
}
|
}
|
||||||
|
|
@ -80,7 +76,7 @@ public class ConfigParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ConfiguratorConfig parseObject(String rawConfig) {
|
private static ConfiguratorConfig parseObject(String rawConfig) {
|
||||||
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
|
Yaml yaml = new Yaml(new SafeConstructor());
|
||||||
Map<String, Object> map = yaml.load(rawConfig);
|
Map<String, Object> map = yaml.load(rawConfig);
|
||||||
return ConfiguratorConfig.parseFromMap(map);
|
return ConfiguratorConfig.parseFromMap(map);
|
||||||
}
|
}
|
||||||
|
|
@ -104,15 +100,10 @@ public class ConfigParser {
|
||||||
if (CollectionUtils.isNotEmpty(apps)) {
|
if (CollectionUtils.isNotEmpty(apps)) {
|
||||||
apps.forEach(app -> {
|
apps.forEach(app -> {
|
||||||
StringBuilder tmpUrlBuilder = new StringBuilder(urlBuilder);
|
StringBuilder tmpUrlBuilder = new StringBuilder(urlBuilder);
|
||||||
urls.add(appendMatchCondition(
|
urls.add(URL.valueOf(tmpUrlBuilder.append("&application=").append(app).toString()));
|
||||||
URL.valueOf(tmpUrlBuilder
|
|
||||||
.append("&application=")
|
|
||||||
.append(app)
|
|
||||||
.toString()),
|
|
||||||
item));
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
urls.add(appendMatchCondition(URL.valueOf(urlBuilder.toString()), item));
|
urls.add(URL.valueOf(urlBuilder.toString()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -144,7 +135,7 @@ public class ConfigParser {
|
||||||
tmpUrlBuilder.append("&category=").append(APP_DYNAMIC_CONFIGURATORS_CATEGORY);
|
tmpUrlBuilder.append("&category=").append(APP_DYNAMIC_CONFIGURATORS_CATEGORY);
|
||||||
tmpUrlBuilder.append("&configVersion=").append(config.getConfigVersion());
|
tmpUrlBuilder.append("&configVersion=").append(config.getConfigVersion());
|
||||||
|
|
||||||
urls.add(appendMatchCondition(URL.valueOf(tmpUrlBuilder.toString()), item));
|
urls.add(URL.valueOf(tmpUrlBuilder.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return urls;
|
return urls;
|
||||||
|
|
@ -160,8 +151,8 @@ public class ConfigParser {
|
||||||
}
|
}
|
||||||
Map<String, String> parameters = item.getParameters();
|
Map<String, String> parameters = item.getParameters();
|
||||||
if (CollectionUtils.isEmptyMap(parameters)) {
|
if (CollectionUtils.isEmptyMap(parameters)) {
|
||||||
throw new IllegalStateException("Invalid configurator rule, please specify at least one parameter "
|
throw new IllegalStateException("Invalid configurator rule, please specify at least one parameter " +
|
||||||
+ "you want to change in the rule.");
|
"you want to change in the rule.");
|
||||||
}
|
}
|
||||||
|
|
||||||
parameters.forEach((k, v) -> {
|
parameters.forEach((k, v) -> {
|
||||||
|
|
@ -176,11 +167,6 @@ public class ConfigParser {
|
||||||
sb.append(OVERRIDE_PROVIDERS_KEY);
|
sb.append(OVERRIDE_PROVIDERS_KEY);
|
||||||
sb.append('=');
|
sb.append('=');
|
||||||
sb.append(CollectionUtils.join(item.getProviderAddresses(), ","));
|
sb.append(CollectionUtils.join(item.getProviderAddresses(), ","));
|
||||||
} else if (PROVIDER.equals(item.getSide())) {
|
|
||||||
sb.append('&');
|
|
||||||
sb.append(OVERRIDE_PROVIDERS_KEY);
|
|
||||||
sb.append('=');
|
|
||||||
sb.append(CollectionUtils.join(parseAddresses(item), ","));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
|
|
@ -232,11 +218,4 @@ public class ConfigParser {
|
||||||
}
|
}
|
||||||
return addresses;
|
return addresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static URL appendMatchCondition(URL url, ConfigItem item) {
|
|
||||||
if (item.getMatch() != null) {
|
|
||||||
url = url.putAttribute(MATCH_CONDITION, item.getMatch());
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,111 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
package org.apache.dubbo.rpc.cluster.configurator.parser.model;
|
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.AddressMatch;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.ListStringMatch;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
|
|
||||||
|
|
||||||
public class ConditionMatch {
|
|
||||||
private AddressMatch address;
|
|
||||||
private AddressMatch providerAddress;
|
|
||||||
private ListStringMatch service;
|
|
||||||
private ListStringMatch app;
|
|
||||||
private List<ParamMatch> param;
|
|
||||||
|
|
||||||
public AddressMatch getAddress() {
|
|
||||||
return address;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAddress(AddressMatch address) {
|
|
||||||
this.address = address;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AddressMatch getProviderAddress() {
|
|
||||||
return providerAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setProviderAddress(AddressMatch providerAddress) {
|
|
||||||
this.providerAddress = providerAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ListStringMatch getService() {
|
|
||||||
return service;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setService(ListStringMatch service) {
|
|
||||||
this.service = service;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ListStringMatch getApp() {
|
|
||||||
return app;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setApp(ListStringMatch app) {
|
|
||||||
this.app = app;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ParamMatch> getParam() {
|
|
||||||
return param;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setParam(List<ParamMatch> param) {
|
|
||||||
this.param = param;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMatch(String host, URL url) {
|
|
||||||
if (getAddress() != null && !getAddress().isMatch(host)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getProviderAddress() != null && !getProviderAddress().isMatch(url.getAddress())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getService() != null && !getService().isMatch(url.getServiceKey())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getApp() != null && !getApp().isMatch(url.getParameter(APPLICATION_KEY))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getParam() != null) {
|
|
||||||
for (ParamMatch match : param) {
|
|
||||||
if (!match.isMatch(url)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ConditionMatch{" + "address='"
|
|
||||||
+ address + '\'' + "providerAddress='"
|
|
||||||
+ providerAddress + '\'' + ", service='"
|
|
||||||
+ service + '\'' + ", app='"
|
|
||||||
+ app + '\'' + ", param='"
|
|
||||||
+ param + '\'' + '}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -16,22 +16,14 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.dubbo.rpc.cluster.configurator.parser.model;
|
package org.apache.dubbo.rpc.cluster.configurator.parser.model;
|
||||||
|
|
||||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
|
||||||
import org.apache.dubbo.common.utils.PojoUtils;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_FAILED_RECEIVE_RULE;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class ConfigItem {
|
public class ConfigItem {
|
||||||
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(ConfigItem.class);
|
|
||||||
|
|
||||||
public static final String GENERAL_TYPE = "general";
|
public static final String GENERAL_TYPE = "general";
|
||||||
public static final String WEIGHT_TYPE = "weight";
|
public static final String WEIGHT_TYPE = "weight";
|
||||||
public static final String BALANCING_TYPE = "balancing";
|
public static final String BALANCING_TYPE = "balancing";
|
||||||
|
|
@ -43,7 +35,6 @@ public class ConfigItem {
|
||||||
public static final String SERVICES_KEY = "services";
|
public static final String SERVICES_KEY = "services";
|
||||||
public static final String APPLICATIONS_KEY = "applications";
|
public static final String APPLICATIONS_KEY = "applications";
|
||||||
public static final String PARAMETERS_KEY = "parameters";
|
public static final String PARAMETERS_KEY = "parameters";
|
||||||
public static final String MATCH_KEY = "match";
|
|
||||||
public static final String SIDE_KEY = "side";
|
public static final String SIDE_KEY = "side";
|
||||||
|
|
||||||
private String type;
|
private String type;
|
||||||
|
|
@ -53,7 +44,6 @@ public class ConfigItem {
|
||||||
private List<String> services;
|
private List<String> services;
|
||||||
private List<String> applications;
|
private List<String> applications;
|
||||||
private Map<String, String> parameters;
|
private Map<String, String> parameters;
|
||||||
private ConditionMatch match;
|
|
||||||
private String side;
|
private String side;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
|
@ -68,49 +58,33 @@ public class ConfigItem {
|
||||||
|
|
||||||
Object addresses = map.get(ADDRESSES_KEY);
|
Object addresses = map.get(ADDRESSES_KEY);
|
||||||
if (addresses != null && List.class.isAssignableFrom(addresses.getClass())) {
|
if (addresses != null && List.class.isAssignableFrom(addresses.getClass())) {
|
||||||
configItem.setAddresses(
|
configItem.setAddresses(((List<Object>) addresses).stream()
|
||||||
((List<Object>) addresses).stream().map(String::valueOf).collect(Collectors.toList()));
|
.map(String::valueOf).collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Object providerAddresses = map.get(PROVIDER_ADDRESSES_KEY);
|
Object providerAddresses = map.get(PROVIDER_ADDRESSES_KEY);
|
||||||
if (providerAddresses != null && List.class.isAssignableFrom(providerAddresses.getClass())) {
|
if (providerAddresses != null && List.class.isAssignableFrom(providerAddresses.getClass())) {
|
||||||
configItem.setProviderAddresses(((List<Object>) providerAddresses)
|
configItem.setProviderAddresses(((List<Object>) providerAddresses).stream()
|
||||||
.stream().map(String::valueOf).collect(Collectors.toList()));
|
.map(String::valueOf).collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Object services = map.get(SERVICES_KEY);
|
Object services = map.get(SERVICES_KEY);
|
||||||
if (services != null && List.class.isAssignableFrom(services.getClass())) {
|
if (services != null && List.class.isAssignableFrom(services.getClass())) {
|
||||||
configItem.setServices(
|
configItem.setServices(((List<Object>) services).stream()
|
||||||
((List<Object>) services).stream().map(String::valueOf).collect(Collectors.toList()));
|
.map(String::valueOf).collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Object applications = map.get(APPLICATIONS_KEY);
|
Object applications = map.get(APPLICATIONS_KEY);
|
||||||
if (applications != null && List.class.isAssignableFrom(applications.getClass())) {
|
if (applications != null && List.class.isAssignableFrom(applications.getClass())) {
|
||||||
configItem.setApplications(
|
configItem.setApplications(((List<Object>) applications).stream()
|
||||||
((List<Object>) applications).stream().map(String::valueOf).collect(Collectors.toList()));
|
.map(String::valueOf).collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Object parameters = map.get(PARAMETERS_KEY);
|
Object parameters = map.get(PARAMETERS_KEY);
|
||||||
if (parameters != null && Map.class.isAssignableFrom(parameters.getClass())) {
|
if (parameters != null && Map.class.isAssignableFrom(parameters.getClass())) {
|
||||||
configItem.setParameters(((Map<String, Object>) parameters)
|
configItem.setParameters(((Map<String, Object>) parameters).entrySet()
|
||||||
.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue()
|
.stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().toString())));
|
||||||
.toString())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
Object match = map.get(MATCH_KEY);
|
|
||||||
if (match != null && Map.class.isAssignableFrom(match.getClass())) {
|
|
||||||
configItem.setMatch(PojoUtils.mapToPojo((Map<String, Object>) match, ConditionMatch.class));
|
|
||||||
}
|
|
||||||
} catch (Throwable t) {
|
|
||||||
logger.error(
|
|
||||||
CLUSTER_FAILED_RECEIVE_RULE,
|
|
||||||
" Failed to parse dynamic configuration rule",
|
|
||||||
String.valueOf(map.get(MATCH_KEY)),
|
|
||||||
"Error occurred when parsing rule component.",
|
|
||||||
t);
|
|
||||||
}
|
|
||||||
|
|
||||||
configItem.setSide((String) map.get(SIDE_KEY));
|
configItem.setSide((String) map.get(SIDE_KEY));
|
||||||
return configItem;
|
return configItem;
|
||||||
}
|
}
|
||||||
|
|
@ -178,12 +152,4 @@ public class ConfigItem {
|
||||||
public void setSide(String side) {
|
public void setSide(String side) {
|
||||||
this.side = side;
|
this.side = side;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConditionMatch getMatch() {
|
|
||||||
return match;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMatch(ConditionMatch match) {
|
|
||||||
this.match = match;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import java.util.stream.Collectors;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class ConfiguratorConfig {
|
public class ConfiguratorConfig {
|
||||||
public static final String MATCH_CONDITION = "MATCH_CONDITION";
|
|
||||||
public static final String SCOPE_SERVICE = "service";
|
public static final String SCOPE_SERVICE = "service";
|
||||||
public static final String SCOPE_APPLICATION = "application";
|
public static final String SCOPE_APPLICATION = "application";
|
||||||
public static final String CONFIG_VERSION_KEY = "configVersion";
|
public static final String CONFIG_VERSION_KEY = "configVersion";
|
||||||
|
|
@ -52,8 +51,8 @@ public class ConfiguratorConfig {
|
||||||
|
|
||||||
Object configs = map.get(CONFIGS_KEY);
|
Object configs = map.get(CONFIGS_KEY);
|
||||||
if (configs != null && List.class.isAssignableFrom(configs.getClass())) {
|
if (configs != null && List.class.isAssignableFrom(configs.getClass())) {
|
||||||
configuratorConfig.setConfigs(((List<Map<String, Object>>) configs)
|
configuratorConfig.setConfigs(((List<Map<String, Object>>) configs).stream()
|
||||||
.stream().map(ConfigItem::parseFromMap).collect(Collectors.toList()));
|
.map(ConfigItem::parseFromMap).collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return configuratorConfig;
|
return configuratorConfig;
|
||||||
|
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
package org.apache.dubbo.rpc.cluster.configurator.parser.model;
|
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.mesh.rule.virtualservice.match.StringMatch;
|
|
||||||
|
|
||||||
public class ParamMatch {
|
|
||||||
private String key;
|
|
||||||
private StringMatch value;
|
|
||||||
|
|
||||||
public String getKey() {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKey(String key) {
|
|
||||||
this.key = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringMatch getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(StringMatch value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMatch(URL url) {
|
|
||||||
if (key == null || value == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
String input = url.getParameter(key);
|
|
||||||
return value.isMatch(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ParamMatch{" + "key='" + key + '\'' + ", value='" + value + '\'' + '}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -20,17 +20,12 @@ import org.apache.dubbo.common.URL;
|
||||||
import org.apache.dubbo.common.Version;
|
import org.apache.dubbo.common.Version;
|
||||||
import org.apache.dubbo.common.config.Configuration;
|
import org.apache.dubbo.common.config.Configuration;
|
||||||
import org.apache.dubbo.common.config.ConfigurationUtils;
|
import org.apache.dubbo.common.config.ConfigurationUtils;
|
||||||
import org.apache.dubbo.common.constants.LoggerCodeConstants;
|
import org.apache.dubbo.common.logger.Logger;
|
||||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||||
import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
|
import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
|
||||||
import org.apache.dubbo.common.utils.ConcurrentHashSet;
|
import org.apache.dubbo.common.utils.ConcurrentHashSet;
|
||||||
import org.apache.dubbo.common.utils.LockUtils;
|
|
||||||
import org.apache.dubbo.common.utils.NetUtils;
|
import org.apache.dubbo.common.utils.NetUtils;
|
||||||
import org.apache.dubbo.common.utils.StringUtils;
|
import org.apache.dubbo.common.utils.StringUtils;
|
||||||
import org.apache.dubbo.metrics.event.MetricsEventBus;
|
|
||||||
import org.apache.dubbo.metrics.model.key.MetricsKey;
|
|
||||||
import org.apache.dubbo.metrics.registry.event.RegistryEvent;
|
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
import org.apache.dubbo.rpc.Invocation;
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
import org.apache.dubbo.rpc.Invoker;
|
||||||
import org.apache.dubbo.rpc.RpcContext;
|
import org.apache.dubbo.rpc.RpcContext;
|
||||||
|
|
@ -38,7 +33,6 @@ import org.apache.dubbo.rpc.RpcException;
|
||||||
import org.apache.dubbo.rpc.cluster.Directory;
|
import org.apache.dubbo.rpc.cluster.Directory;
|
||||||
import org.apache.dubbo.rpc.cluster.Router;
|
import org.apache.dubbo.rpc.cluster.Router;
|
||||||
import org.apache.dubbo.rpc.cluster.RouterChain;
|
import org.apache.dubbo.rpc.cluster.RouterChain;
|
||||||
import org.apache.dubbo.rpc.cluster.SingleRouterChain;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
||||||
import org.apache.dubbo.rpc.cluster.support.ClusterUtils;
|
import org.apache.dubbo.rpc.cluster.support.ClusterUtils;
|
||||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||||
|
|
@ -46,7 +40,6 @@ import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
@ -57,9 +50,6 @@ import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
|
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_RECONNECT_TASK_PERIOD;
|
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_RECONNECT_TASK_PERIOD;
|
||||||
|
|
@ -71,7 +61,6 @@ import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.RECONNECT_TASK_PERIOD;
|
import static org.apache.dubbo.common.constants.CommonConstants.RECONNECT_TASK_PERIOD;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.RECONNECT_TASK_TRY_COUNT;
|
import static org.apache.dubbo.common.constants.CommonConstants.RECONNECT_TASK_TRY_COUNT;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.REGISTER_IP_KEY;
|
import static org.apache.dubbo.common.constants.CommonConstants.REGISTER_IP_KEY;
|
||||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_NO_VALID_PROVIDER;
|
|
||||||
import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
|
import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
|
||||||
import static org.apache.dubbo.rpc.cluster.Constants.CONSUMER_URL_KEY;
|
import static org.apache.dubbo.rpc.cluster.Constants.CONSUMER_URL_KEY;
|
||||||
import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
|
import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
|
||||||
|
|
@ -82,7 +71,7 @@ import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
|
||||||
public abstract class AbstractDirectory<T> implements Directory<T> {
|
public abstract class AbstractDirectory<T> implements Directory<T> {
|
||||||
|
|
||||||
// logger
|
// logger
|
||||||
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(AbstractDirectory.class);
|
private static final Logger logger = LoggerFactory.getLogger(AbstractDirectory.class);
|
||||||
|
|
||||||
private final URL url;
|
private final URL url;
|
||||||
|
|
||||||
|
|
@ -125,8 +114,6 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
|
||||||
|
|
||||||
private volatile ScheduledFuture<?> connectivityCheckFuture;
|
private volatile ScheduledFuture<?> connectivityCheckFuture;
|
||||||
|
|
||||||
private final ReentrantLock invokerRefreshLock = new ReentrantLock();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The max count of invokers for each reconnect task select to try to reconnect.
|
* The max count of invokers for each reconnect task select to try to reconnect.
|
||||||
*/
|
*/
|
||||||
|
|
@ -137,8 +124,6 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
|
||||||
*/
|
*/
|
||||||
private final int reconnectTaskPeriod;
|
private final int reconnectTaskPeriod;
|
||||||
|
|
||||||
private ApplicationModel applicationModel;
|
|
||||||
|
|
||||||
public AbstractDirectory(URL url) {
|
public AbstractDirectory(URL url) {
|
||||||
this(url, null, false);
|
this(url, null, false);
|
||||||
}
|
}
|
||||||
|
|
@ -164,21 +149,19 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove some local only parameters
|
// remove some local only parameters
|
||||||
applicationModel = url.getOrDefaultApplicationModel();
|
ApplicationModel applicationModel = url.getOrDefaultApplicationModel();
|
||||||
this.queryMap =
|
this.queryMap = applicationModel.getBeanFactory().getBean(ClusterUtils.class).mergeLocalParams(queryMap);
|
||||||
applicationModel.getBeanFactory().getBean(ClusterUtils.class).mergeLocalParams(queryMap);
|
|
||||||
|
|
||||||
if (consumerUrl == null) {
|
if (consumerUrl == null) {
|
||||||
String host =
|
String host = isNotEmpty(queryMap.get(REGISTER_IP_KEY)) ? queryMap.get(REGISTER_IP_KEY) : this.url.getHost();
|
||||||
isNotEmpty(queryMap.get(REGISTER_IP_KEY)) ? queryMap.get(REGISTER_IP_KEY) : this.url.getHost();
|
|
||||||
String path = isNotEmpty(queryMap.get(PATH_KEY)) ? queryMap.get(PATH_KEY) : queryMap.get(INTERFACE_KEY);
|
String path = isNotEmpty(queryMap.get(PATH_KEY)) ? queryMap.get(PATH_KEY) : queryMap.get(INTERFACE_KEY);
|
||||||
String consumedProtocol = isNotEmpty(queryMap.get(PROTOCOL_KEY)) ? queryMap.get(PROTOCOL_KEY) : CONSUMER;
|
String consumedProtocol = isNotEmpty(queryMap.get(PROTOCOL_KEY)) ? queryMap.get(PROTOCOL_KEY) : CONSUMER;
|
||||||
|
|
||||||
URL consumerUrlFrom = this.url
|
URL consumerUrlFrom = this.url
|
||||||
.setHost(host)
|
.setHost(host)
|
||||||
.setPort(0)
|
.setPort(0)
|
||||||
.setProtocol(consumedProtocol)
|
.setProtocol(consumedProtocol)
|
||||||
.setPath(path);
|
.setPath(path);
|
||||||
if (isUrlFromRegistry) {
|
if (isUrlFromRegistry) {
|
||||||
// reserve parameters if url is already a consumer url
|
// reserve parameters if url is already a consumer url
|
||||||
consumerUrlFrom = consumerUrlFrom.clearParameters();
|
consumerUrlFrom = consumerUrlFrom.clearParameters();
|
||||||
|
|
@ -186,11 +169,8 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
|
||||||
this.consumerUrl = consumerUrlFrom.addParameters(queryMap);
|
this.consumerUrl = consumerUrlFrom.addParameters(queryMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.connectivityExecutor = applicationModel
|
this.connectivityExecutor = applicationModel.getFrameworkModel().getBeanFactory()
|
||||||
.getFrameworkModel()
|
.getBean(FrameworkExecutorRepository.class).getConnectivityScheduledExecutor();
|
||||||
.getBeanFactory()
|
|
||||||
.getBean(FrameworkExecutorRepository.class)
|
|
||||||
.getConnectivityScheduledExecutor();
|
|
||||||
Configuration configuration = ConfigurationUtils.getGlobalConfiguration(url.getOrDefaultModuleModel());
|
Configuration configuration = ConfigurationUtils.getGlobalConfiguration(url.getOrDefaultModuleModel());
|
||||||
this.reconnectTaskTryCount = configuration.getInt(RECONNECT_TASK_TRY_COUNT, DEFAULT_RECONNECT_TASK_TRY_COUNT);
|
this.reconnectTaskTryCount = configuration.getInt(RECONNECT_TASK_TRY_COUNT, DEFAULT_RECONNECT_TASK_TRY_COUNT);
|
||||||
this.reconnectTaskPeriod = configuration.getInt(RECONNECT_TASK_PERIOD, DEFAULT_RECONNECT_TASK_PERIOD);
|
this.reconnectTaskPeriod = configuration.getInt(RECONNECT_TASK_PERIOD, DEFAULT_RECONNECT_TASK_PERIOD);
|
||||||
|
|
@ -200,56 +180,28 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
|
||||||
@Override
|
@Override
|
||||||
public List<Invoker<T>> list(Invocation invocation) throws RpcException {
|
public List<Invoker<T>> list(Invocation invocation) throws RpcException {
|
||||||
if (destroyed) {
|
if (destroyed) {
|
||||||
throw new RpcException(
|
throw new RpcException("Directory of type " + this.getClass().getSimpleName() + " already destroyed for service " + getConsumerUrl().getServiceKey() + " from registry " + getUrl());
|
||||||
"Directory of type " + this.getClass().getSimpleName() + " already destroyed for service "
|
|
||||||
+ getConsumerUrl().getServiceKey() + " from registry " + getUrl());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BitList<Invoker<T>> availableInvokers;
|
BitList<Invoker<T>> availableInvokers;
|
||||||
SingleRouterChain<T> singleChain = null;
|
// use clone to avoid being modified at doList().
|
||||||
try {
|
if (invokersInitialized) {
|
||||||
try {
|
availableInvokers = validInvokers.clone();
|
||||||
if (routerChain != null) {
|
} else {
|
||||||
routerChain.getLock().readLock().lock();
|
availableInvokers = invokers.clone();
|
||||||
}
|
|
||||||
// use clone to avoid being modified at doList().
|
|
||||||
if (invokersInitialized) {
|
|
||||||
availableInvokers = validInvokers.clone();
|
|
||||||
} else {
|
|
||||||
availableInvokers = invokers.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (routerChain != null) {
|
|
||||||
singleChain = routerChain.getSingleChain(getConsumerUrl(), availableInvokers, invocation);
|
|
||||||
singleChain.getLock().readLock().lock();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (routerChain != null) {
|
|
||||||
routerChain.getLock().readLock().unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Invoker<T>> routedResult = doList(singleChain, availableInvokers, invocation);
|
|
||||||
if (routedResult.isEmpty()) {
|
|
||||||
// 2-2 - No provider available.
|
|
||||||
|
|
||||||
logger.warn(
|
|
||||||
CLUSTER_NO_VALID_PROVIDER,
|
|
||||||
"provider server or registry center crashed",
|
|
||||||
"",
|
|
||||||
"No provider available after connectivity filter for the service "
|
|
||||||
+ getConsumerUrl().getServiceKey()
|
|
||||||
+ " All routed invokers' size: " + routedResult.size()
|
|
||||||
+ " from registry " + this
|
|
||||||
+ " on the consumer " + NetUtils.getLocalHost()
|
|
||||||
+ " using the dubbo version " + Version.getVersion() + ".");
|
|
||||||
}
|
|
||||||
return Collections.unmodifiableList(routedResult);
|
|
||||||
} finally {
|
|
||||||
if (singleChain != null) {
|
|
||||||
singleChain.getLock().readLock().unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Invoker<T>> routedResult = doList(availableInvokers, invocation);
|
||||||
|
if (routedResult.isEmpty()) {
|
||||||
|
logger.warn("No provider available after connectivity filter for the service " + getConsumerUrl().getServiceKey()
|
||||||
|
+ " All validInvokers' size: " + validInvokers.size()
|
||||||
|
+ " All routed invokers' size: " + routedResult.size()
|
||||||
|
+ " All invokers' size: " + invokers.size()
|
||||||
|
+ " from registry " + getUrl().getAddress()
|
||||||
|
+ " on the consumer " + NetUtils.getLocalHost()
|
||||||
|
+ " using the dubbo version " + Version.getVersion() + ".");
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableList(routedResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -298,109 +250,70 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInvalidateInvoker(Invoker<T> invoker) {
|
public void addInvalidateInvoker(Invoker<T> invoker) {
|
||||||
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
|
// 1. remove this invoker from validInvokers list, this invoker will not be listed in the next time
|
||||||
// 1. remove this invoker from validInvokers list, this invoker will not be listed in the next time
|
if (removeValidInvoker(invoker)) {
|
||||||
if (removeValidInvoker(invoker)) {
|
// 2. add this invoker to reconnect list
|
||||||
// 2. add this invoker to reconnect list
|
invokersToReconnect.add(invoker);
|
||||||
invokersToReconnect.add(invoker);
|
// 3. try start check connectivity task
|
||||||
// 3. try start check connectivity task
|
checkConnectivity();
|
||||||
checkConnectivity();
|
}
|
||||||
|
|
||||||
logger.info("The invoker " + invoker.getUrl()
|
|
||||||
+ " has been added to invalidate list due to connectivity problem. "
|
|
||||||
+ "Will trying to reconnect to it in the background.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkConnectivity() {
|
public void checkConnectivity() {
|
||||||
// try to submit task, to ensure there is only one task at most for each directory
|
// try to submit task, to ensure there is only one task at most for each directory
|
||||||
if (checkConnectivityPermit.tryAcquire()) {
|
if (checkConnectivityPermit.tryAcquire()) {
|
||||||
this.connectivityCheckFuture = connectivityExecutor.schedule(
|
this.connectivityCheckFuture = connectivityExecutor.schedule(() -> {
|
||||||
() -> {
|
try {
|
||||||
try {
|
if (isDestroyed()) {
|
||||||
if (isDestroyed()) {
|
return;
|
||||||
return;
|
}
|
||||||
|
RpcContext.getServiceContext().setConsumerUrl(getConsumerUrl());
|
||||||
|
List<Invoker<T>> needDeleteList = new ArrayList<>();
|
||||||
|
List<Invoker<T>> invokersToTry = new ArrayList<>();
|
||||||
|
|
||||||
|
// 1. pick invokers from invokersToReconnect
|
||||||
|
// limit max reconnectTaskTryCount, prevent this task hang up all the connectivityExecutor for long time
|
||||||
|
if (invokersToReconnect.size() < reconnectTaskTryCount) {
|
||||||
|
invokersToTry.addAll(invokersToReconnect);
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < reconnectTaskTryCount; i++) {
|
||||||
|
Invoker<T> tInvoker = invokersToReconnect.get(ThreadLocalRandom.current().nextInt(invokersToReconnect.size()));
|
||||||
|
if (!invokersToTry.contains(tInvoker)) {
|
||||||
|
// ignore if is selected, invokersToTry's size is always smaller than reconnectTaskTryCount + 1
|
||||||
|
invokersToTry.add(tInvoker);
|
||||||
}
|
}
|
||||||
RpcContext.getServiceContext().setConsumerUrl(getConsumerUrl());
|
|
||||||
List<Invoker<T>> needDeleteList = new ArrayList<>();
|
|
||||||
List<Invoker<T>> invokersToTry = new ArrayList<>();
|
|
||||||
|
|
||||||
// 1. pick invokers from invokersToReconnect
|
|
||||||
// limit max reconnectTaskTryCount, prevent this task hang up all the connectivityExecutor
|
|
||||||
// for long time
|
|
||||||
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
|
|
||||||
if (invokersToReconnect.size() < reconnectTaskTryCount) {
|
|
||||||
invokersToTry.addAll(invokersToReconnect);
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < reconnectTaskTryCount; i++) {
|
|
||||||
Invoker<T> tInvoker = invokersToReconnect.get(
|
|
||||||
ThreadLocalRandom.current().nextInt(invokersToReconnect.size()));
|
|
||||||
if (!invokersToTry.contains(tInvoker)) {
|
|
||||||
// ignore if is selected, invokersToTry's size is always smaller than
|
|
||||||
// reconnectTaskTryCount + 1
|
|
||||||
invokersToTry.add(tInvoker);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 2. try to check the invoker's status
|
|
||||||
for (Invoker<T> invoker : invokersToTry) {
|
|
||||||
AtomicBoolean invokerExist = new AtomicBoolean(false);
|
|
||||||
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
|
|
||||||
invokerExist.set(invokers.contains(invoker));
|
|
||||||
});
|
|
||||||
// Should not lock here, `invoker.isAvailable` may need some time to check
|
|
||||||
if (invokerExist.get()) {
|
|
||||||
if (invoker.isAvailable()) {
|
|
||||||
needDeleteList.add(invoker);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
needDeleteList.add(invoker);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. recover valid invoker
|
|
||||||
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
|
|
||||||
for (Invoker<T> tInvoker : needDeleteList) {
|
|
||||||
if (invokers.contains(tInvoker)) {
|
|
||||||
addValidInvoker(tInvoker);
|
|
||||||
logger.info("Recover service address: " + tInvoker.getUrl()
|
|
||||||
+ " from invalid list.");
|
|
||||||
} else {
|
|
||||||
logger.info(
|
|
||||||
"The invoker " + tInvoker.getUrl()
|
|
||||||
+ " has been removed from invokers list. Will remove it in reconnect list.");
|
|
||||||
}
|
|
||||||
invokersToReconnect.remove(tInvoker);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (Throwable t) {
|
|
||||||
logger.error(
|
|
||||||
LoggerCodeConstants.INTERNAL_ERROR,
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"Error occurred when check connectivity. ",
|
|
||||||
t);
|
|
||||||
} finally {
|
|
||||||
checkConnectivityPermit.release();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 4. submit new task if it has more to recover
|
// 2. try to check the invoker's status
|
||||||
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
|
for (Invoker<T> invoker : invokersToTry) {
|
||||||
if (!invokersToReconnect.isEmpty()) {
|
if (invokers.contains(invoker)) {
|
||||||
checkConnectivity();
|
if (invoker.isAvailable()) {
|
||||||
|
needDeleteList.add(invoker);
|
||||||
}
|
}
|
||||||
});
|
} else {
|
||||||
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(
|
needDeleteList.add(invoker);
|
||||||
applicationModel, getSummary(), getDirectoryMeta()));
|
}
|
||||||
},
|
}
|
||||||
reconnectTaskPeriod,
|
|
||||||
TimeUnit.MILLISECONDS);
|
// 3. recover valid invoker
|
||||||
|
for (Invoker<T> tInvoker : needDeleteList) {
|
||||||
|
if (invokers.contains(tInvoker)) {
|
||||||
|
addValidInvoker(tInvoker);
|
||||||
|
logger.info("Recover service address: " + tInvoker.getUrl() + " from invalid list.");
|
||||||
|
}
|
||||||
|
invokersToReconnect.remove(tInvoker);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
checkConnectivityPermit.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. submit new task if it has more to recover
|
||||||
|
if (!invokersToReconnect.isEmpty()) {
|
||||||
|
checkConnectivity();
|
||||||
|
}
|
||||||
|
}, reconnectTaskPeriod, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
MetricsEventBus.publish(
|
|
||||||
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -411,20 +324,12 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
|
||||||
* 4. all the invokers disappeared from total invokers should be removed in the disabled invokers list
|
* 4. all the invokers disappeared from total invokers should be removed in the disabled invokers list
|
||||||
*/
|
*/
|
||||||
public void refreshInvoker() {
|
public void refreshInvoker() {
|
||||||
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
|
if (invokersInitialized) {
|
||||||
if (invokersInitialized) {
|
refreshInvokerInternal();
|
||||||
refreshInvokerInternal();
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
MetricsEventBus.publish(
|
|
||||||
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Map<String, String> getDirectoryMeta() {
|
private synchronized void refreshInvokerInternal() {
|
||||||
return Collections.emptyMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshInvokerInternal() {
|
|
||||||
BitList<Invoker<T>> copiedInvokers = invokers.clone();
|
BitList<Invoker<T>> copiedInvokers = invokers.clone();
|
||||||
refreshInvokers(copiedInvokers, invokersToReconnect);
|
refreshInvokers(copiedInvokers, invokersToReconnect);
|
||||||
refreshInvokers(copiedInvokers, disabledInvokers);
|
refreshInvokers(copiedInvokers, disabledInvokers);
|
||||||
|
|
@ -445,49 +350,22 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addDisabledInvoker(Invoker<T> invoker) {
|
public void addDisabledInvoker(Invoker<T> invoker) {
|
||||||
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
|
if (invokers.contains(invoker)) {
|
||||||
if (invokers.contains(invoker)) {
|
disabledInvokers.add(invoker);
|
||||||
disabledInvokers.add(invoker);
|
removeValidInvoker(invoker);
|
||||||
removeValidInvoker(invoker);
|
logger.info("Disable service address: " + invoker.getUrl() + ".");
|
||||||
logger.info("Disable service address: " + invoker.getUrl() + ".");
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
MetricsEventBus.publish(
|
|
||||||
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void recoverDisabledInvoker(Invoker<T> invoker) {
|
public void recoverDisabledInvoker(Invoker<T> invoker) {
|
||||||
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
|
if (disabledInvokers.remove(invoker)) {
|
||||||
if (disabledInvokers.remove(invoker)) {
|
try {
|
||||||
try {
|
addValidInvoker(invoker);
|
||||||
addValidInvoker(invoker);
|
logger.info("Recover service address: " + invoker.getUrl() + " from disabled list.");
|
||||||
logger.info("Recover service address: " + invoker.getUrl() + " from disabled list.");
|
} catch (Throwable ignore) {
|
||||||
} catch (Throwable ignore) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
MetricsEventBus.publish(
|
|
||||||
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void refreshRouter(BitList<Invoker<T>> newlyInvokers, Runnable switchAction) {
|
|
||||||
try {
|
|
||||||
routerChain.setInvokers(newlyInvokers.clone(), switchAction);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
logger.error(
|
|
||||||
LoggerCodeConstants.INTERNAL_ERROR,
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"Error occurred when refreshing router chain. " + "The addresses from notification: "
|
|
||||||
+ newlyInvokers.stream()
|
|
||||||
.map(Invoker::getUrl)
|
|
||||||
.map(URL::getAddress)
|
|
||||||
.collect(Collectors.joining(", ")),
|
|
||||||
t);
|
|
||||||
|
|
||||||
throw t;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -526,98 +404,30 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setInvokers(BitList<Invoker<T>> invokers) {
|
protected void setInvokers(BitList<Invoker<T>> invokers) {
|
||||||
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
|
this.invokers = invokers;
|
||||||
this.invokers = invokers;
|
refreshInvokerInternal();
|
||||||
refreshInvokerInternal();
|
this.invokersInitialized = true;
|
||||||
this.invokersInitialized = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
MetricsEventBus.publish(
|
|
||||||
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void destroyInvokers() {
|
protected void destroyInvokers() {
|
||||||
// set empty instead of clearing to support concurrent access.
|
// set empty instead of clearing to support concurrent access.
|
||||||
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
|
this.invokers = BitList.emptyList();
|
||||||
this.invokers = BitList.emptyList();
|
this.validInvokers = BitList.emptyList();
|
||||||
this.validInvokers = BitList.emptyList();
|
this.invokersInitialized = false;
|
||||||
this.invokersInitialized = false;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean addValidInvoker(Invoker<T> invoker) {
|
private boolean addValidInvoker(Invoker<T> invoker) {
|
||||||
AtomicBoolean result = new AtomicBoolean(false);
|
synchronized (this.validInvokers) {
|
||||||
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
|
return this.validInvokers.add(invoker);
|
||||||
result.set(this.validInvokers.add(invoker));
|
}
|
||||||
});
|
|
||||||
MetricsEventBus.publish(
|
|
||||||
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
|
|
||||||
return result.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean removeValidInvoker(Invoker<T> invoker) {
|
private boolean removeValidInvoker(Invoker<T> invoker) {
|
||||||
AtomicBoolean result = new AtomicBoolean(false);
|
synchronized (this.validInvokers) {
|
||||||
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
|
return this.validInvokers.remove(invoker);
|
||||||
result.set(this.validInvokers.remove(invoker));
|
|
||||||
});
|
|
||||||
MetricsEventBus.publish(
|
|
||||||
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
|
|
||||||
return result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract List<Invoker<T>> doList(
|
|
||||||
SingleRouterChain<T> singleRouterChain, BitList<Invoker<T>> invokers, Invocation invocation)
|
|
||||||
throws RpcException;
|
|
||||||
|
|
||||||
protected String joinValidInvokerAddresses() {
|
|
||||||
BitList<Invoker<T>> validInvokers = getValidInvokers().clone();
|
|
||||||
if (validInvokers.isEmpty()) {
|
|
||||||
return "empty";
|
|
||||||
}
|
}
|
||||||
return validInvokers.stream()
|
|
||||||
.limit(5)
|
|
||||||
.map(Invoker::getUrl)
|
|
||||||
.map(URL::getAddress)
|
|
||||||
.collect(Collectors.joining(","));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<MetricsKey, Map<String, Integer>> getSummary() {
|
protected abstract List<Invoker<T>> doList(BitList<Invoker<T>> invokers, Invocation invocation) throws RpcException;
|
||||||
Map<MetricsKey, Map<String, Integer>> summaryMap = new HashMap<>();
|
|
||||||
|
|
||||||
summaryMap.put(MetricsKey.DIRECTORY_METRIC_NUM_VALID, groupByServiceKey(getValidInvokers()));
|
|
||||||
summaryMap.put(MetricsKey.DIRECTORY_METRIC_NUM_DISABLE, groupByServiceKey(getDisabledInvokers()));
|
|
||||||
summaryMap.put(MetricsKey.DIRECTORY_METRIC_NUM_TO_RECONNECT, groupByServiceKey(getInvokersToReconnect()));
|
|
||||||
summaryMap.put(MetricsKey.DIRECTORY_METRIC_NUM_ALL, groupByServiceKey(getInvokers()));
|
|
||||||
return summaryMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, Integer> groupByServiceKey(Collection<Invoker<T>> invokers) {
|
|
||||||
return Collections.singletonMap(getConsumerUrl().getServiceKey(), invokers.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Directory(" + "invokers: "
|
|
||||||
+ invokers.size() + "["
|
|
||||||
+ invokers.stream()
|
|
||||||
.map(Invoker::getUrl)
|
|
||||||
.map(URL::getAddress)
|
|
||||||
.limit(3)
|
|
||||||
.collect(Collectors.joining(", "))
|
|
||||||
+ "]" + ", validInvokers: "
|
|
||||||
+ validInvokers.size() + "["
|
|
||||||
+ validInvokers.stream()
|
|
||||||
.map(Invoker::getUrl)
|
|
||||||
.map(URL::getAddress)
|
|
||||||
.limit(3)
|
|
||||||
.collect(Collectors.joining(", "))
|
|
||||||
+ "]" + ", invokersToReconnect: "
|
|
||||||
+ invokersToReconnect.size() + "["
|
|
||||||
+ invokersToReconnect.stream()
|
|
||||||
.map(Invoker::getUrl)
|
|
||||||
.map(URL::getAddress)
|
|
||||||
.limit(3)
|
|
||||||
.collect(Collectors.joining(", "))
|
|
||||||
+ "]" + ')';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,30 +17,22 @@
|
||||||
package org.apache.dubbo.rpc.cluster.directory;
|
package org.apache.dubbo.rpc.cluster.directory;
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
import org.apache.dubbo.common.logger.Logger;
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
import org.apache.dubbo.rpc.Invocation;
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
import org.apache.dubbo.rpc.Invoker;
|
||||||
import org.apache.dubbo.rpc.RpcException;
|
import org.apache.dubbo.rpc.RpcException;
|
||||||
import org.apache.dubbo.rpc.cluster.RouterChain;
|
import org.apache.dubbo.rpc.cluster.RouterChain;
|
||||||
import org.apache.dubbo.rpc.cluster.SingleRouterChain;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_FAILED_SITE_SELECTION;
|
|
||||||
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTER_MODE_KEY;
|
|
||||||
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_KEY;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* StaticDirectory
|
* StaticDirectory
|
||||||
*/
|
*/
|
||||||
public class StaticDirectory<T> extends AbstractDirectory<T> {
|
public class StaticDirectory<T> extends AbstractDirectory<T> {
|
||||||
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(StaticDirectory.class);
|
private static final Logger logger = LoggerFactory.getLogger(StaticDirectory.class);
|
||||||
private final Class<T> interfaceClass;
|
|
||||||
|
|
||||||
public StaticDirectory(List<Invoker<T>> invokers) {
|
public StaticDirectory(List<Invoker<T>> invokers) {
|
||||||
this(null, invokers, null);
|
this(null, invokers, null);
|
||||||
|
|
@ -55,22 +47,16 @@ public class StaticDirectory<T> extends AbstractDirectory<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public StaticDirectory(URL url, List<Invoker<T>> invokers, RouterChain<T> routerChain) {
|
public StaticDirectory(URL url, List<Invoker<T>> invokers, RouterChain<T> routerChain) {
|
||||||
super(
|
super(url == null && CollectionUtils.isNotEmpty(invokers) ? invokers.get(0).getUrl() : url, routerChain, false);
|
||||||
url == null && CollectionUtils.isNotEmpty(invokers)
|
|
||||||
? invokers.get(0).getUrl()
|
|
||||||
: url,
|
|
||||||
routerChain,
|
|
||||||
false);
|
|
||||||
if (CollectionUtils.isEmpty(invokers)) {
|
if (CollectionUtils.isEmpty(invokers)) {
|
||||||
throw new IllegalArgumentException("invokers == null");
|
throw new IllegalArgumentException("invokers == null");
|
||||||
}
|
}
|
||||||
this.setInvokers(new BitList<>(invokers));
|
this.setInvokers(new BitList<>(invokers));
|
||||||
this.interfaceClass = invokers.get(0).getInterface();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<T> getInterface() {
|
public Class<T> getInterface() {
|
||||||
return interfaceClass;
|
return getInvokers().get(0).getInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -86,8 +72,6 @@ public class StaticDirectory<T> extends AbstractDirectory<T> {
|
||||||
for (Invoker<T> invoker : getValidInvokers()) {
|
for (Invoker<T> invoker : getValidInvokers()) {
|
||||||
if (invoker.isAvailable()) {
|
if (invoker.isAvailable()) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
|
||||||
addInvalidateInvoker(invoker);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -106,45 +90,29 @@ public class StaticDirectory<T> extends AbstractDirectory<T> {
|
||||||
|
|
||||||
public void buildRouterChain() {
|
public void buildRouterChain() {
|
||||||
RouterChain<T> routerChain = RouterChain.buildChain(getInterface(), getUrl());
|
RouterChain<T> routerChain = RouterChain.buildChain(getInterface(), getUrl());
|
||||||
routerChain.setInvokers(getInvokers(), () -> {});
|
routerChain.setInvokers(getInvokers());
|
||||||
this.setRouterChain(routerChain);
|
this.setRouterChain(routerChain);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notify(List<Invoker<T>> invokers) {
|
public void notify(List<Invoker<T>> invokers) {
|
||||||
BitList<Invoker<T>> bitList = new BitList<>(invokers);
|
this.setInvokers(new BitList<>(invokers));
|
||||||
if (routerChain != null) {
|
if (routerChain != null) {
|
||||||
refreshRouter(bitList.clone(), () -> this.setInvokers(bitList));
|
routerChain.setInvokers(this.getInvokers());
|
||||||
} else {
|
|
||||||
this.setInvokers(bitList);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<Invoker<T>> doList(
|
protected List<Invoker<T>> doList(BitList<Invoker<T>> invokers, Invocation invocation) throws RpcException {
|
||||||
SingleRouterChain<T> singleRouterChain, BitList<Invoker<T>> invokers, Invocation invocation)
|
if (routerChain != null) {
|
||||||
throws RpcException {
|
|
||||||
if (singleRouterChain != null) {
|
|
||||||
try {
|
try {
|
||||||
List<Invoker<T>> finalInvokers = singleRouterChain.route(getConsumerUrl(), invokers, invocation);
|
List<Invoker<T>> finalInvokers = routerChain.route(getConsumerUrl(), invokers, invocation);
|
||||||
return finalInvokers == null ? BitList.emptyList() : finalInvokers;
|
return finalInvokers == null ? BitList.emptyList() : finalInvokers;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
logger.error(
|
logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t);
|
||||||
CLUSTER_FAILED_SITE_SELECTION,
|
|
||||||
"Failed to execute router",
|
|
||||||
"",
|
|
||||||
"Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(),
|
|
||||||
t);
|
|
||||||
return BitList.emptyList();
|
return BitList.emptyList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return invokers;
|
return invokers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Map<String, String> getDirectoryMeta() {
|
|
||||||
Map<String, String> metas = new HashMap<>();
|
|
||||||
metas.put(REGISTRY_KEY, "static");
|
|
||||||
metas.put(REGISTER_MODE_KEY, "static");
|
|
||||||
return metas;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,4 +21,5 @@ import org.apache.dubbo.common.extension.SPI;
|
||||||
import org.apache.dubbo.rpc.BaseFilter;
|
import org.apache.dubbo.rpc.BaseFilter;
|
||||||
|
|
||||||
@SPI(scope = ExtensionScope.MODULE)
|
@SPI(scope = ExtensionScope.MODULE)
|
||||||
public interface ClusterFilter extends BaseFilter {}
|
public interface ClusterFilter extends BaseFilter {
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ package org.apache.dubbo.rpc.cluster.filter;
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
import org.apache.dubbo.common.extension.Activate;
|
import org.apache.dubbo.common.extension.Activate;
|
||||||
import org.apache.dubbo.common.extension.ExtensionDirector;
|
import org.apache.dubbo.common.extension.ExtensionDirector;
|
||||||
import org.apache.dubbo.common.extension.support.ActivateComparator;
|
import org.apache.dubbo.common.extension.support.MultiInstanceActivateComparator;
|
||||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||||
import org.apache.dubbo.rpc.Filter;
|
import org.apache.dubbo.rpc.Filter;
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
import org.apache.dubbo.rpc.Invoker;
|
||||||
|
|
@ -47,14 +47,12 @@ public class DefaultFilterChainBuilder implements FilterChainBuilder {
|
||||||
List<ModuleModel> moduleModels = getModuleModelsFromUrl(url);
|
List<ModuleModel> moduleModels = getModuleModelsFromUrl(url);
|
||||||
List<Filter> filters;
|
List<Filter> filters;
|
||||||
if (moduleModels != null && moduleModels.size() == 1) {
|
if (moduleModels != null && moduleModels.size() == 1) {
|
||||||
filters = ScopeModelUtil.getExtensionLoader(Filter.class, moduleModels.get(0))
|
filters = ScopeModelUtil.getExtensionLoader(Filter.class, moduleModels.get(0)).getActivateExtension(url, key, group);
|
||||||
.getActivateExtension(url, key, group);
|
|
||||||
} else if (moduleModels != null && moduleModels.size() > 1) {
|
} else if (moduleModels != null && moduleModels.size() > 1) {
|
||||||
filters = new ArrayList<>();
|
filters = new ArrayList<>();
|
||||||
List<ExtensionDirector> directors = new ArrayList<>();
|
List<ExtensionDirector> directors = new ArrayList<>();
|
||||||
for (ModuleModel moduleModel : moduleModels) {
|
for (ModuleModel moduleModel : moduleModels) {
|
||||||
List<Filter> tempFilters = ScopeModelUtil.getExtensionLoader(Filter.class, moduleModel)
|
List<Filter> tempFilters = ScopeModelUtil.getExtensionLoader(Filter.class, moduleModel).getActivateExtension(url, key, group);
|
||||||
.getActivateExtension(url, key, group);
|
|
||||||
filters.addAll(tempFilters);
|
filters.addAll(tempFilters);
|
||||||
directors.add(moduleModel.getExtensionDirector());
|
directors.add(moduleModel.getExtensionDirector());
|
||||||
}
|
}
|
||||||
|
|
@ -64,6 +62,7 @@ public class DefaultFilterChainBuilder implements FilterChainBuilder {
|
||||||
filters = ScopeModelUtil.getExtensionLoader(Filter.class, null).getActivateExtension(url, key, group);
|
filters = ScopeModelUtil.getExtensionLoader(Filter.class, null).getActivateExtension(url, key, group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!CollectionUtils.isEmpty(filters)) {
|
if (!CollectionUtils.isEmpty(filters)) {
|
||||||
for (int i = filters.size() - 1; i >= 0; i--) {
|
for (int i = filters.size() - 1; i >= 0; i--) {
|
||||||
final Filter filter = filters.get(i);
|
final Filter filter = filters.get(i);
|
||||||
|
|
@ -80,29 +79,25 @@ public class DefaultFilterChainBuilder implements FilterChainBuilder {
|
||||||
* build consumer cluster filter chain
|
* build consumer cluster filter chain
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public <T> ClusterInvoker<T> buildClusterInvokerChain(
|
public <T> ClusterInvoker<T> buildClusterInvokerChain(final ClusterInvoker<T> originalInvoker, String key, String group) {
|
||||||
final ClusterInvoker<T> originalInvoker, String key, String group) {
|
|
||||||
ClusterInvoker<T> last = originalInvoker;
|
ClusterInvoker<T> last = originalInvoker;
|
||||||
URL url = originalInvoker.getUrl();
|
URL url = originalInvoker.getUrl();
|
||||||
List<ModuleModel> moduleModels = getModuleModelsFromUrl(url);
|
List<ModuleModel> moduleModels = getModuleModelsFromUrl(url);
|
||||||
List<ClusterFilter> filters;
|
List<ClusterFilter> filters;
|
||||||
if (moduleModels != null && moduleModels.size() == 1) {
|
if (moduleModels != null && moduleModels.size() == 1) {
|
||||||
filters = ScopeModelUtil.getExtensionLoader(ClusterFilter.class, moduleModels.get(0))
|
filters = ScopeModelUtil.getExtensionLoader(ClusterFilter.class, moduleModels.get(0)).getActivateExtension(url, key, group);
|
||||||
.getActivateExtension(url, key, group);
|
|
||||||
} else if (moduleModels != null && moduleModels.size() > 1) {
|
} else if (moduleModels != null && moduleModels.size() > 1) {
|
||||||
filters = new ArrayList<>();
|
filters = new ArrayList<>();
|
||||||
List<ExtensionDirector> directors = new ArrayList<>();
|
List<ExtensionDirector> directors = new ArrayList<>();
|
||||||
for (ModuleModel moduleModel : moduleModels) {
|
for (ModuleModel moduleModel : moduleModels) {
|
||||||
List<ClusterFilter> tempFilters = ScopeModelUtil.getExtensionLoader(ClusterFilter.class, moduleModel)
|
List<ClusterFilter> tempFilters = ScopeModelUtil.getExtensionLoader(ClusterFilter.class, moduleModel).getActivateExtension(url, key, group);
|
||||||
.getActivateExtension(url, key, group);
|
|
||||||
filters.addAll(tempFilters);
|
filters.addAll(tempFilters);
|
||||||
directors.add(moduleModel.getExtensionDirector());
|
directors.add(moduleModel.getExtensionDirector());
|
||||||
}
|
}
|
||||||
filters = sortingAndDeduplication(filters, directors);
|
filters = sortingAndDeduplication(filters, directors);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
filters =
|
filters = ScopeModelUtil.getExtensionLoader(ClusterFilter.class, null).getActivateExtension(url, key, group);
|
||||||
ScopeModelUtil.getExtensionLoader(ClusterFilter.class, null).getActivateExtension(url, key, group);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CollectionUtils.isEmpty(filters)) {
|
if (!CollectionUtils.isEmpty(filters)) {
|
||||||
|
|
@ -118,7 +113,7 @@ public class DefaultFilterChainBuilder implements FilterChainBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> List<T> sortingAndDeduplication(List<T> filters, List<ExtensionDirector> directors) {
|
private <T> List<T> sortingAndDeduplication(List<T> filters, List<ExtensionDirector> directors) {
|
||||||
Map<Class<?>, T> filtersSet = new TreeMap<>(new ActivateComparator(directors));
|
Map<Class<?>, T> filtersSet = new TreeMap<>(new MultiInstanceActivateComparator(directors));
|
||||||
for (T filter : filters) {
|
for (T filter : filters) {
|
||||||
filtersSet.putIfAbsent(filter.getClass(), filter);
|
filtersSet.putIfAbsent(filter.getClass(), filter);
|
||||||
}
|
}
|
||||||
|
|
@ -146,4 +141,5 @@ public class DefaultFilterChainBuilder implements FilterChainBuilder {
|
||||||
}
|
}
|
||||||
return moduleModels;
|
return moduleModels;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,8 @@ package org.apache.dubbo.rpc.cluster.filter;
|
||||||
import org.apache.dubbo.common.Experimental;
|
import org.apache.dubbo.common.Experimental;
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
import org.apache.dubbo.common.extension.SPI;
|
import org.apache.dubbo.common.extension.SPI;
|
||||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
import org.apache.dubbo.common.logger.Logger;
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||||
import org.apache.dubbo.rpc.AsyncRpcResult;
|
|
||||||
import org.apache.dubbo.rpc.BaseFilter;
|
import org.apache.dubbo.rpc.BaseFilter;
|
||||||
import org.apache.dubbo.rpc.Filter;
|
import org.apache.dubbo.rpc.Filter;
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
import org.apache.dubbo.rpc.Invocation;
|
||||||
|
|
@ -36,8 +35,6 @@ import org.apache.dubbo.rpc.cluster.Directory;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_EXECUTE_FILTER_EXCEPTION;
|
|
||||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_ERROR;
|
|
||||||
import static org.apache.dubbo.common.extension.ExtensionScope.APPLICATION;
|
import static org.apache.dubbo.common.extension.ExtensionScope.APPLICATION;
|
||||||
|
|
||||||
@SPI(value = "default", scope = APPLICATION)
|
@SPI(value = "default", scope = APPLICATION)
|
||||||
|
|
@ -92,8 +89,7 @@ public interface FilterChainBuilder {
|
||||||
public Result invoke(Invocation invocation) throws RpcException {
|
public Result invoke(Invocation invocation) throws RpcException {
|
||||||
Result asyncResult;
|
Result asyncResult;
|
||||||
try {
|
try {
|
||||||
InvocationProfilerUtils.enterDetailProfiler(
|
InvocationProfilerUtils.enterDetailProfiler(invocation, () -> "Filter " + filter.getClass().getName() + " invoke.");
|
||||||
invocation, () -> "Filter " + filter.getClass().getName() + " invoke.");
|
|
||||||
asyncResult = filter.invoke(nextNode, invocation);
|
asyncResult = filter.invoke(nextNode, invocation);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
InvocationProfilerUtils.releaseDetailProfiler(invocation);
|
InvocationProfilerUtils.releaseDetailProfiler(invocation);
|
||||||
|
|
@ -160,11 +156,12 @@ public interface FilterChainBuilder {
|
||||||
* @param <TYPE>
|
* @param <TYPE>
|
||||||
*/
|
*/
|
||||||
class ClusterFilterChainNode<T, TYPE extends ClusterInvoker<T>, FILTER extends BaseFilter>
|
class ClusterFilterChainNode<T, TYPE extends ClusterInvoker<T>, FILTER extends BaseFilter>
|
||||||
extends FilterChainNode<T, TYPE, FILTER> implements ClusterInvoker<T> {
|
extends FilterChainNode<T, TYPE, FILTER> implements ClusterInvoker<T> {
|
||||||
public ClusterFilterChainNode(TYPE originalInvoker, Invoker<T> nextNode, FILTER filter) {
|
public ClusterFilterChainNode(TYPE originalInvoker, Invoker<T> nextNode, FILTER filter) {
|
||||||
super(originalInvoker, nextNode, filter);
|
super(originalInvoker, nextNode, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URL getRegistryUrl() {
|
public URL getRegistryUrl() {
|
||||||
return getOriginalInvoker().getRegistryUrl();
|
return getOriginalInvoker().getRegistryUrl();
|
||||||
|
|
@ -182,8 +179,7 @@ public interface FilterChainBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
class CallbackRegistrationInvoker<T, FILTER extends BaseFilter> implements Invoker<T> {
|
class CallbackRegistrationInvoker<T, FILTER extends BaseFilter> implements Invoker<T> {
|
||||||
private static final ErrorTypeAwareLogger LOGGER =
|
static final Logger LOGGER = LoggerFactory.getLogger(CallbackRegistrationInvoker.class);
|
||||||
LoggerFactory.getErrorTypeAwareLogger(CallbackRegistrationInvoker.class);
|
|
||||||
final Invoker<T> filterInvoker;
|
final Invoker<T> filterInvoker;
|
||||||
final List<FILTER> filters;
|
final List<FILTER> filters;
|
||||||
|
|
||||||
|
|
@ -224,20 +220,9 @@ public interface FilterChainBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (RuntimeException runtimeException) {
|
} catch (RuntimeException runtimeException) {
|
||||||
LOGGER.error(
|
LOGGER.error(String.format("Exception occurred while executing the %s filter named %s.", i, filter.getClass().getSimpleName()));
|
||||||
CLUSTER_EXECUTE_FILTER_EXCEPTION,
|
|
||||||
"the custom filter is abnormal",
|
|
||||||
"",
|
|
||||||
String.format(
|
|
||||||
"Exception occurred while executing the %s filter named %s.",
|
|
||||||
i, filter.getClass().getSimpleName()));
|
|
||||||
if (LOGGER.isDebugEnabled()) {
|
if (LOGGER.isDebugEnabled()) {
|
||||||
LOGGER.debug(String.format(
|
LOGGER.debug(String.format("Whole filter list is: %s", filters.stream().map(tmpFilter -> tmpFilter.getClass().getSimpleName()).collect(Collectors.toList())));
|
||||||
"Whole filter list is: %s",
|
|
||||||
filters.stream()
|
|
||||||
.map(tmpFilter ->
|
|
||||||
tmpFilter.getClass().getSimpleName())
|
|
||||||
.collect(Collectors.toList())));
|
|
||||||
}
|
}
|
||||||
filterRuntimeException = runtimeException;
|
filterRuntimeException = runtimeException;
|
||||||
t = runtimeException;
|
t = runtimeException;
|
||||||
|
|
@ -251,10 +236,6 @@ public interface FilterChainBuilder {
|
||||||
return asyncResult;
|
return asyncResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Invoker<T> getFilterInvoker() {
|
|
||||||
return filterInvoker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<T> getInterface() {
|
public Class<T> getInterface() {
|
||||||
return filterInvoker.getInterface();
|
return filterInvoker.getInterface();
|
||||||
|
|
@ -276,12 +257,11 @@ public interface FilterChainBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClusterCallbackRegistrationInvoker<T, FILTER extends BaseFilter>
|
class ClusterCallbackRegistrationInvoker<T, FILTER extends BaseFilter> extends CallbackRegistrationInvoker<T, FILTER>
|
||||||
extends CallbackRegistrationInvoker<T, FILTER> implements ClusterInvoker<T> {
|
implements ClusterInvoker<T> {
|
||||||
private ClusterInvoker<T> originalInvoker;
|
private ClusterInvoker<T> originalInvoker;
|
||||||
|
|
||||||
public ClusterCallbackRegistrationInvoker(
|
public ClusterCallbackRegistrationInvoker(ClusterInvoker<T> originalInvoker, Invoker<T> filterInvoker, List<FILTER> filters) {
|
||||||
ClusterInvoker<T> originalInvoker, Invoker<T> filterInvoker, List<FILTER> filters) {
|
|
||||||
super(filterInvoker, filters);
|
super(filterInvoker, filters);
|
||||||
this.originalInvoker = originalInvoker;
|
this.originalInvoker = originalInvoker;
|
||||||
}
|
}
|
||||||
|
|
@ -306,11 +286,9 @@ public interface FilterChainBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Experimental(
|
|
||||||
"Works for the same purpose as FilterChainNode, replace FilterChainNode with this one when proved stable enough")
|
@Experimental("Works for the same purpose as FilterChainNode, replace FilterChainNode with this one when proved stable enough")
|
||||||
class CopyOfFilterChainNode<T, TYPE extends Invoker<T>, FILTER extends BaseFilter> implements Invoker<T> {
|
class CopyOfFilterChainNode<T, TYPE extends Invoker<T>, FILTER extends BaseFilter> implements Invoker<T> {
|
||||||
private static final ErrorTypeAwareLogger LOGGER =
|
|
||||||
LoggerFactory.getErrorTypeAwareLogger(CopyOfFilterChainNode.class);
|
|
||||||
TYPE originalInvoker;
|
TYPE originalInvoker;
|
||||||
Invoker<T> nextNode;
|
Invoker<T> nextNode;
|
||||||
FILTER filter;
|
FILTER filter;
|
||||||
|
|
@ -344,17 +322,8 @@ public interface FilterChainBuilder {
|
||||||
public Result invoke(Invocation invocation) throws RpcException {
|
public Result invoke(Invocation invocation) throws RpcException {
|
||||||
Result asyncResult;
|
Result asyncResult;
|
||||||
try {
|
try {
|
||||||
InvocationProfilerUtils.enterDetailProfiler(
|
InvocationProfilerUtils.enterDetailProfiler(invocation, () -> "Filter " + filter.getClass().getName() + " invoke.");
|
||||||
invocation, () -> "Filter " + filter.getClass().getName() + " invoke.");
|
|
||||||
asyncResult = filter.invoke(nextNode, invocation);
|
asyncResult = filter.invoke(nextNode, invocation);
|
||||||
if (!(asyncResult instanceof AsyncRpcResult)) {
|
|
||||||
String msg =
|
|
||||||
"The result of filter invocation must be AsyncRpcResult. (If you want to recreate a result, please use AsyncRpcResult.newDefaultAsyncResult.) "
|
|
||||||
+ "Filter class: " + filter.getClass().getName() + ". Result class: "
|
|
||||||
+ asyncResult.getClass().getName() + ".";
|
|
||||||
LOGGER.error(INTERNAL_ERROR, "", "", msg);
|
|
||||||
throw new RpcException(msg);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
InvocationProfilerUtils.releaseDetailProfiler(invocation);
|
InvocationProfilerUtils.releaseDetailProfiler(invocation);
|
||||||
if (filter instanceof ListenableFilter) {
|
if (filter instanceof ListenableFilter) {
|
||||||
|
|
@ -389,14 +358,14 @@ public interface FilterChainBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Experimental(
|
@Experimental("Works for the same purpose as ClusterFilterChainNode, replace ClusterFilterChainNode with this one when proved stable enough")
|
||||||
"Works for the same purpose as ClusterFilterChainNode, replace ClusterFilterChainNode with this one when proved stable enough")
|
|
||||||
class CopyOfClusterFilterChainNode<T, TYPE extends ClusterInvoker<T>, FILTER extends BaseFilter>
|
class CopyOfClusterFilterChainNode<T, TYPE extends ClusterInvoker<T>, FILTER extends BaseFilter>
|
||||||
extends CopyOfFilterChainNode<T, TYPE, FILTER> implements ClusterInvoker<T> {
|
extends CopyOfFilterChainNode<T, TYPE, FILTER> implements ClusterInvoker<T> {
|
||||||
public CopyOfClusterFilterChainNode(TYPE originalInvoker, Invoker<T> nextNode, FILTER filter) {
|
public CopyOfClusterFilterChainNode(TYPE originalInvoker, Invoker<T> nextNode, FILTER filter) {
|
||||||
super(originalInvoker, nextNode, filter);
|
super(originalInvoker, nextNode, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URL getRegistryUrl() {
|
public URL getRegistryUrl() {
|
||||||
return getOriginalInvoker().getRegistryUrl();
|
return getOriginalInvoker().getRegistryUrl();
|
||||||
|
|
|
||||||
|
|
@ -62,8 +62,7 @@ public class ProtocolFilterWrapper implements Protocol {
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> FilterChainBuilder getFilterChainBuilder(URL url) {
|
private <T> FilterChainBuilder getFilterChainBuilder(URL url) {
|
||||||
return ScopeModelUtil.getExtensionLoader(FilterChainBuilder.class, url.getScopeModel())
|
return ScopeModelUtil.getExtensionLoader(FilterChainBuilder.class, url.getScopeModel()).getDefaultExtension();
|
||||||
.getDefaultExtension();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -84,4 +83,5 @@ public class ProtocolFilterWrapper implements Protocol {
|
||||||
public List<ProtocolServer> getServers() {
|
public List<ProtocolServer> getServers() {
|
||||||
return protocol.getServers();
|
return protocol.getServers();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
package org.apache.dubbo.rpc.cluster.filter.support;
|
|
||||||
|
|
||||||
import org.apache.dubbo.common.extension.Activate;
|
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
|
||||||
import org.apache.dubbo.rpc.Result;
|
|
||||||
import org.apache.dubbo.rpc.RpcException;
|
|
||||||
import org.apache.dubbo.rpc.cluster.filter.ClusterFilter;
|
|
||||||
import org.apache.dubbo.rpc.model.ServiceModel;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
|
|
||||||
|
|
||||||
@Activate(group = CONSUMER, order = Integer.MIN_VALUE + 100)
|
|
||||||
public class ConsumerClassLoaderFilter implements ClusterFilter {
|
|
||||||
@Override
|
|
||||||
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
|
|
||||||
ClassLoader originClassLoader = Thread.currentThread().getContextClassLoader();
|
|
||||||
try {
|
|
||||||
Optional.ofNullable(invocation.getServiceModel())
|
|
||||||
.map(ServiceModel::getClassLoader)
|
|
||||||
.ifPresent(Thread.currentThread()::setContextClassLoader);
|
|
||||||
return invoker.invoke(invocation);
|
|
||||||
} finally {
|
|
||||||
Thread.currentThread().setContextClassLoader(originClassLoader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -19,6 +19,7 @@ package org.apache.dubbo.rpc.cluster.filter.support;
|
||||||
import org.apache.dubbo.common.extension.Activate;
|
import org.apache.dubbo.common.extension.Activate;
|
||||||
import org.apache.dubbo.common.extension.ExtensionLoader;
|
import org.apache.dubbo.common.extension.ExtensionLoader;
|
||||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||||
|
import org.apache.dubbo.common.utils.NetUtils;
|
||||||
import org.apache.dubbo.rpc.AsyncRpcResult;
|
import org.apache.dubbo.rpc.AsyncRpcResult;
|
||||||
import org.apache.dubbo.rpc.Filter;
|
import org.apache.dubbo.rpc.Filter;
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
import org.apache.dubbo.rpc.Invocation;
|
||||||
|
|
@ -32,13 +33,11 @@ import org.apache.dubbo.rpc.RpcInvocation;
|
||||||
import org.apache.dubbo.rpc.TimeoutCountDown;
|
import org.apache.dubbo.rpc.TimeoutCountDown;
|
||||||
import org.apache.dubbo.rpc.cluster.filter.ClusterFilter;
|
import org.apache.dubbo.rpc.cluster.filter.ClusterFilter;
|
||||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||||
import org.apache.dubbo.rpc.support.RpcUtils;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
|
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.ENABLE_TIMEOUT_COUNTDOWN_KEY;
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_APPLICATION_KEY;
|
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_APPLICATION_KEY;
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.TIME_COUNTDOWN_KEY;
|
import static org.apache.dubbo.common.constants.CommonConstants.TIME_COUNTDOWN_KEY;
|
||||||
|
|
||||||
|
|
@ -55,75 +54,70 @@ public class ConsumerContextFilter implements ClusterFilter, ClusterFilter.Liste
|
||||||
private Set<PenetrateAttachmentSelector> supportedSelectors;
|
private Set<PenetrateAttachmentSelector> supportedSelectors;
|
||||||
|
|
||||||
public ConsumerContextFilter(ApplicationModel applicationModel) {
|
public ConsumerContextFilter(ApplicationModel applicationModel) {
|
||||||
ExtensionLoader<PenetrateAttachmentSelector> selectorExtensionLoader =
|
ExtensionLoader<PenetrateAttachmentSelector> selectorExtensionLoader = applicationModel.getExtensionLoader(PenetrateAttachmentSelector.class);
|
||||||
applicationModel.getExtensionLoader(PenetrateAttachmentSelector.class);
|
|
||||||
supportedSelectors = selectorExtensionLoader.getSupportedExtensionInstances();
|
supportedSelectors = selectorExtensionLoader.getSupportedExtensionInstances();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
|
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
|
||||||
RpcContext.getServiceContext().setInvoker(invoker).setInvocation(invocation);
|
RpcContext.RestoreServiceContext originServiceContext = RpcContext.storeServiceContext();
|
||||||
|
try {
|
||||||
|
RpcContext.getServiceContext()
|
||||||
|
.setInvoker(invoker)
|
||||||
|
.setInvocation(invocation)
|
||||||
|
.setLocalAddress(NetUtils.getLocalHost(), 0);
|
||||||
|
|
||||||
RpcContext context = RpcContext.getClientAttachment();
|
RpcContext context = RpcContext.getClientAttachment();
|
||||||
context.setAttachment(REMOTE_APPLICATION_KEY, invoker.getUrl().getApplication());
|
context.setAttachment(REMOTE_APPLICATION_KEY, invoker.getUrl().getApplication());
|
||||||
if (invocation instanceof RpcInvocation) {
|
if (invocation instanceof RpcInvocation) {
|
||||||
((RpcInvocation) invocation).setInvoker(invoker);
|
((RpcInvocation) invocation).setInvoker(invoker);
|
||||||
}
|
|
||||||
|
|
||||||
if (CollectionUtils.isNotEmpty(supportedSelectors)) {
|
|
||||||
for (PenetrateAttachmentSelector supportedSelector : supportedSelectors) {
|
|
||||||
Map<String, Object> selected = supportedSelector.select(
|
|
||||||
invocation, RpcContext.getClientAttachment(), RpcContext.getServerAttachment());
|
|
||||||
if (CollectionUtils.isNotEmptyMap(selected)) {
|
|
||||||
((RpcInvocation) invocation).addObjectAttachments(selected);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
((RpcInvocation) invocation)
|
|
||||||
.addObjectAttachments(RpcContext.getServerAttachment().getObjectAttachments());
|
|
||||||
}
|
|
||||||
Map<String, Object> contextAttachments =
|
|
||||||
RpcContext.getClientAttachment().getObjectAttachments();
|
|
||||||
if (CollectionUtils.isNotEmptyMap(contextAttachments)) {
|
|
||||||
/**
|
|
||||||
* invocation.addAttachmentsIfAbsent(context){@link RpcInvocation#addAttachmentsIfAbsent(Map)}should not be used here,
|
|
||||||
* because the {@link RpcContext#setAttachment(String, String)} is passed in the Filter when the call is triggered
|
|
||||||
* by the built-in retry mechanism of the Dubbo. The attachment to update RpcContext will no longer work, which is
|
|
||||||
* a mistake in most cases (for example, through Filter to RpcContext output traceId and spanId and other information).
|
|
||||||
*/
|
|
||||||
((RpcInvocation) invocation).addObjectAttachments(contextAttachments);
|
|
||||||
}
|
|
||||||
|
|
||||||
// pass default timeout set by end user (ReferenceConfig)
|
if (CollectionUtils.isNotEmpty(supportedSelectors)) {
|
||||||
Object countDown = RpcContext.getServerAttachment().getObjectAttachment(TIME_COUNTDOWN_KEY);
|
for (PenetrateAttachmentSelector supportedSelector : supportedSelectors) {
|
||||||
if (countDown != null) {
|
Map<String, Object> selected = supportedSelector.select();
|
||||||
String methodName = RpcUtils.getMethodName(invocation);
|
if (CollectionUtils.isNotEmptyMap(selected)) {
|
||||||
// When the client has enabled the timeout-countdown function,
|
((RpcInvocation) invocation).addObjectAttachments(selected);
|
||||||
// the subsequent calls launched by the Server side will be enabled by default,
|
}
|
||||||
// and support to turn off the function on a node to get rid of the timeout control.
|
}
|
||||||
if (invoker.getUrl().getMethodParameter(methodName, ENABLE_TIMEOUT_COUNTDOWN_KEY, true)) {
|
} else {
|
||||||
context.setObjectAttachment(TIME_COUNTDOWN_KEY, countDown);
|
((RpcInvocation) invocation).addObjectAttachments(RpcContext.getServerAttachment().getObjectAttachments());
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> contextAttachments = RpcContext.getClientAttachment().getObjectAttachments();
|
||||||
|
if (CollectionUtils.isNotEmptyMap(contextAttachments)) {
|
||||||
|
/**
|
||||||
|
* invocation.addAttachmentsIfAbsent(context){@link RpcInvocation#addAttachmentsIfAbsent(Map)}should not be used here,
|
||||||
|
* because the {@link RpcContext#setAttachment(String, String)} is passed in the Filter when the call is triggered
|
||||||
|
* by the built-in retry mechanism of the Dubbo. The attachment to update RpcContext will no longer work, which is
|
||||||
|
* a mistake in most cases (for example, through Filter to RpcContext output traceId and spanId and other information).
|
||||||
|
*/
|
||||||
|
((RpcInvocation) invocation).addObjectAttachments(contextAttachments);
|
||||||
|
}
|
||||||
|
|
||||||
|
// pass default timeout set by end user (ReferenceConfig)
|
||||||
|
Object countDown = context.getObjectAttachment(TIME_COUNTDOWN_KEY);
|
||||||
|
if (countDown != null) {
|
||||||
TimeoutCountDown timeoutCountDown = (TimeoutCountDown) countDown;
|
TimeoutCountDown timeoutCountDown = (TimeoutCountDown) countDown;
|
||||||
if (timeoutCountDown.isExpired()) {
|
if (timeoutCountDown.isExpired()) {
|
||||||
return AsyncRpcResult.newDefaultAsyncResult(
|
return AsyncRpcResult.newDefaultAsyncResult(new RpcException(RpcException.TIMEOUT_TERMINATE,
|
||||||
new RpcException(
|
"No time left for making the following call: " + invocation.getServiceName() + "."
|
||||||
RpcException.TIMEOUT_TERMINATE,
|
+ invocation.getMethodName() + ", terminate directly."), invocation);
|
||||||
"No time left for making the following call: " + invocation.getServiceName() + "."
|
|
||||||
+ RpcUtils.getMethodName(invocation) + ", terminate directly."),
|
|
||||||
invocation);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RpcContext.removeServerContext();
|
||||||
|
return invoker.invoke(invocation);
|
||||||
|
} finally {
|
||||||
|
RpcContext.restoreServiceContext(originServiceContext);
|
||||||
}
|
}
|
||||||
RpcContext.removeClientResponseContext();
|
|
||||||
return invoker.invoke(invocation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {
|
public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {
|
||||||
// pass attachments to result
|
// pass attachments to result
|
||||||
Map<String, Object> map = appResponse.getObjectAttachments();
|
RpcContext.getServerContext().setObjectAttachments(appResponse.getObjectAttachments());
|
||||||
RpcContext.getClientResponseContext().setObjectAttachments(map);
|
|
||||||
removeContext(invocation);
|
removeContext(invocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,15 +132,14 @@ public class ConsumerContextFilter implements ClusterFilter, ClusterFilter.Liste
|
||||||
RpcInvocation rpcInvocation = (RpcInvocation) invocation;
|
RpcInvocation rpcInvocation = (RpcInvocation) invocation;
|
||||||
if (rpcInvocation.getInvokeMode() != null) {
|
if (rpcInvocation.getInvokeMode() != null) {
|
||||||
// clear service context if not in sync mode
|
// clear service context if not in sync mode
|
||||||
if (rpcInvocation.getInvokeMode() == InvokeMode.ASYNC
|
if (rpcInvocation.getInvokeMode() == InvokeMode.ASYNC || rpcInvocation.getInvokeMode() == InvokeMode.FUTURE) {
|
||||||
|| rpcInvocation.getInvokeMode() == InvokeMode.FUTURE) {
|
|
||||||
RpcContext.removeServiceContext();
|
RpcContext.removeServiceContext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// server context must not be removed because user might use it on callback.
|
// server context must not be removed because user might use it on callback.
|
||||||
// So the clear of is delayed til the start of the next rpc call, see RpcContext.removeServerContext(); in
|
// So the clear of is delayed til the start of the next rpc call, see RpcContext.removeServerContext(); in invoke() above
|
||||||
// invoke() above
|
|
||||||
// RpcContext.removeServerContext();
|
// RpcContext.removeServerContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
package org.apache.dubbo.rpc.cluster.filter.support;
|
|
||||||
|
|
||||||
import org.apache.dubbo.common.extension.Activate;
|
|
||||||
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
|
|
||||||
import org.apache.dubbo.metrics.event.MetricsDispatcher;
|
|
||||||
import org.apache.dubbo.metrics.event.MetricsEventBus;
|
|
||||||
import org.apache.dubbo.metrics.event.RequestEvent;
|
|
||||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
|
||||||
import org.apache.dubbo.rpc.BaseFilter;
|
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
|
||||||
import org.apache.dubbo.rpc.Result;
|
|
||||||
import org.apache.dubbo.rpc.RpcException;
|
|
||||||
import org.apache.dubbo.rpc.cluster.filter.ClusterFilter;
|
|
||||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
|
||||||
import org.apache.dubbo.rpc.model.ScopeModelAware;
|
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
|
|
||||||
|
|
||||||
@Activate(group = CONSUMER, onClass = "org.apache.dubbo.metrics.collector.DefaultMetricsCollector")
|
|
||||||
public class MetricsClusterFilter implements ClusterFilter, BaseFilter.Listener, ScopeModelAware {
|
|
||||||
|
|
||||||
private ApplicationModel applicationModel;
|
|
||||||
private DefaultMetricsCollector collector;
|
|
||||||
private String appName;
|
|
||||||
private MetricsDispatcher metricsDispatcher;
|
|
||||||
private boolean serviceLevel;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setApplicationModel(ApplicationModel applicationModel) {
|
|
||||||
this.applicationModel = applicationModel;
|
|
||||||
this.collector = applicationModel.getBeanFactory().getBean(DefaultMetricsCollector.class);
|
|
||||||
this.appName = applicationModel.tryGetApplicationName();
|
|
||||||
this.metricsDispatcher = applicationModel.getBeanFactory().getBean(MetricsDispatcher.class);
|
|
||||||
this.serviceLevel = MethodMetric.isServiceLevel(applicationModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
|
|
||||||
return invoker.invoke(invocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResponse(Result result, Invoker<?> invoker, Invocation invocation) {
|
|
||||||
handleMethodException(result.getException(), invocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {
|
|
||||||
handleMethodException(t, invocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleMethodException(Throwable t, Invocation invocation) {
|
|
||||||
if (collector == null || !collector.isCollectEnabled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (t instanceof RpcException) {
|
|
||||||
RpcException e = (RpcException) t;
|
|
||||||
if (e.isForbidden()) {
|
|
||||||
MetricsEventBus.publish(RequestEvent.toRequestErrorEvent(
|
|
||||||
applicationModel,
|
|
||||||
appName,
|
|
||||||
metricsDispatcher,
|
|
||||||
invocation,
|
|
||||||
CONSUMER_SIDE,
|
|
||||||
e.getCode(),
|
|
||||||
serviceLevel));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
package org.apache.dubbo.rpc.cluster.filter.support;
|
|
||||||
|
|
||||||
import org.apache.dubbo.common.extension.Activate;
|
|
||||||
import org.apache.dubbo.metrics.filter.MetricsFilter;
|
|
||||||
import org.apache.dubbo.rpc.BaseFilter;
|
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
|
||||||
import org.apache.dubbo.rpc.Result;
|
|
||||||
import org.apache.dubbo.rpc.RpcException;
|
|
||||||
import org.apache.dubbo.rpc.cluster.filter.ClusterFilter;
|
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
|
|
||||||
|
|
||||||
@Activate(
|
|
||||||
group = {CONSUMER},
|
|
||||||
order = Integer.MIN_VALUE + 100)
|
|
||||||
public class MetricsConsumerFilter extends MetricsFilter implements ClusterFilter, BaseFilter.Listener {
|
|
||||||
public MetricsConsumerFilter() {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
|
|
||||||
return super.invoke(invoker, invocation, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {
|
|
||||||
super.onResponse(appResponse, invoker, invocation, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {
|
|
||||||
super.onError(t, invoker, invocation, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
package org.apache.dubbo.rpc.cluster.filter.support;
|
|
||||||
|
|
||||||
import org.apache.dubbo.common.extension.Activate;
|
|
||||||
import org.apache.dubbo.metrics.observation.DefaultDubboClientObservationConvention;
|
|
||||||
import org.apache.dubbo.metrics.observation.DubboClientContext;
|
|
||||||
import org.apache.dubbo.metrics.observation.DubboClientObservationConvention;
|
|
||||||
import org.apache.dubbo.metrics.observation.DubboObservationDocumentation;
|
|
||||||
import org.apache.dubbo.rpc.BaseFilter;
|
|
||||||
import org.apache.dubbo.rpc.Filter;
|
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
|
||||||
import org.apache.dubbo.rpc.Result;
|
|
||||||
import org.apache.dubbo.rpc.RpcException;
|
|
||||||
import org.apache.dubbo.rpc.cluster.filter.ClusterFilter;
|
|
||||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
|
||||||
import org.apache.dubbo.rpc.model.ScopeModelAware;
|
|
||||||
|
|
||||||
import io.micrometer.observation.Observation;
|
|
||||||
import io.micrometer.observation.ObservationRegistry;
|
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link Filter} that creates an {@link Observation} around the outgoing message.
|
|
||||||
*/
|
|
||||||
@Activate(group = CONSUMER, order = -1, onClass = "io.micrometer.observation.NoopObservationRegistry")
|
|
||||||
public class ObservationSenderFilter implements ClusterFilter, BaseFilter.Listener, ScopeModelAware {
|
|
||||||
|
|
||||||
private ObservationRegistry observationRegistry;
|
|
||||||
|
|
||||||
private DubboClientObservationConvention clientObservationConvention;
|
|
||||||
|
|
||||||
public ObservationSenderFilter(ApplicationModel applicationModel) {
|
|
||||||
applicationModel.getApplicationConfigManager().getTracing().ifPresent(cfg -> {
|
|
||||||
if (Boolean.TRUE.equals(cfg.getEnabled())) {
|
|
||||||
observationRegistry = applicationModel.getBeanFactory().getBean(ObservationRegistry.class);
|
|
||||||
clientObservationConvention =
|
|
||||||
applicationModel.getBeanFactory().getBean(DubboClientObservationConvention.class);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
|
|
||||||
if (observationRegistry == null) {
|
|
||||||
return invoker.invoke(invocation);
|
|
||||||
}
|
|
||||||
final DubboClientContext senderContext = new DubboClientContext(invoker, invocation);
|
|
||||||
final Observation observation = DubboObservationDocumentation.CLIENT.observation(
|
|
||||||
this.clientObservationConvention,
|
|
||||||
DefaultDubboClientObservationConvention.getInstance(),
|
|
||||||
() -> senderContext,
|
|
||||||
observationRegistry);
|
|
||||||
invocation.put(Observation.class, observation.start());
|
|
||||||
return observation.scoped(() -> invoker.invoke(invocation));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {
|
|
||||||
final Observation observation = getObservation(invocation);
|
|
||||||
if (observation == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
observation.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {
|
|
||||||
final Observation observation = getObservation(invocation);
|
|
||||||
if (observation == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
observation.error(t);
|
|
||||||
observation.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Observation getObservation(Invocation invocation) {
|
|
||||||
return (Observation) invocation.get(Observation.class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -22,7 +22,7 @@ import org.apache.dubbo.rpc.model.ModuleModel;
|
||||||
|
|
||||||
public class DefaultGovernanceRuleRepositoryImpl implements GovernanceRuleRepository {
|
public class DefaultGovernanceRuleRepositoryImpl implements GovernanceRuleRepository {
|
||||||
|
|
||||||
private final ModuleModel moduleModel;
|
private ModuleModel moduleModel;
|
||||||
|
|
||||||
public DefaultGovernanceRuleRepositoryImpl(ModuleModel moduleModel) {
|
public DefaultGovernanceRuleRepositoryImpl(ModuleModel moduleModel) {
|
||||||
this.moduleModel = moduleModel;
|
this.moduleModel = moduleModel;
|
||||||
|
|
@ -54,6 +54,7 @@ public class DefaultGovernanceRuleRepositoryImpl implements GovernanceRuleReposi
|
||||||
}
|
}
|
||||||
|
|
||||||
private DynamicConfiguration getDynamicConfiguration() {
|
private DynamicConfiguration getDynamicConfiguration() {
|
||||||
return moduleModel.modelEnvironment().getDynamicConfiguration().orElse(null);
|
return moduleModel.getModelEnvironment().getDynamicConfiguration().orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ public interface GovernanceRuleRepository {
|
||||||
addListener(key, DEFAULT_GROUP, listener);
|
addListener(key, DEFAULT_GROUP, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link #removeListener(String, String, ConfigurationListener)}
|
* {@link #removeListener(String, String, ConfigurationListener)}
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ import org.apache.dubbo.rpc.Invocation;
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
import org.apache.dubbo.rpc.Invoker;
|
||||||
import org.apache.dubbo.rpc.cluster.ClusterInvoker;
|
import org.apache.dubbo.rpc.cluster.ClusterInvoker;
|
||||||
import org.apache.dubbo.rpc.cluster.LoadBalance;
|
import org.apache.dubbo.rpc.cluster.LoadBalance;
|
||||||
import org.apache.dubbo.rpc.support.RpcUtils;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
@ -47,7 +46,7 @@ public abstract class AbstractLoadBalance implements LoadBalance {
|
||||||
* @return weight which takes warmup into account
|
* @return weight which takes warmup into account
|
||||||
*/
|
*/
|
||||||
static int calculateWarmupWeight(int uptime, int warmup, int weight) {
|
static int calculateWarmupWeight(int uptime, int warmup, int weight) {
|
||||||
int ww = (int) (uptime / ((float) warmup / weight));
|
int ww = (int) ( uptime / ((float) warmup / weight));
|
||||||
return ww < 1 ? 1 : (Math.min(ww, weight));
|
return ww < 1 ? 1 : (Math.min(ww, weight));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,6 +63,7 @@ public abstract class AbstractLoadBalance implements LoadBalance {
|
||||||
|
|
||||||
protected abstract <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation);
|
protected abstract <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the weight of the invoker's invocation which takes warmup time into account
|
* Get the weight of the invoker's invocation which takes warmup time into account
|
||||||
* if the uptime is within the warmup time, the weight will be reduce proportionally
|
* if the uptime is within the warmup time, the weight will be reduce proportionally
|
||||||
|
|
@ -83,7 +83,7 @@ public abstract class AbstractLoadBalance implements LoadBalance {
|
||||||
if (REGISTRY_SERVICE_REFERENCE_PATH.equals(url.getServiceInterface())) {
|
if (REGISTRY_SERVICE_REFERENCE_PATH.equals(url.getServiceInterface())) {
|
||||||
weight = url.getParameter(WEIGHT_KEY, DEFAULT_WEIGHT);
|
weight = url.getParameter(WEIGHT_KEY, DEFAULT_WEIGHT);
|
||||||
} else {
|
} else {
|
||||||
weight = url.getMethodParameter(RpcUtils.getMethodName(invocation), WEIGHT_KEY, DEFAULT_WEIGHT);
|
weight = url.getMethodParameter(invocation.getMethodName(), WEIGHT_KEY, DEFAULT_WEIGHT);
|
||||||
if (weight > 0) {
|
if (weight > 0) {
|
||||||
long timestamp = invoker.getUrl().getParameter(TIMESTAMP_KEY, 0L);
|
long timestamp = invoker.getUrl().getParameter(TIMESTAMP_KEY, 0L);
|
||||||
if (timestamp > 0L) {
|
if (timestamp > 0L) {
|
||||||
|
|
@ -93,7 +93,7 @@ public abstract class AbstractLoadBalance implements LoadBalance {
|
||||||
}
|
}
|
||||||
int warmup = invoker.getUrl().getParameter(WARMUP_KEY, DEFAULT_WARMUP);
|
int warmup = invoker.getUrl().getParameter(WARMUP_KEY, DEFAULT_WARMUP);
|
||||||
if (uptime > 0 && uptime < warmup) {
|
if (uptime > 0 && uptime < warmup) {
|
||||||
weight = calculateWarmupWeight((int) uptime, warmup, weight);
|
weight = calculateWarmupWeight((int)uptime, warmup, weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,135 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
package org.apache.dubbo.rpc.cluster.loadbalance;
|
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
|
||||||
import org.apache.dubbo.common.constants.LoadbalanceRules;
|
|
||||||
import org.apache.dubbo.common.utils.StringUtils;
|
|
||||||
import org.apache.dubbo.rpc.AdaptiveMetrics;
|
|
||||||
import org.apache.dubbo.rpc.Constants;
|
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
|
||||||
import org.apache.dubbo.rpc.RpcContext;
|
|
||||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
|
||||||
import org.apache.dubbo.rpc.support.RpcUtils;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT;
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.LOADBALANCE_KEY;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AdaptiveLoadBalance
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
public class AdaptiveLoadBalance extends AbstractLoadBalance {
|
|
||||||
|
|
||||||
public static final String NAME = "adaptive";
|
|
||||||
|
|
||||||
// default key
|
|
||||||
private String attachmentKey = "mem,load";
|
|
||||||
|
|
||||||
private final AdaptiveMetrics adaptiveMetrics;
|
|
||||||
|
|
||||||
public AdaptiveLoadBalance(ApplicationModel scopeModel) {
|
|
||||||
adaptiveMetrics = scopeModel.getBeanFactory().getBean(AdaptiveMetrics.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
|
|
||||||
Invoker<T> invoker = selectByP2C(invokers, invocation);
|
|
||||||
invocation.setAttachment(Constants.ADAPTIVE_LOADBALANCE_ATTACHMENT_KEY, attachmentKey);
|
|
||||||
long startTime = System.currentTimeMillis();
|
|
||||||
invocation.getAttributes().put(Constants.ADAPTIVE_LOADBALANCE_START_TIME, startTime);
|
|
||||||
invocation.getAttributes().put(LOADBALANCE_KEY, LoadbalanceRules.ADAPTIVE);
|
|
||||||
adaptiveMetrics.addConsumerReq(getServiceKey(invoker, invocation));
|
|
||||||
adaptiveMetrics.setPickTime(getServiceKey(invoker, invocation), startTime);
|
|
||||||
|
|
||||||
return invoker;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> Invoker<T> selectByP2C(List<Invoker<T>> invokers, Invocation invocation) {
|
|
||||||
int length = invokers.size();
|
|
||||||
if (length == 1) {
|
|
||||||
return invokers.get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length == 2) {
|
|
||||||
return chooseLowLoadInvoker(invokers.get(0), invokers.get(1), invocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
int pos1 = ThreadLocalRandom.current().nextInt(length);
|
|
||||||
int pos2 = ThreadLocalRandom.current().nextInt(length - 1);
|
|
||||||
if (pos2 >= pos1) {
|
|
||||||
pos2 = pos2 + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return chooseLowLoadInvoker(invokers.get(pos1), invokers.get(pos2), invocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getServiceKey(Invoker<?> invoker, Invocation invocation) {
|
|
||||||
|
|
||||||
String key = (String) invocation.getAttributes().get(invoker);
|
|
||||||
if (StringUtils.isNotEmpty(key)) {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
key = buildServiceKey(invoker, invocation);
|
|
||||||
invocation.getAttributes().put(invoker, key);
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String buildServiceKey(Invoker<?> invoker, Invocation invocation) {
|
|
||||||
URL url = invoker.getUrl();
|
|
||||||
StringBuilder sb = new StringBuilder(128);
|
|
||||||
sb.append(url.getAddress()).append(":").append(invocation.getProtocolServiceKey());
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getTimeout(Invoker<?> invoker, Invocation invocation) {
|
|
||||||
URL url = invoker.getUrl();
|
|
||||||
String methodName = RpcUtils.getMethodName(invocation);
|
|
||||||
return (int)
|
|
||||||
RpcUtils.getTimeout(url, methodName, RpcContext.getClientAttachment(), invocation, DEFAULT_TIMEOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> Invoker<T> chooseLowLoadInvoker(Invoker<T> invoker1, Invoker<T> invoker2, Invocation invocation) {
|
|
||||||
int weight1 = getWeight(invoker1, invocation);
|
|
||||||
int weight2 = getWeight(invoker2, invocation);
|
|
||||||
int timeout1 = getTimeout(invoker1, invocation);
|
|
||||||
int timeout2 = getTimeout(invoker2, invocation);
|
|
||||||
long load1 = Double.doubleToLongBits(
|
|
||||||
adaptiveMetrics.getLoad(getServiceKey(invoker1, invocation), weight1, timeout1));
|
|
||||||
long load2 = Double.doubleToLongBits(
|
|
||||||
adaptiveMetrics.getLoad(getServiceKey(invoker2, invocation), weight2, timeout2));
|
|
||||||
|
|
||||||
if (load1 == load2) {
|
|
||||||
// The sum of weights
|
|
||||||
int totalWeight = weight1 + weight2;
|
|
||||||
if (totalWeight > 0) {
|
|
||||||
int offset = ThreadLocalRandom.current().nextInt(totalWeight);
|
|
||||||
if (offset < weight1) {
|
|
||||||
return invoker1;
|
|
||||||
}
|
|
||||||
return invoker2;
|
|
||||||
}
|
|
||||||
return ThreadLocalRandom.current().nextInt(2) == 0 ? invoker1 : invoker2;
|
|
||||||
}
|
|
||||||
return load1 > load2 ? invoker2 : invoker1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -46,7 +46,7 @@ public class ConsistentHashLoadBalance extends AbstractLoadBalance {
|
||||||
*/
|
*/
|
||||||
public static final String HASH_ARGUMENTS = "hash.arguments";
|
public static final String HASH_ARGUMENTS = "hash.arguments";
|
||||||
|
|
||||||
private final ConcurrentMap<String, ConsistentHashSelector<?>> selectors = new ConcurrentHashMap<>();
|
private final ConcurrentMap<String, ConsistentHashSelector<?>> selectors = new ConcurrentHashMap<String, ConsistentHashSelector<?>>();
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -74,7 +74,7 @@ public class ConsistentHashLoadBalance extends AbstractLoadBalance {
|
||||||
private final int[] argumentIndex;
|
private final int[] argumentIndex;
|
||||||
|
|
||||||
ConsistentHashSelector(List<Invoker<T>> invokers, String methodName, int identityHashCode) {
|
ConsistentHashSelector(List<Invoker<T>> invokers, String methodName, int identityHashCode) {
|
||||||
this.virtualInvokers = new TreeMap<>();
|
this.virtualInvokers = new TreeMap<Long, Invoker<T>>();
|
||||||
this.identityHashCode = identityHashCode;
|
this.identityHashCode = identityHashCode;
|
||||||
URL url = invokers.get(0).getUrl();
|
URL url = invokers.get(0).getUrl();
|
||||||
this.replicaNumber = url.getMethodParameter(methodName, HASH_NODES, 160);
|
this.replicaNumber = url.getMethodParameter(methodName, HASH_NODES, 160);
|
||||||
|
|
@ -96,8 +96,7 @@ public class ConsistentHashLoadBalance extends AbstractLoadBalance {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Invoker<T> select(Invocation invocation) {
|
public Invoker<T> select(Invocation invocation) {
|
||||||
String key = toKey(RpcUtils.getArguments(invocation));
|
String key = toKey(invocation.getArguments());
|
||||||
|
|
||||||
byte[] digest = Bytes.getMD5(key);
|
byte[] digest = Bytes.getMD5(key);
|
||||||
return selectForKey(hash(digest, 0));
|
return selectForKey(hash(digest, 0));
|
||||||
}
|
}
|
||||||
|
|
@ -105,7 +104,7 @@ public class ConsistentHashLoadBalance extends AbstractLoadBalance {
|
||||||
private String toKey(Object[] args) {
|
private String toKey(Object[] args) {
|
||||||
StringBuilder buf = new StringBuilder();
|
StringBuilder buf = new StringBuilder();
|
||||||
for (int i : argumentIndex) {
|
for (int i : argumentIndex) {
|
||||||
if (i >= 0 && args != null && i < args.length) {
|
if (i >= 0 && i < args.length) {
|
||||||
buf.append(args[i]);
|
buf.append(args[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -122,10 +121,11 @@ public class ConsistentHashLoadBalance extends AbstractLoadBalance {
|
||||||
|
|
||||||
private long hash(byte[] digest, int number) {
|
private long hash(byte[] digest, int number) {
|
||||||
return (((long) (digest[3 + number * 4] & 0xFF) << 24)
|
return (((long) (digest[3 + number * 4] & 0xFF) << 24)
|
||||||
| ((long) (digest[2 + number * 4] & 0xFF) << 16)
|
| ((long) (digest[2 + number * 4] & 0xFF) << 16)
|
||||||
| ((long) (digest[1 + number * 4] & 0xFF) << 8)
|
| ((long) (digest[1 + number * 4] & 0xFF) << 8)
|
||||||
| (digest[number * 4] & 0xFF))
|
| (digest[number * 4] & 0xFF))
|
||||||
& 0xFFFFFFFFL;
|
& 0xFFFFFFFFL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ import org.apache.dubbo.common.URL;
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
import org.apache.dubbo.rpc.Invocation;
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
import org.apache.dubbo.rpc.Invoker;
|
||||||
import org.apache.dubbo.rpc.RpcStatus;
|
import org.apache.dubbo.rpc.RpcStatus;
|
||||||
import org.apache.dubbo.rpc.support.RpcUtils;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
@ -56,18 +55,17 @@ public class LeastActiveLoadBalance extends AbstractLoadBalance {
|
||||||
// Every least active invoker has the same weight value?
|
// Every least active invoker has the same weight value?
|
||||||
boolean sameWeight = true;
|
boolean sameWeight = true;
|
||||||
|
|
||||||
|
|
||||||
// Filter out all the least active invokers
|
// Filter out all the least active invokers
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
Invoker<T> invoker = invokers.get(i);
|
Invoker<T> invoker = invokers.get(i);
|
||||||
// Get the active number of the invoker
|
// Get the active number of the invoker
|
||||||
int active = RpcStatus.getStatus(invoker.getUrl(), RpcUtils.getMethodName(invocation))
|
int active = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName()).getActive();
|
||||||
.getActive();
|
|
||||||
// Get the weight of the invoker's configuration. The default value is 100.
|
// Get the weight of the invoker's configuration. The default value is 100.
|
||||||
int afterWarmup = getWeight(invoker, invocation);
|
int afterWarmup = getWeight(invoker, invocation);
|
||||||
// save for later use
|
// save for later use
|
||||||
weights[i] = afterWarmup;
|
weights[i] = afterWarmup;
|
||||||
// If it is the first invoker or the active number of the invoker is less than the current least active
|
// If it is the first invoker or the active number of the invoker is less than the current least active number
|
||||||
// number
|
|
||||||
if (leastActive == -1 || active < leastActive) {
|
if (leastActive == -1 || active < leastActive) {
|
||||||
// Reset the active number of the current invoker to the least active number
|
// Reset the active number of the current invoker to the least active number
|
||||||
leastActive = active;
|
leastActive = active;
|
||||||
|
|
@ -99,7 +97,7 @@ public class LeastActiveLoadBalance extends AbstractLoadBalance {
|
||||||
return invokers.get(leastIndexes[0]);
|
return invokers.get(leastIndexes[0]);
|
||||||
}
|
}
|
||||||
if (!sameWeight && totalWeight > 0) {
|
if (!sameWeight && totalWeight > 0) {
|
||||||
// If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on
|
// If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on
|
||||||
// totalWeight.
|
// totalWeight.
|
||||||
int offsetWeight = ThreadLocalRandom.current().nextInt(totalWeight);
|
int offsetWeight = ThreadLocalRandom.current().nextInt(totalWeight);
|
||||||
// Return a invoker based on the random value.
|
// Return a invoker based on the random value.
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,7 @@ import org.apache.dubbo.common.utils.StringUtils;
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
import org.apache.dubbo.rpc.Invocation;
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
import org.apache.dubbo.rpc.Invoker;
|
||||||
import org.apache.dubbo.rpc.cluster.ClusterInvoker;
|
import org.apache.dubbo.rpc.cluster.ClusterInvoker;
|
||||||
import org.apache.dubbo.rpc.support.RpcUtils;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
|
@ -45,9 +43,8 @@ public class RandomLoadBalance extends AbstractLoadBalance {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select one invoker between a list using a random criteria
|
* Select one invoker between a list using a random criteria
|
||||||
*
|
* @param invokers List of possible invokers
|
||||||
* @param invokers List of possible invokers
|
* @param url URL
|
||||||
* @param url URL
|
|
||||||
* @param invocation Invocation
|
* @param invocation Invocation
|
||||||
* @param <T>
|
* @param <T>
|
||||||
* @return The selected invoker
|
* @return The selected invoker
|
||||||
|
|
@ -57,13 +54,13 @@ public class RandomLoadBalance extends AbstractLoadBalance {
|
||||||
// Number of invokers
|
// Number of invokers
|
||||||
int length = invokers.size();
|
int length = invokers.size();
|
||||||
|
|
||||||
if (!needWeightLoadBalance(invokers, invocation)) {
|
if (!needWeightLoadBalance(invokers,invocation)){
|
||||||
return invokers.get(ThreadLocalRandom.current().nextInt(length));
|
return invokers.get(ThreadLocalRandom.current().nextInt(length));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Every invoker has the same weight?
|
// Every invoker has the same weight?
|
||||||
boolean sameWeight = true;
|
boolean sameWeight = true;
|
||||||
// the maxWeight of every invoker, the minWeight = 0 or the maxWeight of the last invoker
|
// the maxWeight of every invokers, the minWeight = 0 or the maxWeight of the last invoker
|
||||||
int[] weights = new int[length];
|
int[] weights = new int[length];
|
||||||
// The sum of weights
|
// The sum of weights
|
||||||
int totalWeight = 0;
|
int totalWeight = 0;
|
||||||
|
|
@ -78,27 +75,13 @@ public class RandomLoadBalance extends AbstractLoadBalance {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (totalWeight > 0 && !sameWeight) {
|
if (totalWeight > 0 && !sameWeight) {
|
||||||
// If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on
|
// If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeight.
|
||||||
// totalWeight.
|
|
||||||
int offset = ThreadLocalRandom.current().nextInt(totalWeight);
|
int offset = ThreadLocalRandom.current().nextInt(totalWeight);
|
||||||
// Return an invoker based on the random value.
|
// Return a invoker based on the random value.
|
||||||
if (length <= 4) {
|
for (int i = 0; i < length; i++) {
|
||||||
for (int i = 0; i < length; i++) {
|
if (offset < weights[i]) {
|
||||||
if (offset < weights[i]) {
|
return invokers.get(i);
|
||||||
return invokers.get(i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
int i = Arrays.binarySearch(weights, offset);
|
|
||||||
if (i < 0) {
|
|
||||||
i = -i - 1;
|
|
||||||
} else {
|
|
||||||
while (weights[i + 1] == offset) {
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
return invokers.get(i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If all invokers have the same weight value or totalWeight=0, return evenly.
|
// If all invokers have the same weight value or totalWeight=0, return evenly.
|
||||||
|
|
@ -106,7 +89,8 @@ public class RandomLoadBalance extends AbstractLoadBalance {
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> boolean needWeightLoadBalance(List<Invoker<T>> invokers, Invocation invocation) {
|
private <T> boolean needWeightLoadBalance(List<Invoker<T>> invokers, Invocation invocation) {
|
||||||
Invoker<T> invoker = invokers.get(0);
|
|
||||||
|
Invoker invoker = invokers.get(0);
|
||||||
URL invokerUrl = invoker.getUrl();
|
URL invokerUrl = invoker.getUrl();
|
||||||
if (invoker instanceof ClusterInvoker) {
|
if (invoker instanceof ClusterInvoker) {
|
||||||
invokerUrl = ((ClusterInvoker<?>) invoker).getRegistryUrl();
|
invokerUrl = ((ClusterInvoker<?>) invoker).getRegistryUrl();
|
||||||
|
|
@ -115,15 +99,22 @@ public class RandomLoadBalance extends AbstractLoadBalance {
|
||||||
// Multiple registry scenario, load balance among multiple registries.
|
// Multiple registry scenario, load balance among multiple registries.
|
||||||
if (REGISTRY_SERVICE_REFERENCE_PATH.equals(invokerUrl.getServiceInterface())) {
|
if (REGISTRY_SERVICE_REFERENCE_PATH.equals(invokerUrl.getServiceInterface())) {
|
||||||
String weight = invokerUrl.getParameter(WEIGHT_KEY);
|
String weight = invokerUrl.getParameter(WEIGHT_KEY);
|
||||||
return StringUtils.isNotEmpty(weight);
|
|
||||||
} else {
|
|
||||||
String weight = invokerUrl.getMethodParameter(RpcUtils.getMethodName(invocation), WEIGHT_KEY);
|
|
||||||
if (StringUtils.isNotEmpty(weight)) {
|
if (StringUtils.isNotEmpty(weight)) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
}
|
||||||
|
} else {
|
||||||
|
String weight = invokerUrl.getMethodParameter(invocation.getMethodName(), WEIGHT_KEY);
|
||||||
|
if (StringUtils.isNotEmpty(weight)) {
|
||||||
|
return true;
|
||||||
|
}else {
|
||||||
String timeStamp = invoker.getUrl().getParameter(TIMESTAMP_KEY);
|
String timeStamp = invoker.getUrl().getParameter(TIMESTAMP_KEY);
|
||||||
return StringUtils.isNotEmpty(timeStamp);
|
if (StringUtils.isNotEmpty(timeStamp)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,8 @@
|
||||||
package org.apache.dubbo.rpc.cluster.loadbalance;
|
package org.apache.dubbo.rpc.cluster.loadbalance;
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
|
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
import org.apache.dubbo.rpc.Invocation;
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
import org.apache.dubbo.rpc.Invoker;
|
||||||
import org.apache.dubbo.rpc.support.RpcUtils;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -37,12 +35,9 @@ public class RoundRobinLoadBalance extends AbstractLoadBalance {
|
||||||
|
|
||||||
private static final int RECYCLE_PERIOD = 60000;
|
private static final int RECYCLE_PERIOD = 60000;
|
||||||
|
|
||||||
private final ConcurrentMap<String, ConcurrentMap<String, WeightedRoundRobin>> methodWeightMap =
|
|
||||||
new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
protected static class WeightedRoundRobin {
|
protected static class WeightedRoundRobin {
|
||||||
private int weight;
|
private int weight;
|
||||||
private final AtomicLong current = new AtomicLong(0);
|
private AtomicLong current = new AtomicLong(0);
|
||||||
private long lastUpdate;
|
private long lastUpdate;
|
||||||
|
|
||||||
public int getWeight() {
|
public int getWeight() {
|
||||||
|
|
@ -71,6 +66,8 @@ public class RoundRobinLoadBalance extends AbstractLoadBalance {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ConcurrentMap<String, ConcurrentMap<String, WeightedRoundRobin>> methodWeightMap = new ConcurrentHashMap<String, ConcurrentMap<String, WeightedRoundRobin>>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get invoker addr list cached for specified invocation
|
* get invoker addr list cached for specified invocation
|
||||||
* <p>
|
* <p>
|
||||||
|
|
@ -81,7 +78,7 @@ public class RoundRobinLoadBalance extends AbstractLoadBalance {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
protected <T> Collection<String> getInvokerAddrList(List<Invoker<T>> invokers, Invocation invocation) {
|
protected <T> Collection<String> getInvokerAddrList(List<Invoker<T>> invokers, Invocation invocation) {
|
||||||
String key = invokers.get(0).getUrl().getServiceKey() + "." + RpcUtils.getMethodName(invocation);
|
String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();
|
||||||
Map<String, WeightedRoundRobin> map = methodWeightMap.get(key);
|
Map<String, WeightedRoundRobin> map = methodWeightMap.get(key);
|
||||||
if (map != null) {
|
if (map != null) {
|
||||||
return map.keySet();
|
return map.keySet();
|
||||||
|
|
@ -91,9 +88,8 @@ public class RoundRobinLoadBalance extends AbstractLoadBalance {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
|
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
|
||||||
String key = invokers.get(0).getUrl().getServiceKey() + "." + RpcUtils.getMethodName(invocation);
|
String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();
|
||||||
ConcurrentMap<String, WeightedRoundRobin> map =
|
ConcurrentMap<String, WeightedRoundRobin> map = methodWeightMap.computeIfAbsent(key, k -> new ConcurrentHashMap<>());
|
||||||
ConcurrentHashMapUtils.computeIfAbsent(methodWeightMap, key, k -> new ConcurrentHashMap<>());
|
|
||||||
int totalWeight = 0;
|
int totalWeight = 0;
|
||||||
long maxCurrent = Long.MIN_VALUE;
|
long maxCurrent = Long.MIN_VALUE;
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
|
|
@ -102,14 +98,14 @@ public class RoundRobinLoadBalance extends AbstractLoadBalance {
|
||||||
for (Invoker<T> invoker : invokers) {
|
for (Invoker<T> invoker : invokers) {
|
||||||
String identifyString = invoker.getUrl().toIdentityString();
|
String identifyString = invoker.getUrl().toIdentityString();
|
||||||
int weight = getWeight(invoker, invocation);
|
int weight = getWeight(invoker, invocation);
|
||||||
WeightedRoundRobin weightedRoundRobin = ConcurrentHashMapUtils.computeIfAbsent(map, identifyString, k -> {
|
WeightedRoundRobin weightedRoundRobin = map.computeIfAbsent(identifyString, k -> {
|
||||||
WeightedRoundRobin wrr = new WeightedRoundRobin();
|
WeightedRoundRobin wrr = new WeightedRoundRobin();
|
||||||
wrr.setWeight(weight);
|
wrr.setWeight(weight);
|
||||||
return wrr;
|
return wrr;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (weight != weightedRoundRobin.getWeight()) {
|
if (weight != weightedRoundRobin.getWeight()) {
|
||||||
// weight changed
|
//weight changed
|
||||||
weightedRoundRobin.setWeight(weight);
|
weightedRoundRobin.setWeight(weight);
|
||||||
}
|
}
|
||||||
long cur = weightedRoundRobin.increaseCurrent();
|
long cur = weightedRoundRobin.increaseCurrent();
|
||||||
|
|
@ -131,4 +127,5 @@ public class RoundRobinLoadBalance extends AbstractLoadBalance {
|
||||||
// should not happen here
|
// should not happen here
|
||||||
return invokers.get(0);
|
return invokers.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,14 +18,12 @@ package org.apache.dubbo.rpc.cluster.loadbalance;
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
|
import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
|
||||||
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
|
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
import org.apache.dubbo.rpc.Invocation;
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
import org.apache.dubbo.rpc.Invoker;
|
||||||
import org.apache.dubbo.rpc.RpcStatus;
|
import org.apache.dubbo.rpc.RpcStatus;
|
||||||
import org.apache.dubbo.rpc.cluster.Constants;
|
import org.apache.dubbo.rpc.cluster.Constants;
|
||||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||||
import org.apache.dubbo.rpc.model.ScopeModelAware;
|
import org.apache.dubbo.rpc.model.ScopeModelAware;
|
||||||
import org.apache.dubbo.rpc.support.RpcUtils;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
@ -49,9 +47,9 @@ public class ShortestResponseLoadBalance extends AbstractLoadBalance implements
|
||||||
|
|
||||||
private int slidePeriod = 30_000;
|
private int slidePeriod = 30_000;
|
||||||
|
|
||||||
private final ConcurrentMap<RpcStatus, SlideWindowData> methodMap = new ConcurrentHashMap<>();
|
private ConcurrentMap<RpcStatus, SlideWindowData> methodMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private final AtomicBoolean onResetSlideWindow = new AtomicBoolean(false);
|
private AtomicBoolean onResetSlideWindow = new AtomicBoolean(false);
|
||||||
|
|
||||||
private volatile long lastUpdateTime = System.currentTimeMillis();
|
private volatile long lastUpdateTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
|
@ -59,22 +57,16 @@ public class ShortestResponseLoadBalance extends AbstractLoadBalance implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setApplicationModel(ApplicationModel applicationModel) {
|
public void setApplicationModel(ApplicationModel applicationModel) {
|
||||||
slidePeriod = applicationModel
|
slidePeriod = applicationModel.getModelEnvironment().getConfiguration().getInt(Constants.SHORTEST_RESPONSE_SLIDE_PERIOD, 30_000);
|
||||||
.modelEnvironment()
|
executorService = applicationModel.getFrameworkModel().getBeanFactory()
|
||||||
.getConfiguration()
|
.getBean(FrameworkExecutorRepository.class).getSharedExecutor();
|
||||||
.getInt(Constants.SHORTEST_RESPONSE_SLIDE_PERIOD, 30_000);
|
|
||||||
executorService = applicationModel
|
|
||||||
.getFrameworkModel()
|
|
||||||
.getBeanFactory()
|
|
||||||
.getBean(FrameworkExecutorRepository.class)
|
|
||||||
.getSharedExecutor();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static class SlideWindowData {
|
protected static class SlideWindowData {
|
||||||
|
|
||||||
private long succeededOffset;
|
private long succeededOffset;
|
||||||
private long succeededElapsedOffset;
|
private long succeededElapsedOffset;
|
||||||
private final RpcStatus rpcStatus;
|
private RpcStatus rpcStatus;
|
||||||
|
|
||||||
public SlideWindowData(RpcStatus rpcStatus) {
|
public SlideWindowData(RpcStatus rpcStatus) {
|
||||||
this.rpcStatus = rpcStatus;
|
this.rpcStatus = rpcStatus;
|
||||||
|
|
@ -123,12 +115,10 @@ public class ShortestResponseLoadBalance extends AbstractLoadBalance implements
|
||||||
// Filter out all the shortest response invokers
|
// Filter out all the shortest response invokers
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
Invoker<T> invoker = invokers.get(i);
|
Invoker<T> invoker = invokers.get(i);
|
||||||
RpcStatus rpcStatus = RpcStatus.getStatus(invoker.getUrl(), RpcUtils.getMethodName(invocation));
|
RpcStatus rpcStatus = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName());
|
||||||
SlideWindowData slideWindowData =
|
SlideWindowData slideWindowData = methodMap.computeIfAbsent(rpcStatus, SlideWindowData::new);
|
||||||
ConcurrentHashMapUtils.computeIfAbsent(methodMap, rpcStatus, SlideWindowData::new);
|
|
||||||
|
|
||||||
// Calculate the estimated response time from the product of active connections and succeeded average
|
// Calculate the estimated response time from the product of active connections and succeeded average elapsed time.
|
||||||
// elapsed time.
|
|
||||||
long estimateResponse = slideWindowData.getEstimateResponse();
|
long estimateResponse = slideWindowData.getEstimateResponse();
|
||||||
int afterWarmup = getWeight(invoker, invocation);
|
int afterWarmup = getWeight(invoker, invocation);
|
||||||
weights[i] = afterWarmup;
|
weights[i] = afterWarmup;
|
||||||
|
|
@ -143,15 +133,16 @@ public class ShortestResponseLoadBalance extends AbstractLoadBalance implements
|
||||||
} else if (estimateResponse == shortestResponse) {
|
} else if (estimateResponse == shortestResponse) {
|
||||||
shortestIndexes[shortestCount++] = i;
|
shortestIndexes[shortestCount++] = i;
|
||||||
totalWeight += afterWarmup;
|
totalWeight += afterWarmup;
|
||||||
if (sameWeight && i > 0 && afterWarmup != firstWeight) {
|
if (sameWeight && i > 0
|
||||||
|
&& afterWarmup != firstWeight) {
|
||||||
sameWeight = false;
|
sameWeight = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (System.currentTimeMillis() - lastUpdateTime > slidePeriod
|
if (System.currentTimeMillis() - lastUpdateTime > slidePeriod
|
||||||
&& onResetSlideWindow.compareAndSet(false, true)) {
|
&& onResetSlideWindow.compareAndSet(false, true)) {
|
||||||
// reset slideWindowData in async way
|
//reset slideWindowData in async way
|
||||||
executorService.execute(() -> {
|
executorService.execute(() -> {
|
||||||
methodMap.values().forEach(SlideWindowData::reset);
|
methodMap.values().forEach(SlideWindowData::reset);
|
||||||
lastUpdateTime = System.currentTimeMillis();
|
lastUpdateTime = System.currentTimeMillis();
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.apache.dubbo.rpc.cluster.merger;
|
package org.apache.dubbo.rpc.cluster.merger;
|
||||||
|
|
||||||
import org.apache.dubbo.common.utils.ArrayUtils;
|
import org.apache.dubbo.common.utils.ArrayUtils;
|
||||||
|
|
@ -42,4 +43,5 @@ public class BooleanArrayMerger implements Merger<boolean[]> {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.apache.dubbo.rpc.cluster.merger;
|
package org.apache.dubbo.rpc.cluster.merger;
|
||||||
|
|
||||||
import org.apache.dubbo.common.utils.ArrayUtils;
|
import org.apache.dubbo.common.utils.ArrayUtils;
|
||||||
|
|
@ -42,4 +43,5 @@ public class ByteArrayMerger implements Merger<byte[]> {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.apache.dubbo.rpc.cluster.merger;
|
package org.apache.dubbo.rpc.cluster.merger;
|
||||||
|
|
||||||
import org.apache.dubbo.common.utils.ArrayUtils;
|
import org.apache.dubbo.common.utils.ArrayUtils;
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.apache.dubbo.rpc.cluster.merger;
|
package org.apache.dubbo.rpc.cluster.merger;
|
||||||
|
|
||||||
import org.apache.dubbo.common.utils.ArrayUtils;
|
import org.apache.dubbo.common.utils.ArrayUtils;
|
||||||
|
|
@ -29,8 +30,7 @@ public class DoubleArrayMerger implements Merger<double[]> {
|
||||||
if (ArrayUtils.isEmpty(items)) {
|
if (ArrayUtils.isEmpty(items)) {
|
||||||
return new double[0];
|
return new double[0];
|
||||||
}
|
}
|
||||||
return Arrays.stream(items)
|
return Arrays.stream(items).filter(Objects::nonNull)
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.flatMapToDouble(Arrays::stream)
|
.flatMapToDouble(Arrays::stream)
|
||||||
.toArray();
|
.toArray();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.apache.dubbo.rpc.cluster.merger;
|
package org.apache.dubbo.rpc.cluster.merger;
|
||||||
|
|
||||||
import org.apache.dubbo.common.utils.ArrayUtils;
|
import org.apache.dubbo.common.utils.ArrayUtils;
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.apache.dubbo.rpc.cluster.merger;
|
package org.apache.dubbo.rpc.cluster.merger;
|
||||||
|
|
||||||
import org.apache.dubbo.common.utils.ArrayUtils;
|
import org.apache.dubbo.common.utils.ArrayUtils;
|
||||||
|
|
@ -29,9 +30,9 @@ public class IntArrayMerger implements Merger<int[]> {
|
||||||
if (ArrayUtils.isEmpty(items)) {
|
if (ArrayUtils.isEmpty(items)) {
|
||||||
return new int[0];
|
return new int[0];
|
||||||
}
|
}
|
||||||
return Arrays.stream(items)
|
return Arrays.stream(items).filter(Objects::nonNull)
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.flatMapToInt(Arrays::stream)
|
.flatMapToInt(Arrays::stream)
|
||||||
.toArray();
|
.toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.apache.dubbo.rpc.cluster.merger;
|
package org.apache.dubbo.rpc.cluster.merger;
|
||||||
|
|
||||||
import org.apache.dubbo.common.utils.ArrayUtils;
|
import org.apache.dubbo.common.utils.ArrayUtils;
|
||||||
|
|
@ -33,9 +34,10 @@ public class ListMerger implements Merger<List<?>> {
|
||||||
if (ArrayUtils.isEmpty(items)) {
|
if (ArrayUtils.isEmpty(items)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
return Stream.of(items)
|
return Stream.of(items).filter(Objects::nonNull)
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.flatMap(Collection::stream)
|
.flatMap(Collection::stream)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.apache.dubbo.rpc.cluster.merger;
|
package org.apache.dubbo.rpc.cluster.merger;
|
||||||
|
|
||||||
import org.apache.dubbo.common.utils.ArrayUtils;
|
import org.apache.dubbo.common.utils.ArrayUtils;
|
||||||
|
|
@ -29,8 +30,7 @@ public class LongArrayMerger implements Merger<long[]> {
|
||||||
if (ArrayUtils.isEmpty(items)) {
|
if (ArrayUtils.isEmpty(items)) {
|
||||||
return new long[0];
|
return new long[0];
|
||||||
}
|
}
|
||||||
return Arrays.stream(items)
|
return Arrays.stream(items).filter(Objects::nonNull)
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.flatMapToLong(Arrays::stream)
|
.flatMapToLong(Arrays::stream)
|
||||||
.toArray();
|
.toArray();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,9 @@ public class MapMerger implements Merger<Map<?, ?>> {
|
||||||
if (ArrayUtils.isEmpty(items)) {
|
if (ArrayUtils.isEmpty(items)) {
|
||||||
return Collections.emptyMap();
|
return Collections.emptyMap();
|
||||||
}
|
}
|
||||||
Map<Object, Object> result = new HashMap<>();
|
Map<Object, Object> result = new HashMap<Object, Object>();
|
||||||
Stream.of(items).filter(Objects::nonNull).forEach(result::putAll);
|
Stream.of(items).filter(Objects::nonNull).forEach(result::putAll);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,10 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.apache.dubbo.rpc.cluster.merger;
|
package org.apache.dubbo.rpc.cluster.merger;
|
||||||
|
|
||||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
import org.apache.dubbo.common.logger.Logger;
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||||
import org.apache.dubbo.common.utils.TypeUtils;
|
import org.apache.dubbo.common.utils.TypeUtils;
|
||||||
|
|
@ -30,13 +31,11 @@ import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_FAILED_LOAD_MERGER;
|
|
||||||
|
|
||||||
public class MergerFactory implements ScopeModelAware {
|
public class MergerFactory implements ScopeModelAware {
|
||||||
|
|
||||||
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(MergerFactory.class);
|
private static final Logger logger = LoggerFactory.getLogger(MergerFactory.class);
|
||||||
|
|
||||||
private ConcurrentMap<Class<?>, Merger<?>> MERGER_CACHE = new ConcurrentHashMap<>();
|
private ConcurrentMap<Class<?>, Merger<?>> MERGER_CACHE = new ConcurrentHashMap<Class<?>, Merger<?>>();
|
||||||
private ScopeModel scopeModel;
|
private ScopeModel scopeModel;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -68,17 +67,13 @@ public class MergerFactory implements ScopeModelAware {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadMergers() {
|
private void loadMergers() {
|
||||||
Set<String> names = scopeModel.getExtensionLoader(Merger.class).getSupportedExtensions();
|
Set<String> names = scopeModel.getExtensionLoader(Merger.class)
|
||||||
|
.getSupportedExtensions();
|
||||||
for (String name : names) {
|
for (String name : names) {
|
||||||
Merger m = scopeModel.getExtensionLoader(Merger.class).getExtension(name);
|
Merger m = scopeModel.getExtensionLoader(Merger.class).getExtension(name);
|
||||||
Class<?> actualTypeArg = getActualTypeArgument(m.getClass());
|
Class<?> actualTypeArg = getActualTypeArgument(m.getClass());
|
||||||
if (actualTypeArg == null) {
|
if (actualTypeArg == null) {
|
||||||
logger.warn(
|
logger.warn("Failed to get actual type argument from merger " + m.getClass().getName());
|
||||||
CLUSTER_FAILED_LOAD_MERGER,
|
|
||||||
"load merger config failed",
|
|
||||||
"",
|
|
||||||
"Failed to get actual type argument from merger "
|
|
||||||
+ m.getClass().getName());
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
MERGER_CACHE.putIfAbsent(actualTypeArg, m);
|
MERGER_CACHE.putIfAbsent(actualTypeArg, m);
|
||||||
|
|
@ -97,7 +92,7 @@ public class MergerFactory implements ScopeModelAware {
|
||||||
ParameterizedType mergerType;
|
ParameterizedType mergerType;
|
||||||
for (Type it : interfaceTypes) {
|
for (Type it : interfaceTypes) {
|
||||||
if (it instanceof ParameterizedType
|
if (it instanceof ParameterizedType
|
||||||
&& (mergerType = ((ParameterizedType) it)).getRawType() == Merger.class) {
|
&& (mergerType = ((ParameterizedType) it)).getRawType() == Merger.class) {
|
||||||
Type typeArg = mergerType.getActualTypeArguments()[0];
|
Type typeArg = mergerType.getActualTypeArguments()[0];
|
||||||
return TypeUtils.getRawClass(typeArg);
|
return TypeUtils.getRawClass(typeArg);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ public class SetMerger implements Merger<Set<?>> {
|
||||||
if (ArrayUtils.isEmpty(items)) {
|
if (ArrayUtils.isEmpty(items)) {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
Set<Object> result = new HashSet<>();
|
Set<Object> result = new HashSet<Object>();
|
||||||
Stream.of(items).filter(Objects::nonNull).forEach(result::addAll);
|
Stream.of(items).filter(Objects::nonNull).forEach(result::addAll);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.apache.dubbo.rpc.cluster.merger;
|
package org.apache.dubbo.rpc.cluster.merger;
|
||||||
|
|
||||||
import org.apache.dubbo.common.utils.ArrayUtils;
|
import org.apache.dubbo.common.utils.ArrayUtils;
|
||||||
|
|
|
||||||
|
|
@ -28,13 +28,12 @@ public abstract class AbstractRouter implements Router {
|
||||||
private GovernanceRuleRepository ruleRepository;
|
private GovernanceRuleRepository ruleRepository;
|
||||||
|
|
||||||
public AbstractRouter(URL url) {
|
public AbstractRouter(URL url) {
|
||||||
this.ruleRepository = url.getOrDefaultModuleModel()
|
this.ruleRepository = url.getOrDefaultModuleModel().getExtensionLoader(GovernanceRuleRepository.class).getDefaultExtension();
|
||||||
.getExtensionLoader(GovernanceRuleRepository.class)
|
|
||||||
.getDefaultExtension();
|
|
||||||
this.url = url;
|
this.url = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractRouter() {}
|
public AbstractRouter() {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URL getUrl() {
|
public URL getUrl() {
|
||||||
|
|
@ -68,7 +67,8 @@ public abstract class AbstractRouter implements Router {
|
||||||
this.priority = priority;
|
this.priority = priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GovernanceRuleRepository getRuleRepository() {
|
public GovernanceRuleRepository getRuleRepository(){
|
||||||
return this.ruleRepository;
|
return this.ruleRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ package org.apache.dubbo.rpc.cluster.router;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.apache.dubbo.rpc.cluster.Constants.CONFIG_VERSION_KEY;
|
|
||||||
import static org.apache.dubbo.rpc.cluster.Constants.DYNAMIC_KEY;
|
import static org.apache.dubbo.rpc.cluster.Constants.DYNAMIC_KEY;
|
||||||
import static org.apache.dubbo.rpc.cluster.Constants.ENABLED_KEY;
|
import static org.apache.dubbo.rpc.cluster.Constants.ENABLED_KEY;
|
||||||
import static org.apache.dubbo.rpc.cluster.Constants.FORCE_KEY;
|
import static org.apache.dubbo.rpc.cluster.Constants.FORCE_KEY;
|
||||||
|
|
@ -41,7 +40,6 @@ public abstract class AbstractRouterRule {
|
||||||
private int priority;
|
private int priority;
|
||||||
private boolean dynamic = false;
|
private boolean dynamic = false;
|
||||||
|
|
||||||
private String version;
|
|
||||||
private String scope;
|
private String scope;
|
||||||
private String key;
|
private String key;
|
||||||
|
|
||||||
|
|
@ -80,7 +78,6 @@ public abstract class AbstractRouterRule {
|
||||||
|
|
||||||
setScope((String) map.get(SCOPE_KEY));
|
setScope((String) map.get(SCOPE_KEY));
|
||||||
setKey((String) map.get(KEY_KEY));
|
setKey((String) map.get(KEY_KEY));
|
||||||
setVersion((String) map.get(CONFIG_VERSION_KEY));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRawRule() {
|
public String getRawRule() {
|
||||||
|
|
@ -154,12 +151,4 @@ public abstract class AbstractRouterRule {
|
||||||
public void setKey(String key) {
|
public void setKey(String key) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getVersion() {
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setVersion(String version) {
|
|
||||||
this.version = version;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
|
||||||
public class RouterSnapshotFilter implements ClusterFilter, BaseFilter.Listener {
|
public class RouterSnapshotFilter implements ClusterFilter, BaseFilter.Listener {
|
||||||
|
|
||||||
private final RouterSnapshotSwitcher switcher;
|
private final RouterSnapshotSwitcher switcher;
|
||||||
private static final Logger logger = LoggerFactory.getLogger(RouterSnapshotFilter.class);
|
private final static Logger logger = LoggerFactory.getLogger(RouterSnapshotFilter.class);
|
||||||
|
|
||||||
public RouterSnapshotFilter(FrameworkModel frameworkModel) {
|
public RouterSnapshotFilter(FrameworkModel frameworkModel) {
|
||||||
this.switcher = frameworkModel.getBeanFactory().getBean(RouterSnapshotSwitcher.class);
|
this.switcher = frameworkModel.getBeanFactory().getBean(RouterSnapshotSwitcher.class);
|
||||||
|
|
|
||||||
|
|
@ -114,55 +114,43 @@ public class RouterSnapshotNode<T> {
|
||||||
|
|
||||||
public String toString(int level) {
|
public String toString(int level) {
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
stringBuilder
|
stringBuilder.append("[ ")
|
||||||
.append("[ ")
|
.append(name)
|
||||||
.append(name)
|
.append(' ')
|
||||||
.append(' ')
|
.append("(Input: ").append(beforeSize).append(") ")
|
||||||
.append("(Input: ")
|
.append("(Current Node Output: ").append(nodeOutputSize).append(") ")
|
||||||
.append(beforeSize)
|
.append("(Chain Node Output: ").append(chainOutputSize).append(')')
|
||||||
.append(") ")
|
.append(routerMessage == null ? "" : " Router message: ")
|
||||||
.append("(Current Node Output: ")
|
.append(routerMessage == null ? "" : routerMessage)
|
||||||
.append(nodeOutputSize)
|
.append(" ] ");
|
||||||
.append(") ")
|
|
||||||
.append("(Chain Node Output: ")
|
|
||||||
.append(chainOutputSize)
|
|
||||||
.append(')')
|
|
||||||
.append(routerMessage == null ? "" : " Router message: ")
|
|
||||||
.append(routerMessage == null ? "" : routerMessage)
|
|
||||||
.append(" ] ");
|
|
||||||
if (level == 1) {
|
if (level == 1) {
|
||||||
stringBuilder
|
stringBuilder.append("Input: ")
|
||||||
.append("Input: ")
|
.append(CollectionUtils.isEmpty(inputInvokers) ? "Empty" :
|
||||||
.append(
|
inputInvokers.subList(0, Math.min(5, inputInvokers.size()))
|
||||||
CollectionUtils.isEmpty(inputInvokers)
|
.stream()
|
||||||
? "Empty"
|
.map(Invoker::getUrl)
|
||||||
: inputInvokers.subList(0, Math.min(5, inputInvokers.size())).stream()
|
.map(URL::getAddress)
|
||||||
.map(Invoker::getUrl)
|
.collect(Collectors.joining(",")))
|
||||||
.map(URL::getAddress)
|
.append(" -> ");
|
||||||
.collect(Collectors.joining(",")))
|
|
||||||
.append(" -> ");
|
|
||||||
|
|
||||||
stringBuilder
|
stringBuilder.append("Chain Node Output: ")
|
||||||
.append("Chain Node Output: ")
|
.append(CollectionUtils.isEmpty(chainOutputInvokers) ? "Empty" :
|
||||||
.append(
|
chainOutputInvokers.subList(0, Math.min(5, chainOutputInvokers.size()))
|
||||||
CollectionUtils.isEmpty(chainOutputInvokers)
|
.stream()
|
||||||
? "Empty"
|
.map(Invoker::getUrl)
|
||||||
: chainOutputInvokers.subList(0, Math.min(5, chainOutputInvokers.size())).stream()
|
.map(URL::getAddress)
|
||||||
.map(Invoker::getUrl)
|
.collect(Collectors.joining(",")));
|
||||||
.map(URL::getAddress)
|
|
||||||
.collect(Collectors.joining(",")));
|
|
||||||
} else {
|
} else {
|
||||||
stringBuilder
|
stringBuilder.append("Current Node Output: ")
|
||||||
.append("Current Node Output: ")
|
.append(CollectionUtils.isEmpty(nodeOutputInvokers) ? "Empty" :
|
||||||
.append(
|
nodeOutputInvokers.subList(0, Math.min(5, nodeOutputInvokers.size()))
|
||||||
CollectionUtils.isEmpty(nodeOutputInvokers)
|
.stream()
|
||||||
? "Empty"
|
.map(Invoker::getUrl)
|
||||||
: nodeOutputInvokers.subList(0, Math.min(5, nodeOutputInvokers.size())).stream()
|
.map(URL::getAddress)
|
||||||
.map(Invoker::getUrl)
|
.collect(Collectors.joining(",")));
|
||||||
.map(URL::getAddress)
|
|
||||||
.collect(Collectors.joining(",")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (nodeOutputInvokers != null && nodeOutputInvokers.size() > 5) {
|
if (nodeOutputInvokers != null && nodeOutputInvokers.size() > 5) {
|
||||||
stringBuilder.append("...");
|
stringBuilder.append("...");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ public class RouterSnapshotSwitcher {
|
||||||
private volatile boolean enable;
|
private volatile boolean enable;
|
||||||
private final Set<String> enabledService = new ConcurrentHashSet<>();
|
private final Set<String> enabledService = new ConcurrentHashSet<>();
|
||||||
|
|
||||||
private static final int MAX_LENGTH = 1 << 5; // 2 ^ 5 = 31
|
private final static int MAX_LENGTH = 1 << 5; // 2 ^ 5 = 31
|
||||||
|
|
||||||
private final AtomicInteger offset = new AtomicInteger(0);
|
private final AtomicInteger offset = new AtomicInteger(0);
|
||||||
private volatile String[] recentSnapshot = new String[MAX_LENGTH];
|
private volatile String[] recentSnapshot = new String[MAX_LENGTH];
|
||||||
|
|
|
||||||
|
|
@ -17,75 +17,62 @@
|
||||||
package org.apache.dubbo.rpc.cluster.router.condition;
|
package org.apache.dubbo.rpc.cluster.router.condition;
|
||||||
|
|
||||||
import org.apache.dubbo.common.URL;
|
import org.apache.dubbo.common.URL;
|
||||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
import org.apache.dubbo.common.logger.Logger;
|
||||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||||
import org.apache.dubbo.common.utils.Holder;
|
import org.apache.dubbo.common.utils.Holder;
|
||||||
import org.apache.dubbo.common.utils.NetUtils;
|
import org.apache.dubbo.common.utils.NetUtils;
|
||||||
import org.apache.dubbo.common.utils.StringUtils;
|
import org.apache.dubbo.common.utils.StringUtils;
|
||||||
|
import org.apache.dubbo.common.utils.UrlUtils;
|
||||||
import org.apache.dubbo.rpc.Invocation;
|
import org.apache.dubbo.rpc.Invocation;
|
||||||
import org.apache.dubbo.rpc.Invoker;
|
import org.apache.dubbo.rpc.Invoker;
|
||||||
import org.apache.dubbo.rpc.RpcException;
|
import org.apache.dubbo.rpc.RpcException;
|
||||||
|
import org.apache.dubbo.rpc.cluster.Constants;
|
||||||
import org.apache.dubbo.rpc.cluster.router.RouterSnapshotNode;
|
import org.apache.dubbo.rpc.cluster.router.RouterSnapshotNode;
|
||||||
import org.apache.dubbo.rpc.cluster.router.condition.matcher.ConditionMatcher;
|
import org.apache.dubbo.rpc.cluster.router.condition.config.AppStateRouter;
|
||||||
import org.apache.dubbo.rpc.cluster.router.condition.matcher.ConditionMatcherFactory;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.condition.matcher.pattern.ValuePattern;
|
|
||||||
import org.apache.dubbo.rpc.cluster.router.state.AbstractStateRouter;
|
import org.apache.dubbo.rpc.cluster.router.state.AbstractStateRouter;
|
||||||
import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
||||||
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY;
|
import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY;
|
||||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_CONDITIONAL_ROUTE_LIST_EMPTY;
|
import static org.apache.dubbo.common.constants.CommonConstants.HOST_KEY;
|
||||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_FAILED_EXEC_CONDITION_ROUTER;
|
import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
|
||||||
|
import static org.apache.dubbo.common.constants.CommonConstants.METHOD_KEY;
|
||||||
|
import static org.apache.dubbo.rpc.cluster.Constants.ADDRESS_KEY;
|
||||||
import static org.apache.dubbo.rpc.cluster.Constants.FORCE_KEY;
|
import static org.apache.dubbo.rpc.cluster.Constants.FORCE_KEY;
|
||||||
import static org.apache.dubbo.rpc.cluster.Constants.RULE_KEY;
|
import static org.apache.dubbo.rpc.cluster.Constants.RULE_KEY;
|
||||||
import static org.apache.dubbo.rpc.cluster.Constants.RUNTIME_KEY;
|
import static org.apache.dubbo.rpc.cluster.Constants.RUNTIME_KEY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Condition Router directs traffics matching the 'when condition' to a particular address subset determined by the 'then condition'.
|
* ConditionRouter
|
||||||
* One typical condition rule is like below, with
|
* It supports the conditional routing configured by "override://", in 2.6.x,
|
||||||
* 1. the 'when condition' on the left side of '=>' contains matching rule like 'method=sayHello' and 'method=sayHi'
|
* refer to https://dubbo.apache.org/en/docs/v2.7/user/examples/routing-rule/ .
|
||||||
* 2. the 'then condition' on the right side of '=>' contains matching rule like 'region=hangzhou' and 'address=*:20881'
|
* For 2.7.x and later, please refer to {@link org.apache.dubbo.rpc.cluster.router.condition.config.ServiceRouter}
|
||||||
* <p>
|
* and {@link AppStateRouter}
|
||||||
* By default, condition router support matching rules like 'foo=bar', 'foo=bar*', 'arguments[0]=bar', 'attachments[foo]=bar', 'attachments[foo]=1~100', etc.
|
* refer to https://dubbo.apache.org/zh/docs/v2.7/user/examples/routing-rule/ .
|
||||||
* It's also very easy to add customized matching rules by extending {@link ConditionMatcherFactory}
|
|
||||||
* and {@link ValuePattern}
|
|
||||||
* <p>
|
|
||||||
* ---
|
|
||||||
* scope: service
|
|
||||||
* force: true
|
|
||||||
* runtime: true
|
|
||||||
* enabled: true
|
|
||||||
* key: org.apache.dubbo.samples.governance.api.DemoService
|
|
||||||
* conditions:
|
|
||||||
* - method=sayHello => region=hangzhou
|
|
||||||
* - method=sayHi => address=*:20881
|
|
||||||
* ...
|
|
||||||
*/
|
*/
|
||||||
public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
|
public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
|
||||||
public static final String NAME = "condition";
|
public static final String NAME = "condition";
|
||||||
|
|
||||||
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(AbstractStateRouter.class);
|
private static final Logger logger = LoggerFactory.getLogger(ConditionStateRouter.class);
|
||||||
protected static final Pattern ROUTE_PATTERN = Pattern.compile("([&!=,]*)\\s*([^&!=,\\s]+)");
|
protected static final Pattern ROUTE_PATTERN = Pattern.compile("([&!=,]*)\\s*([^&!=,\\s]+)");
|
||||||
protected Map<String, ConditionMatcher> whenCondition;
|
protected static Pattern ARGUMENTS_PATTERN = Pattern.compile("arguments\\[([0-9]+)\\]");
|
||||||
protected Map<String, ConditionMatcher> thenCondition;
|
protected Map<String, MatchPair> whenCondition;
|
||||||
protected List<ConditionMatcherFactory> matcherFactories;
|
protected Map<String, MatchPair> thenCondition;
|
||||||
|
|
||||||
private final boolean enabled;
|
private boolean enabled;
|
||||||
|
|
||||||
public ConditionStateRouter(URL url, String rule, boolean force, boolean enabled) {
|
public ConditionStateRouter(URL url, String rule, boolean force, boolean enabled) {
|
||||||
super(url);
|
super(url);
|
||||||
this.setForce(force);
|
this.setForce(force);
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
matcherFactories =
|
|
||||||
moduleModel.getExtensionLoader(ConditionMatcherFactory.class).getActivateExtensions();
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
this.init(rule);
|
this.init(rule);
|
||||||
}
|
}
|
||||||
|
|
@ -95,8 +82,6 @@ public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
|
||||||
super(url);
|
super(url);
|
||||||
this.setUrl(url);
|
this.setUrl(url);
|
||||||
this.setForce(url.getParameter(FORCE_KEY, false));
|
this.setForce(url.getParameter(FORCE_KEY, false));
|
||||||
matcherFactories =
|
|
||||||
moduleModel.getExtensionLoader(ConditionMatcherFactory.class).getActivateExtensions();
|
|
||||||
this.enabled = url.getParameter(ENABLED_KEY, true);
|
this.enabled = url.getParameter(ENABLED_KEY, true);
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
init(url.getParameterAndDecoded(RULE_KEY));
|
init(url.getParameterAndDecoded(RULE_KEY));
|
||||||
|
|
@ -112,10 +97,8 @@ public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
|
||||||
int i = rule.indexOf("=>");
|
int i = rule.indexOf("=>");
|
||||||
String whenRule = i < 0 ? null : rule.substring(0, i).trim();
|
String whenRule = i < 0 ? null : rule.substring(0, i).trim();
|
||||||
String thenRule = i < 0 ? rule.trim() : rule.substring(i + 2).trim();
|
String thenRule = i < 0 ? rule.trim() : rule.substring(i + 2).trim();
|
||||||
Map<String, ConditionMatcher> when =
|
Map<String, MatchPair> when = StringUtils.isBlank(whenRule) || "true".equals(whenRule) ? new HashMap<String, MatchPair>() : parseRule(whenRule);
|
||||||
StringUtils.isBlank(whenRule) || "true".equals(whenRule) ? new HashMap<>() : parseRule(whenRule);
|
Map<String, MatchPair> then = StringUtils.isBlank(thenRule) || "false".equals(thenRule) ? null : parseRule(thenRule);
|
||||||
Map<String, ConditionMatcher> then =
|
|
||||||
StringUtils.isBlank(thenRule) || "false".equals(thenRule) ? null : parseRule(thenRule);
|
|
||||||
// NOTE: It should be determined on the business level whether the `When condition` can be empty or not.
|
// NOTE: It should be determined on the business level whether the `When condition` can be empty or not.
|
||||||
this.whenCondition = when;
|
this.whenCondition = when;
|
||||||
this.thenCondition = then;
|
this.thenCondition = then;
|
||||||
|
|
@ -124,13 +107,14 @@ public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, ConditionMatcher> parseRule(String rule) throws ParseException {
|
private static Map<String, MatchPair> parseRule(String rule)
|
||||||
Map<String, ConditionMatcher> condition = new HashMap<>();
|
throws ParseException {
|
||||||
|
Map<String, MatchPair> condition = new HashMap<String, MatchPair>();
|
||||||
if (StringUtils.isBlank(rule)) {
|
if (StringUtils.isBlank(rule)) {
|
||||||
return condition;
|
return condition;
|
||||||
}
|
}
|
||||||
// Key-Value pair, stores both match and mismatch conditions
|
// Key-Value pair, stores both match and mismatch conditions
|
||||||
ConditionMatcher matcherPair = null;
|
MatchPair pair = null;
|
||||||
// Multiple values
|
// Multiple values
|
||||||
Set<String> values = null;
|
Set<String> values = null;
|
||||||
final Matcher matcher = ROUTE_PATTERN.matcher(rule);
|
final Matcher matcher = ROUTE_PATTERN.matcher(rule);
|
||||||
|
|
@ -139,77 +123,64 @@ public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
|
||||||
String content = matcher.group(2);
|
String content = matcher.group(2);
|
||||||
// Start part of the condition expression.
|
// Start part of the condition expression.
|
||||||
if (StringUtils.isEmpty(separator)) {
|
if (StringUtils.isEmpty(separator)) {
|
||||||
matcherPair = this.getMatcher(content);
|
pair = new MatchPair();
|
||||||
condition.put(content, matcherPair);
|
condition.put(content, pair);
|
||||||
}
|
}
|
||||||
// The KV part of the condition expression
|
// The KV part of the condition expression
|
||||||
else if ("&".equals(separator)) {
|
else if ("&".equals(separator)) {
|
||||||
if (condition.get(content) == null) {
|
if (condition.get(content) == null) {
|
||||||
matcherPair = this.getMatcher(content);
|
pair = new MatchPair();
|
||||||
condition.put(content, matcherPair);
|
condition.put(content, pair);
|
||||||
} else {
|
} else {
|
||||||
matcherPair = condition.get(content);
|
pair = condition.get(content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// The Value in the KV part.
|
// The Value in the KV part.
|
||||||
else if ("=".equals(separator)) {
|
else if ("=".equals(separator)) {
|
||||||
if (matcherPair == null) {
|
if (pair == null) {
|
||||||
throw new ParseException(
|
throw new ParseException("Illegal route rule \""
|
||||||
"Illegal route rule \""
|
+ rule + "\", The error char '" + separator
|
||||||
+ rule + "\", The error char '" + separator
|
+ "' at index " + matcher.start() + " before \""
|
||||||
+ "' at index " + matcher.start() + " before \""
|
+ content + "\".", matcher.start());
|
||||||
+ content + "\".",
|
|
||||||
matcher.start());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
values = matcherPair.getMatches();
|
values = pair.matches;
|
||||||
values.add(content);
|
values.add(content);
|
||||||
}
|
}
|
||||||
// The Value in the KV part.
|
// The Value in the KV part.
|
||||||
else if ("!=".equals(separator)) {
|
else if ("!=".equals(separator)) {
|
||||||
if (matcherPair == null) {
|
if (pair == null) {
|
||||||
throw new ParseException(
|
throw new ParseException("Illegal route rule \""
|
||||||
"Illegal route rule \""
|
+ rule + "\", The error char '" + separator
|
||||||
+ rule + "\", The error char '" + separator
|
+ "' at index " + matcher.start() + " before \""
|
||||||
+ "' at index " + matcher.start() + " before \""
|
+ content + "\".", matcher.start());
|
||||||
+ content + "\".",
|
|
||||||
matcher.start());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
values = matcherPair.getMismatches();
|
values = pair.mismatches;
|
||||||
values.add(content);
|
values.add(content);
|
||||||
}
|
}
|
||||||
// The Value in the KV part, if Value have more than one items.
|
// The Value in the KV part, if Value have more than one items.
|
||||||
else if (",".equals(separator)) { // Should be separated by ','
|
else if (",".equals(separator)) { // Should be separated by ','
|
||||||
if (values == null || values.isEmpty()) {
|
if (values == null || values.isEmpty()) {
|
||||||
throw new ParseException(
|
throw new ParseException("Illegal route rule \""
|
||||||
"Illegal route rule \""
|
+ rule + "\", The error char '" + separator
|
||||||
+ rule + "\", The error char '" + separator
|
+ "' at index " + matcher.start() + " before \""
|
||||||
+ "' at index " + matcher.start() + " before \""
|
+ content + "\".", matcher.start());
|
||||||
+ content + "\".",
|
|
||||||
matcher.start());
|
|
||||||
}
|
}
|
||||||
values.add(content);
|
values.add(content);
|
||||||
} else {
|
} else {
|
||||||
throw new ParseException(
|
throw new ParseException("Illegal route rule \"" + rule
|
||||||
"Illegal route rule \"" + rule
|
+ "\", The error char '" + separator + "' at index "
|
||||||
+ "\", The error char '" + separator + "' at index "
|
+ matcher.start() + " before \"" + content + "\".", matcher.start());
|
||||||
+ matcher.start() + " before \"" + content + "\".",
|
|
||||||
matcher.start());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return condition;
|
return condition;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected BitList<Invoker<T>> doRoute(
|
protected BitList<Invoker<T>> doRoute(BitList<Invoker<T>> invokers, URL url, Invocation invocation,
|
||||||
BitList<Invoker<T>> invokers,
|
boolean needToPrintMessage, Holder<RouterSnapshotNode<T>> nodeHolder,
|
||||||
URL url,
|
Holder<String> messageHolder) throws RpcException {
|
||||||
Invocation invocation,
|
|
||||||
boolean needToPrintMessage,
|
|
||||||
Holder<RouterSnapshotNode<T>> nodeHolder,
|
|
||||||
Holder<String> messageHolder)
|
|
||||||
throws RpcException {
|
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
if (needToPrintMessage) {
|
if (needToPrintMessage) {
|
||||||
messageHolder.set("Directly return. Reason: ConditionRouter disabled.");
|
messageHolder.set("Directly return. Reason: ConditionRouter disabled.");
|
||||||
|
|
@ -231,12 +202,7 @@ public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
|
||||||
return invokers;
|
return invokers;
|
||||||
}
|
}
|
||||||
if (thenCondition == null) {
|
if (thenCondition == null) {
|
||||||
logger.warn(
|
logger.warn("The current consumer in the service blacklist. consumer: " + NetUtils.getLocalHost() + ", service: " + url.getServiceKey());
|
||||||
CLUSTER_CONDITIONAL_ROUTE_LIST_EMPTY,
|
|
||||||
"condition state router thenCondition is empty",
|
|
||||||
"",
|
|
||||||
"The current consumer in the service blocklist. consumer: " + NetUtils.getLocalHost()
|
|
||||||
+ ", service: " + url.getServiceKey());
|
|
||||||
if (needToPrintMessage) {
|
if (needToPrintMessage) {
|
||||||
messageHolder.set("Empty return. Reason: ThenCondition is empty.");
|
messageHolder.set("Empty return. Reason: ThenCondition is empty.");
|
||||||
}
|
}
|
||||||
|
|
@ -251,26 +217,15 @@ public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} else if (this.isForce()) {
|
} else if (this.isForce()) {
|
||||||
logger.warn(
|
logger.warn("The route result is empty and force execute. consumer: " + NetUtils.getLocalHost() + ", service: " + url.getServiceKey() + ", router: " + url.getParameterAndDecoded(RULE_KEY));
|
||||||
CLUSTER_CONDITIONAL_ROUTE_LIST_EMPTY,
|
|
||||||
"execute condition state router result list is empty. and force=true",
|
|
||||||
"",
|
|
||||||
"The route result is empty and force execute. consumer: " + NetUtils.getLocalHost()
|
|
||||||
+ ", service: " + url.getServiceKey() + ", router: "
|
|
||||||
+ url.getParameterAndDecoded(RULE_KEY));
|
|
||||||
if (needToPrintMessage) {
|
if (needToPrintMessage) {
|
||||||
messageHolder.set("Empty return. Reason: Empty result from condition and condition is force.");
|
messageHolder.set("Empty return. Reason: Empty result from condition and condition is force.");
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
logger.error(
|
logger.error("Failed to execute condition router rule: " + getUrl() + ", invokers: " + invokers + ", cause: " + t.getMessage(), t);
|
||||||
CLUSTER_FAILED_EXEC_CONDITION_ROUTER,
|
|
||||||
"execute condition state router exception",
|
|
||||||
"",
|
|
||||||
"Failed to execute condition router rule: " + getUrl() + ", invokers: " + invokers + ", cause: "
|
|
||||||
+ t.getMessage(),
|
|
||||||
t);
|
|
||||||
}
|
}
|
||||||
if (needToPrintMessage) {
|
if (needToPrintMessage) {
|
||||||
messageHolder.set("Directly return. Reason: Error occurred ( or result is empty ).");
|
messageHolder.set("Directly return. Reason: Error occurred ( or result is empty ).");
|
||||||
|
|
@ -281,51 +236,139 @@ public class ConditionStateRouter<T> extends AbstractStateRouter<T> {
|
||||||
@Override
|
@Override
|
||||||
public boolean isRuntime() {
|
public boolean isRuntime() {
|
||||||
// We always return true for previously defined Router, that is, old Router doesn't support cache anymore.
|
// We always return true for previously defined Router, that is, old Router doesn't support cache anymore.
|
||||||
// return true;
|
// return true;
|
||||||
return this.getUrl().getParameter(RUNTIME_KEY, false);
|
return this.getUrl().getParameter(RUNTIME_KEY, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConditionMatcher getMatcher(String key) {
|
|
||||||
for (ConditionMatcherFactory factory : matcherFactories) {
|
|
||||||
if (factory.shouldMatch(key)) {
|
|
||||||
return factory.createMatcher(key, moduleModel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return moduleModel
|
|
||||||
.getExtensionLoader(ConditionMatcherFactory.class)
|
|
||||||
.getExtension("param")
|
|
||||||
.createMatcher(key, moduleModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean matchWhen(URL url, Invocation invocation) {
|
boolean matchWhen(URL url, Invocation invocation) {
|
||||||
if (CollectionUtils.isEmptyMap(whenCondition)) {
|
return CollectionUtils.isEmptyMap(whenCondition) || matchCondition(whenCondition, url, null, invocation);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return doMatch(url, null, invocation, whenCondition, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean matchThen(URL url, URL param) {
|
private boolean matchThen(URL url, URL param) {
|
||||||
if (CollectionUtils.isEmptyMap(thenCondition)) {
|
return CollectionUtils.isNotEmptyMap(thenCondition) && matchCondition(thenCondition, url, param, null);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return doMatch(url, param, null, thenCondition, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean doMatch(
|
private boolean matchCondition(Map<String, MatchPair> condition, URL url, URL param, Invocation invocation) {
|
||||||
URL url,
|
Map<String, String> sample = url.toMap();
|
||||||
URL param,
|
boolean result = false;
|
||||||
Invocation invocation,
|
for (Map.Entry<String, MatchPair> matchPair : condition.entrySet()) {
|
||||||
Map<String, ConditionMatcher> conditions,
|
String key = matchPair.getKey();
|
||||||
boolean isWhenCondition) {
|
|
||||||
Map<String, String> sample = url.toOriginalMap();
|
if (key.startsWith(Constants.ARGUMENTS)) {
|
||||||
for (Map.Entry<String, ConditionMatcher> entry : conditions.entrySet()) {
|
if (!matchArguments(matchPair, invocation)) {
|
||||||
ConditionMatcher matchPair = entry.getValue();
|
return false;
|
||||||
if (!matchPair.isMatch(sample, param, invocation, isWhenCondition)) {
|
} else {
|
||||||
return false;
|
result = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String sampleValue;
|
||||||
|
//get real invoked method name from invocation
|
||||||
|
if (invocation != null && (METHOD_KEY.equals(key) || METHODS_KEY.equals(key))) {
|
||||||
|
sampleValue = invocation.getMethodName();
|
||||||
|
} else if (ADDRESS_KEY.equals(key)) {
|
||||||
|
sampleValue = url.getAddress();
|
||||||
|
} else if (HOST_KEY.equals(key)) {
|
||||||
|
sampleValue = url.getHost();
|
||||||
|
} else {
|
||||||
|
sampleValue = sample.get(key);
|
||||||
|
}
|
||||||
|
if (sampleValue != null) {
|
||||||
|
if (!matchPair.getValue().isMatch(sampleValue, param)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//not pass the condition
|
||||||
|
if (!matchPair.getValue().matches.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* analysis the arguments in the rule.
|
||||||
|
* Examples would be like this:
|
||||||
|
* "arguments[0]=1", whenCondition is that the first argument is equal to '1'.
|
||||||
|
* "arguments[1]=a", whenCondition is that the second argument is equal to 'a'.
|
||||||
|
* @param matchPair
|
||||||
|
* @param invocation
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean matchArguments(Map.Entry<String, MatchPair> matchPair, Invocation invocation) {
|
||||||
|
try {
|
||||||
|
// split the rule
|
||||||
|
String key = matchPair.getKey();
|
||||||
|
String[] expressArray = key.split("\\.");
|
||||||
|
String argumentExpress = expressArray[0];
|
||||||
|
final Matcher matcher = ARGUMENTS_PATTERN.matcher(argumentExpress);
|
||||||
|
if (!matcher.find()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//extract the argument index
|
||||||
|
int index = Integer.parseInt(matcher.group(1));
|
||||||
|
if (index < 0 || index > invocation.getArguments().length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//extract the argument value
|
||||||
|
Object object = invocation.getArguments()[index];
|
||||||
|
|
||||||
|
if (matchPair.getValue().isMatch(String.valueOf(object), null)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn("Arguments match failed, matchPair[]" + matchPair + "] invocation[" + invocation + "]", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static final class MatchPair {
|
||||||
|
final Set<String> matches = new HashSet<String>();
|
||||||
|
final Set<String> mismatches = new HashSet<String>();
|
||||||
|
|
||||||
|
private boolean isMatch(String value, URL param) {
|
||||||
|
if (!matches.isEmpty() && mismatches.isEmpty()) {
|
||||||
|
for (String match : matches) {
|
||||||
|
if (UrlUtils.isMatchGlobPattern(match, value, param)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mismatches.isEmpty() && matches.isEmpty()) {
|
||||||
|
for (String mismatch : mismatches) {
|
||||||
|
if (UrlUtils.isMatchGlobPattern(mismatch, value, param)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!matches.isEmpty() && !mismatches.isEmpty()) {
|
||||||
|
//when both mismatches and matches contain the same value, then using mismatches first
|
||||||
|
for (String mismatch : mismatches) {
|
||||||
|
if (UrlUtils.isMatchGlobPattern(mismatch, value, param)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (String match : matches) {
|
||||||
|
if (UrlUtils.isMatchGlobPattern(match, value, param)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,6 @@ public class ConditionStateRouterFactory extends CacheableStateRouterFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected <T> StateRouter<T> createRouter(Class<T> interfaceClass, URL url) {
|
protected <T> StateRouter<T> createRouter(Class<T> interfaceClass, URL url) {
|
||||||
return new ConditionStateRouter<>(url);
|
return new ConditionStateRouter<T>(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue