Compare commits
No commits in common. "dubbo-2.0.10" and "3.2" have entirely different histories.
dubbo-2.0.
...
3.2
|
|
@ -0,0 +1,117 @@
|
|||
# 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
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
#
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#
|
||||
|
||||
notifications:
|
||||
commits: commits@dubbo.apache.org
|
||||
issues: notifications@dubbo.apache.org
|
||||
pullrequests: notifications@dubbo.apache.org
|
||||
jira_options: link label link label
|
||||
|
||||
github:
|
||||
homepage: https://dubbo.apache.org/
|
||||
description: "The java implementation of Apache Dubbo. An RPC and microservice framework."
|
||||
features:
|
||||
# Enable wiki for documentation
|
||||
wiki: true
|
||||
# Enable issue management
|
||||
issues: true
|
||||
# Enable projects for project management boards
|
||||
projects: true
|
||||
protected_branches:
|
||||
master:
|
||||
# only disable force push
|
||||
foo: bar
|
||||
3.0:
|
||||
# only disable force push
|
||||
foo: bar
|
||||
3.1:
|
||||
# only disable force push
|
||||
foo: bar
|
||||
labels:
|
||||
- java
|
||||
- rpc
|
||||
- microservices
|
||||
- framework
|
||||
- restful
|
||||
- distributed-systems
|
||||
- dubbo
|
||||
- service-mesh
|
||||
- http
|
||||
- grpc
|
||||
- web
|
||||
collaborators:
|
||||
- oxsean
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
# 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.
|
||||
#
|
||||
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
tab_width = 4
|
||||
max_line_length = 120
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.java]
|
||||
ij_java_continuation_indent_size = 8
|
||||
ij_java_keep_control_statement_in_one_line = false
|
||||
ij_java_for_brace_force = always
|
||||
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
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
# 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.
|
||||
#
|
||||
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
|
||||
*.java text eol=lf
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
#
|
||||
# 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!"
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
#
|
||||
# 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!"
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
#
|
||||
# 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!"
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
#
|
||||
# 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,22 @@
|
|||
#
|
||||
# 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:
|
||||
- name: Question & FAQ & Proposal
|
||||
url: https://github.com/apache/dubbo/discussions/
|
||||
about: Ask a question, request support or submit a proposal for Apache Dubbo.
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
## What is the purpose of the change
|
||||
|
||||
|
||||
|
||||
## Brief changelog
|
||||
|
||||
|
||||
## Verifying this change
|
||||
|
||||
|
||||
<!-- Follow this checklist to help us incorporate your contribution quickly and easily: -->
|
||||
|
||||
## Checklist
|
||||
- [x] Make sure there is a [GitHub_issue](https://github.com/apache/dubbo/issues) field for the change (usually before you start working on it). Trivial changes like typos do not require a GitHub issue. Your pull request should address just this issue, without pulling in other changes - one PR resolves one issue.
|
||||
- [ ] Each commit in the pull request should have a meaningful subject line and body.
|
||||
- [ ] Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
|
||||
- [ ] Check if is necessary to patch to Dubbo 3 if you are work on Dubbo 2.7
|
||||
- [ ] Write necessary unit-test to verify your logic correction, more mock a little better when cross module dependency exist. If the new feature or significant change is committed, please remember to add sample in [dubbo samples](https://github.com/apache/dubbo-samples) project.
|
||||
- [ ] Add some description to [dubbo-website](https://github.com/apache/dubbo-website) project if you are requesting to add a feature.
|
||||
- [ ] GitHub Actions works fine on your own branch.
|
||||
- [ ] If this contribution is large, please follow the [Software Donation Guide](https://github.com/apache/dubbo/wiki/Software-donation-guide).
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
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,604 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,502 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,502 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,502 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,497 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
# maven ignore
|
||||
target/
|
||||
*.jar
|
||||
*.war
|
||||
*.zip
|
||||
*.tar
|
||||
*.tar.gz
|
||||
.flattened-pom.xml
|
||||
|
||||
# eclipse ignore
|
||||
.settings/
|
||||
.project
|
||||
.classpath
|
||||
.externalToolBuilders
|
||||
maven-eclipse.xml
|
||||
|
||||
# idea ignore
|
||||
.idea/
|
||||
*.ipr
|
||||
*.iml
|
||||
*.iws
|
||||
|
||||
# visual-studio-code ignore
|
||||
.vscode/
|
||||
|
||||
# temp ignore
|
||||
*.log
|
||||
*.cache
|
||||
*.diff
|
||||
*.patch
|
||||
*.tmp
|
||||
|
||||
# system ignore
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
*.orig
|
||||
|
||||
# license check result
|
||||
license-list
|
||||
|
||||
# grpc compiler
|
||||
compiler/gradle.properties
|
||||
compiler/build/*
|
||||
compiler/.gradle/*
|
||||
|
||||
# protobuf
|
||||
dubbo-serialization/dubbo-serialization-protobuf/build/*
|
||||
dubbo-demo/dubbo-demo-triple/build/*
|
||||
|
||||
# global registry center
|
||||
.tmp
|
||||
|
||||
.git.exec.error
|
||||
|
||||
# log files generated by testcase.
|
||||
dubbo-rpc/dubbo-rpc-api/custom-access.log*
|
||||
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# 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
|
||||
#
|
||||
# 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,513 @@
|
|||
# Release Notes
|
||||
|
||||
Please refer to https://github.com/apache/dubbo/releases for notes of future releases.
|
||||
|
||||
## 2.7.6
|
||||
|
||||
### Features
|
||||
* Support Service Authentication https://github.com/apache/dubbo/issues/5461
|
||||
|
||||
### Enhancement
|
||||
* Removing the internal JDK API from FileSystemDynamicConfiguration
|
||||
* Refactor the APT test-cases implementation of dubbo-metadata-processor in Java 9+
|
||||
* Remove feature envy
|
||||
* JsonRpcProtocol support Generalization
|
||||
* Reduce object allocation for ProtocolUtils.serviceKey
|
||||
* Reduce object allocation for ContextFilter.invoke
|
||||
|
||||
### Bugfixes
|
||||
* Fixed bugs reported from 2.7.5 or lower versions, check [2.7.6 milestone](https://github.com/apache/dubbo/milestone/30) for details.
|
||||
|
||||
### Compatibility
|
||||
1. Filter refactor, the callback method `onResponse` annotated as @Deprecated has been removed, users of lower versions that
|
||||
have extended Filter implementations and enabled Filter callbacks should be careful of this change.
|
||||
2. RpcContext added some experimental APIs to support generic Object transmission.
|
||||
|
||||
## 2.7.5
|
||||
|
||||
### Features
|
||||
* Support HTTP/2 through gRPC, offers all features supported by HTTP/2 and gRPC
|
||||
* Stream communication: client stream, server stream and bi-stream.
|
||||
* Reactive stream style RPC call.
|
||||
* Back pressure based on HTTP/2 flow-control mechanism.
|
||||
* TLS secure transport layer.
|
||||
* Define service using IDL
|
||||
* Protobuf support for native Dubbo
|
||||
* Define service using IDL
|
||||
* Protobuf serialization
|
||||
* TLS for netty4 server
|
||||
* New SPI for dynamically adding extra parameters into provider URL, especially env parameters.
|
||||
* **[BETA]** Brand new Service Discovery mechanism: Service Reflection - instance (application) level service discovery.
|
||||
* **[BETA]** Brand new API for bootstraping Dubbo projects
|
||||
|
||||
### Performance Tuning
|
||||
* Overall performance improved by nearly 30% compared to v2.7.3 (by QPS in certain circumstances)
|
||||
* Improved consumer side thread model to avoid thread allocation and context switch, especially useful for services serving big traffic.
|
||||
|
||||
### Enhancement
|
||||
* Load balance strategy among multiple registries:
|
||||
* Preferred
|
||||
* Same zone first
|
||||
* Weighted LB
|
||||
* The first one available
|
||||
* New callback SPI for receiving address change notifications
|
||||
* Refactoring of config module
|
||||
|
||||
### Bugfixes
|
||||
check 2.7.5 milestone for details.
|
||||
|
||||
## 2.7.4.1
|
||||
|
||||
### Enhancement
|
||||
|
||||
* Enhance ProtobufTypeBuilder support generate type definition which contains Bytes List or Bytes Map. #5083
|
||||
* Using the ID of Dubbo Config as the alias of Bean. #5094
|
||||
* tag router supports anyhost. #4431
|
||||
* optimize generic invoke. #4076
|
||||
* dubbo zookeeper registry too slow #4828
|
||||
* use consul with group and version. #4755
|
||||
* qos support host config. #4720
|
||||
* migrate http protocol #4781
|
||||
* Some unit test optimization. #5026 #4803 #4687
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Apollo namespace optimization. #5105
|
||||
* Simplify dubbo-common transitive dependencies. #5107
|
||||
* Delete 'config.' prefix for url generated from ConfigCenterConfig. #5001
|
||||
* fix set generic method error. #5079
|
||||
* Add support for overriding Map properties in AbstractConfig.refresh. #4882
|
||||
* Fix travis javax.ex dependency issue. (unit test)
|
||||
* Fix: ExtensionLoader load duplicate filter,no log or exception. #4340
|
||||
* When the provider interrupts abnormally, the consumer cannot return quickly and still waits for the timeout to end. #4694
|
||||
* Fix register config not take effect because of url simplified。 #4397
|
||||
* Don't support metadata for generic service. #4641
|
||||
* Avoid resize in ClassUtils.java. #5009
|
||||
* default attribute in <dubbo:registry> doesn't work as expected. #4412
|
||||
* make RegistryDirectory can refresh the invokers when providers number become 0 when using nacos registry. #4793
|
||||
* Multiple @Reference annotations only have one effect #4674
|
||||
* Fix RpcContext.getContext().getRemoteApplicationName() returns null #4351
|
||||
* Security issue: upgrade fastjson version to 1.2.60. #5018
|
||||
* nacos-registry:serviceName split error #4974
|
||||
* AbstractConfig.java-getMetaData set default depend on getmethod sequence #4678
|
||||
* fix protocol register set false not work. #4776
|
||||
* Fix: In Rest protocol, the limitation of Dubbo-Attachments. #4898
|
||||
* The logic of org.apache.dubbo.config.MonitorConfig#isValid is incorrect #4892
|
||||
* protostuff return stackoverflow and other error msg #4861
|
||||
* fix method parameter bean generation. #3796
|
||||
* replace hardcode with regex pattern #4810
|
||||
* Fix warm up issue when provider's timestamp is bigger than local machine's timestamp. #4870
|
||||
* Fix use generic invocation via API , lost #4238 ion" value #4784
|
||||
* In consumer side the app cannot catch the exception from provider that is configured serialization="kryo". #4238
|
||||
* fix StringUtils#isBlank #4725
|
||||
* 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 #
|
||||
* add Thread ContextClassLoader #4712
|
||||
* Fix judgment ipv4 address #4729
|
||||
* The compilation of static methods should be excluded when generating the proxy. #4647
|
||||
* check EOF of inputstream in IOUtils.write #4648
|
||||
|
||||
|
||||
## 2.7.3
|
||||
|
||||
### Change List
|
||||
|
||||
1. Asynchronous support
|
||||
* Unified asynchronous and synchronous callback process, exception scenario triggers onError callback, #4401
|
||||
* Performance degradation caused by CompletableFuture.get() in JDK1.8 environment, #4279
|
||||
|
||||
2. Configuration Center
|
||||
* ConfigCenter custom namespace does not take effect, #4411
|
||||
* Unify the models implemented by several configuration centers such as Zookeeper, Nacos, and Etcd. Please refer to the description for possible incompatibility issues, #4388
|
||||
* Adjust Override Coverage Rule Center Priority: Service Level > Application Level, #4175
|
||||
|
||||
3. 2.6.x compatibility
|
||||
* Support Zipkin tracing feature provided by Zipkin officially, #3728, #4471
|
||||
* DubboComponentScan supports simultaneous scanning of annotations under the `com.alibaba.*` and `org.apache.*` packages, #4330
|
||||
|
||||
4. The Nacos Registration Center only subscribes to the address list and no longer subscribes to configuration information, #4454.
|
||||
|
||||
5. Support to read the environment configuration from the specified location, which can be specified by -D or OS VARIABLE. Please refer to [automatically loading environment variables](http://dubbo.apache.org/en-us/docs/user/configuration/environment-variables.html)
|
||||
|
||||
6. Fix consumer cannot downgrade to providers with no tags when there's no tagged providers can match, #4525
|
||||
|
||||
7. Some other bugfixes, #4346 #4338 #4349 #4377
|
||||
|
||||
### Change List
|
||||
|
||||
1. 异步支持相关
|
||||
|
||||
- 统一异步和同步的回调流程,异常场景触发onError回调 #4401
|
||||
- CompletableFuture.get()在JDK1.8环境下带来的性能下降问题 #4279
|
||||
|
||||
2. 配置中心相关
|
||||
|
||||
- ConfigCenter自定义namespace不生效的问题 #4411
|
||||
- 统一Zookeeper、Nacos、Etcd等几个配置中心实现的模型,可能带来的不兼容性问题请参见说明。相关修改:#4388
|
||||
- 调整Override覆盖规则中心优先级:服务级别 > 应用级别 #4175
|
||||
|
||||
3. 2.6.x兼容性
|
||||
|
||||
- 兼容zipkin官方提供的基于Dubbo-2.6 API的集成 #3728, #4471
|
||||
- DubboComponentScan支持同时扫描 `com.alibaba.*` 和 `org.apache.*` 两个包下的注解 #4330
|
||||
|
||||
4. Nacos注册中心只订阅地址列表,不再订阅配置信息 #4454
|
||||
|
||||
5. 支持从指定位置读取环境配置,可通过-D或OS VARIABLE指定,具体请参见[使用说明](http://dubbo.apache.org/zh-cn/docs/user/configuration/environment-variables.html)
|
||||
|
||||
6. 标签路由在消费端使用静态打标方式时,无法实现自动降级以消费无标签提供者 #4525
|
||||
|
||||
7. 其他一些bugfix,#4346 #4338 #4349 #4377
|
||||
|
||||
## 2.7.2
|
||||
|
||||
### New Features
|
||||
|
||||
- nacos config center / metadata center support. [#3846](https://github.com/apache/dubbo/issues/3846)
|
||||
- Etcd support as config center and metadata center [#3653](https://github.com/apache/dubbo/issues/3653)
|
||||
- Support Redis cluster in Metadata Report. [#3817](https://github.com/apache/dubbo/issues/3817)
|
||||
- add new module for Dubbo Event. [#4096](https://github.com/apache/dubbo/issues/4096)
|
||||
- Support multiple registry that including some effective registry, such as zk, redis [#3599](https://github.com/apache/dubbo/issues/3599)
|
||||
- support nacos metadata [#4025](https://github.com/apache/dubbo/issues/4025)
|
||||
- Dubbo support Google Protobuf generic reference [#3829](https://github.com/apache/dubbo/issues/3829)
|
||||
- Merge serialization-native-hessian-for-apache-dubbo into incubator-dubbo [#3961](https://github.com/apache/dubbo/issues/3961)
|
||||
- Merge rpc-native-thrift-for-apache-dubbo into incubator-dubbo [#3960](https://github.com/apache/dubbo/issues/3960)
|
||||
- add socks5 proxy support [#3624](https://github.com/apache/dubbo/issues/3624)
|
||||
- Integrate with SOFARegistry [#3874](https://github.com/apache/dubbo/issues/3874)
|
||||
- Introduce CompletableFuture $invokeAsync for GenericService, now, for generic call, you can use:
|
||||
$invoke for sync method call with normal return type.
|
||||
$invokeAsync for async method call with CompletableFuture<T> signature. [#3163](https://github.com/apache/dubbo/issues/3163)
|
||||
|
||||
### Enhancement
|
||||
|
||||
- Performance tuning for TimeoutTask in DefaultFuture. [#4129](https://github.com/apache/dubbo/issues/4129)
|
||||
- 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)
|
||||
- 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)
|
||||
- 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)
|
||||
- remove useless module-dubbo-test-integration [#3573](https://github.com/apache/dubbo/issues/3573)
|
||||
- complete lookup method of consul registry and add integration test [#3890](https://github.com/apache/dubbo/issues/3890)
|
||||
- Metrics Service [#3702](https://github.com/apache/dubbo/issues/3702)
|
||||
- Update nacos-client to 1.0.0 [#3804](https://github.com/apache/dubbo/issues/3804)
|
||||
- Fluent style builder API support [#3431](https://github.com/apache/dubbo/issues/3431)
|
||||
- Update readme to remove the incubator prefix [#4159](https://github.com/apache/dubbo/issues/4159)
|
||||
- update erlang link [#4100](https://github.com/apache/dubbo/issues/4100)
|
||||
- optimize array code style [#4031](https://github.com/apache/dubbo/issues/4031)
|
||||
- optimize some code style [#4006](https://github.com/apache/dubbo/issues/4006)
|
||||
- remove useless module-dubbo-test-integration [#3989](https://github.com/apache/dubbo/issues/3989)
|
||||
- optimize constant naming style [#3970](https://github.com/apache/dubbo/issues/3970)
|
||||
- Use maven CI friendly versions: revision. [#3851](https://github.com/apache/dubbo/issues/3851)
|
||||
- remove-parse-error-log [#3862](https://github.com/apache/dubbo/issues/3862)
|
||||
- Complete xsd definition for ConfigCenterConfig. [#3854](https://github.com/apache/dubbo/issues/3854)
|
||||
- add remoteApplicationName field in RpcContext [#3816](https://github.com/apache/dubbo/issues/3816)
|
||||
|
||||
### Bugfixes
|
||||
|
||||
- @Reference can't match the local @Service beans. [#4071](https://github.com/apache/dubbo/issues/4071)
|
||||
- remove some illegal licence: jcip-annotations, jsr173_api. [#3790](https://github.com/apache/dubbo/issues/3790)
|
||||
- Qos port can't be disabled by externalized property. [#3958](https://github.com/apache/dubbo/issues/3958)
|
||||
- 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)
|
||||
- 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)
|
||||
- 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)
|
||||
- dubbo registry extension compatibility with dubbo 2.6.x. [#3882](https://github.com/apache/dubbo/issues/3882)
|
||||
- Annotation mode cannot set service parameters in 2.7.0. [#3778](https://github.com/apache/dubbo/issues/3778)
|
||||
- compatibility with Zipkin. [#3728](https://github.com/apache/dubbo/issues/3728)
|
||||
- do local export before register any listener. [#3669](https://github.com/apache/dubbo/issues/3669)
|
||||
- Cannot recognize 2.6.x compatible rules from dubbo-admin. [#4059](https://github.com/apache/dubbo/issues/4059)
|
||||
- In Dubbo 2.7.0, the provider can't be configured to async [#3650](https://github.com/apache/dubbo/issues/3650)
|
||||
- dubbox compatibility [#3991](https://github.com/apache/dubbo/issues/3991)
|
||||
- dubbo-2.7.1 providers repeat register [#3785](https://github.com/apache/dubbo/issues/3785)
|
||||
- consul registry: NullPointerException [#3923](https://github.com/apache/dubbo/issues/3923)
|
||||
- cannot publish local ip address when local ip and public ip exist at the same time [#3802](https://github.com/apache/dubbo/issues/3802)
|
||||
- roll back change made by 3520. [#3935](https://github.com/apache/dubbo/issues/3935)
|
||||
- dubbo-registry-nacos module is not bundled into Apache Dubbo 2.7.1 [#3797](https://github.com/apache/dubbo/issues/3797)
|
||||
- switch from CopyOnWriteArrayList to regular list in order to avoid potential UnsupportedOperationException [#3242](https://github.com/apache/dubbo/issues/3242)
|
||||
- Serialization ContentTypeId conflict between avro protocol and protocoluff protocol [#3926](https://github.com/apache/dubbo/issues/3926)
|
||||
- delay export function doesn't work. [#3952](https://github.com/apache/dubbo/issues/3952)
|
||||
- org.apache.dubbo.rpc.support.MockInvoker#getInterface should not return null [#3713](https://github.com/apache/dubbo/issues/3713)
|
||||
- dubbo TagRouter does not work with dubbo:parameter [#3875](https://github.com/apache/dubbo/issues/3875)
|
||||
- make protocols a mutable list (a concrete ArrayList) [#3841](https://github.com/apache/dubbo/issues/3841)
|
||||
- javadoc lint issue [#3646](https://github.com/apache/dubbo/issues/3646)
|
||||
- The etcd3 lease should be recycled correctly [#3684](https://github.com/apache/dubbo/issues/3684)
|
||||
- telnet can't work when parameter has no nullary constructor and some fields is primitive [#4007](https://github.com/apache/dubbo/issues/4007)
|
||||
- Sort added router list before set the 'routers' field of the RouterChain [#3969](https://github.com/apache/dubbo/issues/3969)
|
||||
- fix injvm and local call [#3638](https://github.com/apache/dubbo/issues/3638)
|
||||
- spelling error in org.apache.dubbo.common.extension.AdaptiveClassCodeGenerator#generateReturnAndInovation [#3933](https://github.com/apache/dubbo/issues/3933)
|
||||
- metadata report doesn't support redis with password [#3826](https://github.com/apache/dubbo/issues/3826)
|
||||
- The dubbo protostuff protocol serializes the bug of java.sql.Timestamp [#3914](https://github.com/apache/dubbo/issues/3914)
|
||||
- do not filter thread pool by port [#3919](https://github.com/apache/dubbo/issues/3919)
|
||||
- 'dubbo-serialization-gson' maven package error [#3903](https://github.com/apache/dubbo/issues/3903)
|
||||
- AbstractRegistry will be endless loop, when doSaveProperties method have no permission to save the file [#3746](https://github.com/apache/dubbo/issues/3746)
|
||||
- fix fastjson serialization with generic return type [#3771](https://github.com/apache/dubbo/issues/3771)
|
||||
- The dubbo-serialization -api modules should not dependency on third-party jar packages [#3762](https://github.com/apache/dubbo/issues/3762)
|
||||
- when using protostuff to serialize, there is not to check whether the data is null [#3727](https://github.com/apache/dubbo/issues/3727)
|
||||
- bugfix and enhancement for async [#3287](https://github.com/apache/dubbo/issues/3287)
|
||||
|
||||
## 2.7.1
|
||||
|
||||
### Notice
|
||||
|
||||
'zkclient' extension for 'org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter' is removed from Dubbo 2.7.1, and 'curator' extension becomes the default extension. If you happen to config your application to use 'zkclient' explicitly, pls. switch to use 'curator' instead.
|
||||
|
||||
### New Features
|
||||
|
||||
- service register support on nacos [#3582](https://github.com/apache/dubbo/issues/3582)
|
||||
- support consul as registry center, config center and metadata center [#983](https://github.com/apache/dubbo/issues/983)
|
||||
- service registry support/config center support on etcd [#808](https://github.com/apache/dubbo/issues/808)
|
||||
- metrics support in dubbo 2.7.1 [#3598](https://github.com/apache/dubbo/issues/3598)
|
||||
- @Argument @Method support [#2405](https://github.com/apache/dubbo/issues/2045)
|
||||
|
||||
### Enhancement
|
||||
|
||||
- [Enhancement] @EnableDubboConfigBinding annotates @Repeatable [#1770](https://github.com/apache/dubbo/issues/1770)
|
||||
- [Enhancement] Change the default behavior of @EnableDubboConfig.multiple() [#3193](https://github.com/apache/dubbo/issues/3193)
|
||||
- Should make annotation easier to use in multiple items circumstance [#3039](https://github.com/apache/dubbo/issues/3039)
|
||||
- NoSuchMethodError are thrown when add custom Filter using dubbo2.6.5 and JDK1.6 and upgrade to dubbo2.7.0 [#3570](https://github.com/apache/dubbo/issues/3570)
|
||||
- introduce dubbo-dependencies-zookeeper [#3607](https://github.com/apache/dubbo/pull/3607)
|
||||
- Zookeeper ConfigCenter reuse the client abstraction and connection session [#3288](https://github.com/apache/dubbo/issues/3288)
|
||||
- [Survey] Is it necessary to continue to maintain zkclient in dubbo project? [#3569](https://github.com/apache/dubbo/issues/3569)
|
||||
- Start to use IdleStateHandler in Netty4 [#3341](https://github.com/apache/dubbo/pull/3341)
|
||||
- Support multiple shared links [#2457](https://github.com/apache/dubbo/pull/2457)
|
||||
- Optimize heartbeat [#3299](https://github.com/apache/dubbo/pull/3299)
|
||||
- AccessLogFilter simple date format reduce instance creation [#3026](https://github.com/apache/dubbo/issues/3026)
|
||||
- Support wildcard ip for tag router rule. [#3289](https://github.com/apache/dubbo/issues/3289)
|
||||
- ScriptRouter should cache CompiledScript [#390](https://github.com/apache/dubbo/issues/390)
|
||||
- Optimize compareTo in Router to guarantee consistent behaviour. [#3302](https://github.com/apache/dubbo/issues/3302)
|
||||
- RMI protocol doesn't support generic invocation [#2779](https://github.com/apache/dubbo/issues/2779)
|
||||
- a more elegant way to enhance HashedWheelTimer [#3567](https://github.com/apache/dubbo/pull/3567)
|
||||
- obtain local address incorrectly sometimes in dubbo [#538](https://github.com/apache/dubbo/issues/538)
|
||||
- implement pull request #3412 on master branch [#3418](https://github.com/apache/dubbo/pull/3418)
|
||||
- enhancement for event of response (follow up for pull request #3043) [#3244](https://github.com/apache/dubbo/issues/3244)
|
||||
- bump up hessian-lite version #3423 [#3513](https://github.com/apache/dubbo/pull/3513)
|
||||
- [Dubbo-3610]make snakeyaml transitive, should we do this? [#3659](https://github.com/apache/dubbo/pull/3659)
|
||||
|
||||
### Bugfixes
|
||||
|
||||
- cannot register REST service in 2.7 due to the changes in RestProtoco#getContextPath [#3445](https://github.com/apache/dubbo/issues/3445)
|
||||
- Conflict between curator client and dubbo [#3574](https://github.com/apache/dubbo/issues/3574)
|
||||
- is there a problem in NettyBackedChannelBuffer.setBytes(...)? [#2619](https://github.com/apache/dubbo/issues/2619)
|
||||
- [Dubbo - client always reconnect offline provider] Dubbo client bug [#3158](https://github.com/apache/dubbo/issues/3158)
|
||||
- fix heartbeat internal [#3579](https://github.com/apache/dubbo/pull/3579)
|
||||
- logic issue in RedisRegistry leads to services cannot be discovered. [#3291](https://github.com/apache/dubbo/pull/3291)
|
||||
- Multicast demo fails with message "Can't assign requested address" [#2423](https://github.com/apache/dubbo/issues/2423)
|
||||
- Fix thrift protocol, use path to locate exporter. [#3331](https://github.com/apache/dubbo/pull/3331)
|
||||
- cannot use override to modify provider's configuration when hessian protocol is used [#900](https://github.com/apache/dubbo/issues/900)
|
||||
- Condition is not properly used ? [#1917](https://github.com/apache/dubbo/issues/1917)
|
||||
- connectionMonitor in RestProtocol seems not work [#3237](https://github.com/apache/dubbo/issues/3237)
|
||||
- fail to parse config text with white space [#3367](https://github.com/apache/dubbo/issues/3367)
|
||||
- @Reference check=false doesn't take effect [#195](https://github.com/apache/dubbo/issues/195)
|
||||
- [Issue] SpringStatusChecker execute errors on non-XML Spring configuration [#3615](https://github.com/apache/dubbo/issues/3615)
|
||||
- monitor's cluster config is set to failsafe and set to failsafe only [#274](https://github.com/apache/dubbo/issues/274)
|
||||
- A question for ReferenceConfigCache. [#1293](https://github.com/apache/dubbo/issues/1293)
|
||||
- referenceconfig#destroy never invoke unregister [#3294](https://github.com/apache/dubbo/issues/3294)
|
||||
- Fix when qos is disable,log will print every time [#3397](https://github.com/apache/dubbo/pull/3397)
|
||||
- service group is not supported in generic direct invocation [#3555](https://github.com/apache/dubbo/issues/3555)
|
||||
- setOnreturn doesn't take effect in async generic invocation [#208](https://github.com/apache/dubbo/issues/208)
|
||||
- Fix timeout filter not work in async way [#3174](https://github.com/apache/dubbo/pull/3174)
|
||||
- java.lang.NumberFormatException: For input string: "" [#3069](https://github.com/apache/dubbo/issues/3069)
|
||||
- NPE occurred when the configuration was deleted [#3533](https://github.com/apache/dubbo/issues/3533)
|
||||
- NPE when package of interface is empty [#3556](https://github.com/apache/dubbo/issues/3556)
|
||||
- NPE when exporting rest service using a given path. [#3477](https://github.com/apache/dubbo/issues/3477)
|
||||
- NullPointerException happened when using SpringContainer.getContext() [#3476](https://github.com/apache/dubbo/issues/3476)
|
||||
- Why does not tomcat throw an exception when `server.start` failed with a socket binding error. [#3236](https://github.com/apache/dubbo/issues/3236)
|
||||
- No such extension org.apache.dubbo.metadata.store.MetadataReportFactory by name redis [#3514](https://github.com/apache/dubbo/issues/3514)
|
||||
- dubbo 2.7.1-SNAPSHOT NoClassDefFoundError when use springboot [#3426](https://github.com/apache/dubbo/issues/3426)
|
||||
- NPE occurs when use @Reference in junit in spring boot application [#3429](https://github.com/apache/dubbo/issues/3429)
|
||||
- When refer the same service with more than one @References(with different configs) on consumer side, only one take effect [#1306](https://github.com/apache/dubbo/issues/1306)
|
||||
- consumer always catch java.lang.reflect.UndeclaredThrowableException for the exception thrown from provider [#3386](https://github.com/apache/dubbo/issues/3386)
|
||||
- dubbo2.7.0 com.alibaba.com.caucho.hessian.io.HessianProtocolException: 'com.alibaba.dubbo.common.URL' could not be instantiated [#3342](https://github.com/apache/dubbo/issues/3342)
|
||||
- Close Resources Properly [#3473](https://github.com/apache/dubbo/issues/3473)
|
||||
- SPI entires dup by 3 times. [#2842](https://github.com/apache/dubbo/issues/2842)
|
||||
- provider gets wrong interface name from attachment when use generic invocation in 2.6.3 [#2981](https://github.com/apache/dubbo/issues/2981)
|
||||
- HashedWheelTimer's queue gets full [#3449](https://github.com/apache/dubbo/issues/3449)
|
||||
- Modify MetadataReportRetry ThreadName [#3550](https://github.com/apache/dubbo/pull/3550)
|
||||
- Keep interface key in the URL in simplify mode when it's different from path. [#3478](https://github.com/apache/dubbo/issues/3478)
|
||||
- nc is not stable in dubbo's bootstrap script [#936](https://github.com/apache/dubbo/issues/936)
|
||||
|
||||
## 2.7.0
|
||||
|
||||
Requirements: **Java 8+** required
|
||||
|
||||
Please check [here](https://github.com/apache/dubbo/blob/2.7.0-release/CHANGES.md#upgrading-and-compatibility-notifications) for notes and possible compatibility issues for upgrading from 2.6.x or lower to 2.7.0.
|
||||
|
||||
### New Features
|
||||
|
||||
- Enhancement of service governance rules.
|
||||
- Enriched Routing Rules.
|
||||
1. Conditional Routing. Supports both application-level and service-level conditions.
|
||||
2. Tag Routing. Newly introduced to better support traffic isolation, such as grey deployment.
|
||||
- Decoupling governance rules with the registry, making it easier to extend. Apollo and Zookeeper are available in this version. Nacos support is on the way...
|
||||
- Application-level Dynamic Configuration support.
|
||||
- Use YAML as the configuration language, which is more friendly to read and use.
|
||||
|
||||
- Externalized Configuration. Supports reading `dubbo.properties` hosted in remote centralized configuration center - centralized configuration.
|
||||
|
||||
- Simplified registry URL. With lower Registry memory use and less notification pressure from Service Directory, separates Configuration notification from Service Discovery.
|
||||
|
||||
- Metadata Center. A totally new concept since 2.7.0, used to store service metadata including static configuration, service definition, method signature, etc.. By default, Zookeeper and Redis are supported as the backend storage. Will work as the basis of service testing, mock and other service governance features going to be supported in [Dubbo-Admin](https://github.com/apache/dubbo-admin).
|
||||
|
||||
- Asynchronous Programming Model (only works for Dubbo protocol now)
|
||||
- Built-in support for the method with CompletableFuture<T> signature.
|
||||
- Server-side asynchronous support, with an AsyncContext API works like Servlet 3.0.
|
||||
- Asynchronous filter chain callback.
|
||||
|
||||
- Serialization Extension: Protobuf.
|
||||
|
||||
- Caching Policy Extension: Expiring Cache.
|
||||
|
||||
### Enhancements / Bugfixes
|
||||
|
||||
- Load Balancing strategy enhancement: ConsitentHash #2190, LeastActive #2171, Random #2597, RoundRobin #2650.
|
||||
|
||||
- Third-party dependency upgrading.
|
||||
- Switch default remoting to Netty 4.
|
||||
- Switch default Zookeeper client to Curator.
|
||||
- Upgrade Jetty to 9.x.
|
||||
|
||||
- IPV6 support #2079.
|
||||
|
||||
- Performance tuning, check hanging requests on a closed channel, make them return directly #2185.
|
||||
|
||||
- Fixed the serialization problem of JDK primitive types in Kryo #2178.
|
||||
|
||||
- Fixed the problem of failing to notify Consumer as early as possible after the Provider side deserialization failed #1903.
|
||||
|
||||
### Upgrading and Compatibility Notifications
|
||||
|
||||
We have always keep compatibility in mind during the whole process of 2.7.0. We even want old users to upgrade with only on pom version upgrade, but it's hard to achieve that, especially when considering that we have the package renamed in this version, so we had some tradeoffs. If you only used the Dubbo's most basic features, you may have little problems of upgrading, but if you have used some advanced features or have some SPI extensions inside, you'd better read the upgrade notifications carefully. The compatibility issues can be classified into the following 5 categories, for each part, there will have detailed dos and don'ts published later in the official website.
|
||||
|
||||
1. Interoperability between 2.7.0 and lower versions
|
||||
|
||||
2. Package renaming
|
||||
|
||||
com.alibaba.dubbo -> org.apache.dubbo
|
||||
|
||||
3. Simplification of registered URLs
|
||||
|
||||
4. Service Governance Rules
|
||||
|
||||
5. Configuration
|
||||
|
||||
## 2.6.6
|
||||
|
||||
Enhancement / New feature:
|
||||
|
||||
* tag route. #3065
|
||||
* Use Netty4 as default Netty version. #3029
|
||||
* upporting Java 8 Date/Time type when serializing with Kryo #3519
|
||||
* support config telnet #3511
|
||||
* add annotation driven in MethodConfig and ArgumentConfig #2603
|
||||
* add nacos-registry module #3296
|
||||
* add `protocol` attribute in `@Rerefence` #3555
|
||||
*support the hierarchical interface in @Service #3251
|
||||
* change the default behavior in `@EnableDubboConfig.multiple()` #3193
|
||||
* inline source code of `spring-context-support` #3192
|
||||
* Simplify externalized configuration of Dubbo Protocol name #3189
|
||||
|
||||
BugFix:
|
||||
|
||||
* update hessian-lite to 2.3.5, fix unnecessary class load #3538
|
||||
* Fix unregister when client destroyed(referenceconfig#destroy) #3502
|
||||
* SPI entires dup by 3 times #3315
|
||||
* fix Consumer throws RpcException after RegistryDirectory notify in high QPS #2016
|
||||
* 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 the priority of `DubboConfigConfigurationSelector ` #2897
|
||||
* fix `@Rerefence#parameters()` not work #2301
|
||||
|
||||
## 2.6.5
|
||||
|
||||
Enhancements / Features:
|
||||
|
||||
- Reactor the generation rule for @Service Bean name [#2235](https://github.com/apache/dubbo/issues/2235)
|
||||
- Introduce a new Spring ApplicationEvent for ServiceBean exporting [#2251](https://github.com/apache/dubbo/issues/2251)
|
||||
- [Enhancement] the algorithm of load issue on Windows. [#1641](https://github.com/apache/dubbo/issues/1641)
|
||||
- add javadoc to dubbo-all module good first issue. [#2600](https://github.com/apache/dubbo/issues/2600)
|
||||
- [Enhancement] Reactor the generation rule for @Service Bean name type/enhancement [#2235](https://github.com/apache/dubbo/issues/2235)
|
||||
- Optimize LeastActiveLoadBalance and add weight test case. [#2540](https://github.com/apache/dubbo/issues/2540)
|
||||
- Smooth Round Robin selection. [#2578](https://github.com/apache/dubbo/issues/2578) [#2647](https://github.com/apache/dubbo/pull/2647)
|
||||
- [Enhancement] Resolve the placeholders for sub-properties. [#2297](https://github.com/apache/dubbo/issues/2297)
|
||||
- Add ability to turn off SPI auto injection, special support for generic Object type injection. [#2681](https://github.com/apache/dubbo/pull/2681)
|
||||
|
||||
|
||||
Bugfixes:
|
||||
|
||||
- @Service(register=false) is not work. [#2063](https://github.com/apache/dubbo/issues/2063)
|
||||
- Our customized serialization id exceeds the maximum limit, now it cannot work on 2.6.2 anymore. [#1903](https://github.com/apache/dubbo/issues/1903)
|
||||
- Consumer throws RpcException after RegistryDirectory notify in high QPS. [#2016](https://github.com/apache/dubbo/issues/2016)
|
||||
- Annotation @Reference can't support to export a service with a sync one and an async one . [#2194](https://github.com/apache/dubbo/issues/2194)
|
||||
- `org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor#generateReferenceBeanCacheKey` has a bug. [#2522](https://github.com/apache/dubbo/issues/2522)
|
||||
- 2.6.x Spring Event & Bugfix. [#2256](https://github.com/apache/dubbo/issues/2256)
|
||||
- Fix incorrect descriptions for dubbo-serialization module. [#2665](https://github.com/apache/dubbo/issues/2665)
|
||||
- A empty directory dubbo-config/dubbo-config-spring/src/test/resources/work after package source tgz. [#2560](https://github.com/apache/dubbo/issues/2560)
|
||||
- Fixed 2.6.x branch a minor issue with doConnect not using getConnectTimeout() in NettyClient. (*No issue*). [#2622](https://github.com/apache/dubbo/pull/2622)
|
||||
- Bean name of @service annotated class does not resolve placeholder. [#1755](https://github.com/apache/dubbo/issues/1755)
|
||||
|
||||
|
||||
|
||||
Issues and Pull Requests, check [milestone-2.6.5](https://github.com/apache/dubbo/milestone/21).
|
||||
|
||||
## 2.6.4
|
||||
|
||||
Enhancements / Features
|
||||
|
||||
- Support access Redis with password, [#2146](https://github.com/apache/dubbo/pull/2146)
|
||||
- Support char array for GenericService, [#2137](https://github.com/apache/dubbo/pull/2137)
|
||||
- Direct return when the server goes down abnormally, [#2451](https://github.com/apache/dubbo/pull/2451)
|
||||
- Add log for trouble-shooting when qos start failed, [#2455](https://github.com/apache/dubbo/pull/2455)
|
||||
- PojoUtil support subclasses of java.util.Date, [#2502](https://github.com/apache/dubbo/pull/2502)
|
||||
- Add ip and application name for MonitorService, [#2166](https://github.com/apache/dubbo/pull/2166)
|
||||
- New ASCII logo, [#2402](https://github.com/apache/dubbo/pull/2402)
|
||||
|
||||
Bugfixes
|
||||
|
||||
- Change consumer retries default value from 0 to 2, [#2303](https://github.com/apache/dubbo/pull/2303)
|
||||
- Fix the problem that attachment is lost when retry, [#2024](https://github.com/apache/dubbo/pull/2024)
|
||||
- Fix NPE when telnet get a null parameter, [#2453](https://github.com/apache/dubbo/pull/2453)
|
||||
|
||||
UT stability
|
||||
|
||||
- Improve the stability by changing different port, setting timeout to 3000ms, [#2501](https://github.com/apache/dubbo/pull/2501)
|
||||
|
||||
Issues and Pull Requests, check [milestone-2.6.4](https://github.com/apache/dubbo/milestone/19).
|
||||
|
||||
## 2.6.3
|
||||
|
||||
Enhancements / Features
|
||||
|
||||
- Support implicit delivery of attachments from provider to consumer, #889
|
||||
- Support inject Spring bean to SPI by bean type, #1837
|
||||
- Add generic invoke and attachments support for http&hessian protocol, #1827
|
||||
- Get the real methodname to support consistenthash for generic invoke, #1872
|
||||
- Remove validation key from provider url on Consumer side, config depedently, #1386
|
||||
- Introducing the Bootstrap module as a unified entry for Dubbo startup and resource destruction, #1820
|
||||
- Open TCP_NODELAY on Netty 3, #1746
|
||||
- Support specify proxy type on provider side, #1873
|
||||
- Support dbindex in redis, #1831
|
||||
- Upgrade tomcat to 8.5.31, #1781
|
||||
|
||||
Bugfixes
|
||||
|
||||
- ExecutionDispatcher meet with user docs, #1089
|
||||
- Remove side effects of Dubbo custom loggers on Netty logger, #1717
|
||||
- Fix isShutdown() judge of Dubbo biz threadpool always return true, #1426
|
||||
- Selection of invoker node under the critical condition of only two nodes, #1759
|
||||
- Listener cann't be removed during unsubscribe when use ZK as registry, #1792
|
||||
- URL parsing problem when user filed contains '@', #1808
|
||||
- Check null in CacheFilter to avoid NPE, #1828
|
||||
- Fix potential deadlock in DubboProtocol, #1836
|
||||
- Restore the bug that attachment has not been updated in the RpcContext when the Dubbo built-in retry mechanism is triggered, #1453
|
||||
- Some other small bugfixes
|
||||
|
||||
Performance Tuning
|
||||
|
||||
- ChannelState branch prediction optimization. #1643
|
||||
- Optimize AtomicPositiveInteger, less memory and compute cost, #348
|
||||
- Introduce embedded Threadlocal to replace the JDK implementation, #1745
|
||||
|
||||
Hessian-lite
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at dev@dubbo.apache.org. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
|
||||
## Contributing to Dubbo
|
||||
Dubbo is released under the non-restrictive Apache 2.0 licenses and follows a very standard Github development process, using Github tracker for issues and merging pull requests into master. Contributions of all form to this repository is acceptable, as long as it follows the prescribed community guidelines enumerated below.
|
||||
|
||||
### Sign the Contributor License Agreement
|
||||
Before we accept a non-trivial patch or pull request (PRs), we will need you to sign the Contributor License Agreement. Signing the contributors' agreement does not grant anyone commits rights to the main repository, but it does mean that we can accept your contributions, and you will get an author credit if we do. Active contributors may get invited to join the core team that will grant them privileges to merge existing PRs.
|
||||
|
||||
### Contact
|
||||
|
||||
#### Mailing list
|
||||
|
||||
The mailing list is the recommended way of pursuing a discussion on almost anything related to Dubbo. Please refer to this [guide](https://github.com/apache/dubbo/wiki/Mailing-list-subscription-guide) for detailed documentation on how to subscribe.
|
||||
|
||||
- [dev@dubbo.apache.org](mailto:dev-subscribe@dubbo.apache.org): the developer mailing list where you can ask questions about an issue you may have encountered while working with Dubbo.
|
||||
- [commits@dubbo.apache.org](mailto:commits-subscribe@dubbo.apache.org): the commit updates will get broadcasted on this mailing list. You can subscribe to it, should you be interested in following Dubbo's development.
|
||||
- [notifications@dubbo.apache.org](mailto:notifications-subscribe@dubbo.apache.org): all the Github [issue](https://github.com/apache/dubbo/issues) updates and [pull request](https://github.com/apache/dubbo/pulls) updates will be sent to this mailing list.
|
||||
|
||||
### Reporting issue
|
||||
|
||||
Please follow the [template](https://github.com/apache/dubbo/issues/new?template=dubbo-issue-report-template.md) for reporting any issues.
|
||||
|
||||
### Code Conventions
|
||||
Our code style is almost in line with the standard java conventions (Popular IDE's default setting satisfy this), with the following additional restricts:
|
||||
* If there are more than 120 characters in the current line, begin a new line.
|
||||
|
||||
* Make sure all new .java files to have a simple Javadoc class comment with at least a @date tag identifying birth, and preferably at least a paragraph on the intended purpose of the class.
|
||||
|
||||
* Add the ASF license header comment to all new .java files (copy from existing files in the project)
|
||||
|
||||
* Make sure no @author tag gets appended to the file you contribute to as the @author tag is incompatible with Apache. Rest assured, other ways, including CVS, will ensure transparency, fairness in recording your contributions.
|
||||
|
||||
* Add some Javadocs and, if you change the namespace, some XSD doc elements.
|
||||
|
||||
* Sufficient unit-tests should accompany new feature development or non-trivial bug fixes.
|
||||
|
||||
* If no-one else is using your branch, please rebase it against the current master (or another target branch in the main project).
|
||||
|
||||
* When writing a commit message, please follow the following conventions: should your commit address an open issue, please add Fixes #XXX at the end of the commit message (where XXX is the issue number).
|
||||
|
||||
### Contribution flow
|
||||
|
||||
A rough outline of an ideal contributors' workflow is as follows:
|
||||
|
||||
* Fork the current repository
|
||||
* Create a topic branch from where to base the contribution. Mostly, it's the master branch.
|
||||
* Make commits of logical units.
|
||||
* Make sure the commit messages are in the proper format (see below).
|
||||
* Push changes in a topic branch to your forked repository.
|
||||
* Follow the checklist in the [pull request template](https://github.com/apache/dubbo/blob/master/PULL_REQUEST_TEMPLATE.md)
|
||||
* Before sending out the pull request, please sync your forked repository with the remote repository to ensure that your PR is elegant, concise. Reference the guide below:
|
||||
```
|
||||
git remote add upstream git@github.com:apache/dubbo.git
|
||||
git fetch upstream
|
||||
git rebase upstream/master
|
||||
git checkout -b your_awesome_patch
|
||||
... add some work
|
||||
git push origin your_awesome_patch
|
||||
```
|
||||
* Submit a pull request to apache/dubbo and wait for the reply.
|
||||
|
||||
Thanks for contributing!
|
||||
|
||||
### Code style
|
||||
|
||||
We provide a template file [dubbo_codestyle_for_idea.xml](https://github.com/apache/dubbo/tree/master/codestyle/dubbo_codestyle_for_idea.xml) for IntelliJ idea that you can import it to your workplace.
|
||||
If you use Eclipse, you can use the IntelliJ Idea template for manually configuring your file.
|
||||
|
||||
**NOTICE**
|
||||
|
||||
It's critical to set the dubbo_codestyle_for_idea.xml to avoid the failure of your Travis CI builds. Steps to configure the code styles are as follows:
|
||||
|
||||
1. Enter `Editor > Code Style`
|
||||
2. To manage a code style scheme, in the Code Style page, select the desired scheme from the drop-down list, and click on .
|
||||
From the drop-down list, select `Import Scheme`, then choose the option `IntelliJ IDEA code style XML` to import the scheme.
|
||||
3. In the Scheme field, type the name of the new scheme and press ⏎ to save the changes.
|
||||
|
||||
13
COPYRIGHT
13
COPYRIGHT
|
|
@ -1,13 +0,0 @@
|
|||
Copyright 1999-2011 Alibaba Group.
|
||||
|
||||
Licensed 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.
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
import groovy.json.JsonSlurper
|
||||
|
||||
pipeline {
|
||||
agent {
|
||||
node {
|
||||
label 'ubuntu'
|
||||
}
|
||||
}
|
||||
|
||||
options {
|
||||
buildDiscarder(logRotator(daysToKeepStr: '14', artifactNumToKeepStr: '10'))
|
||||
}
|
||||
|
||||
environment {
|
||||
JAVA_HOME = "${tool 'JDK 1.8 (latest)'}"
|
||||
}
|
||||
|
||||
tools {
|
||||
maven 'Maven 3 (latest)'
|
||||
jdk 'JDK 1.8 (latest)'
|
||||
}
|
||||
|
||||
triggers {
|
||||
cron '''TZ=Asia/Shanghai
|
||||
H 2,14 * * *'''
|
||||
pollSCM '''TZ=Asia/Shanghai
|
||||
H H/2 * * *'''
|
||||
}
|
||||
|
||||
|
||||
stages {
|
||||
stage('Clone') {
|
||||
steps {
|
||||
checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'CloneOption', noTags: true, reference: '', shallow: true]], gitTool: 'Default', submoduleCfg: [], userRemoteConfigs: [[url: 'https://github.com/apache/dubbo.git']]])
|
||||
}
|
||||
}
|
||||
|
||||
stage('Duplicate deploy check') {
|
||||
steps {
|
||||
script {
|
||||
def deployedCommitId = sh(returnStdout: true, script: "curl --silent https://builds.apache.org/job/Apache%20Dubbo/job/${env.JOB_BASE_NAME}/lastSuccessfulBuild/artifact/DEPLOY_COMMIT_ID || true").trim()
|
||||
env.DEPLOYED_COMMIT_ID = deployedCommitId
|
||||
def commitId = sh(returnStdout: true, script: 'git rev-parse HEAD').trim()
|
||||
env.COMMIT_ID = commitId
|
||||
|
||||
if (commitId == deployedCommitId) {
|
||||
env.STATUS_CHECK = "false"
|
||||
println "Latest deployed commit id is $deployedCommitId, Skip deployment this time"
|
||||
} else {
|
||||
env.STATUS_CHECK = "true"
|
||||
println "Current commit id hasn't been deployed, continue"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Commit status check') {
|
||||
when {
|
||||
expression {
|
||||
return env.STATUS_CHECK == "true";
|
||||
}
|
||||
}
|
||||
steps {
|
||||
script {
|
||||
def commitId = env.COMMIT_ID
|
||||
println "Current commit id: $commitId"
|
||||
|
||||
def commitStatusJson = sh(script: "curl --silent https://api.github.com/repos/apache/dubbo/commits/$commitId/status", returnStdout: true).trim()
|
||||
println "Commit status: \r\n$commitStatusJson"
|
||||
|
||||
def jsonSlurper = new JsonSlurper()
|
||||
def jsonObject = jsonSlurper.parseText(commitStatusJson)
|
||||
|
||||
def status = jsonObject.state
|
||||
|
||||
println "Current commit status is $status"
|
||||
|
||||
if (status == "success") {
|
||||
env.STATUS_CHECK = "true"
|
||||
println "Continue to deploy snapshot"
|
||||
} else {
|
||||
env.STATUS_CHECK = "false"
|
||||
println "Current commit status not allow to deploy snapshot"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Snapshot version check') {
|
||||
when {
|
||||
expression {
|
||||
return env.STATUS_CHECK == "true";
|
||||
}
|
||||
}
|
||||
steps {
|
||||
sh 'env'
|
||||
sh 'java -version'
|
||||
sh './mvnw clean install -pl "dubbo-dependencies-bom" && ./mvnw clean install -DskipTests=true && ./mvnw clean validate -Psnapshot-ci-deploy -pl "dubbo-all"'
|
||||
}
|
||||
}
|
||||
|
||||
stage('Deploy snapshot') {
|
||||
when {
|
||||
expression {
|
||||
return env.STATUS_CHECK == "true";
|
||||
}
|
||||
}
|
||||
steps {
|
||||
timeout(40) {
|
||||
sh './mvnw --version'
|
||||
sh './mvnw clean package deploy -pl dubbo-dependencies-bom && ./mvnw clean source:jar javadoc:jar package deploy -DskipTests=true'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Save deployed commit id') {
|
||||
steps {
|
||||
script {
|
||||
if (env.STATUS_CHECK != "true") {
|
||||
println "Not pass status check"
|
||||
env.COMMIT_ID = env.DEPLOYED_COMMIT_ID
|
||||
}
|
||||
}
|
||||
writeFile file: 'DEPLOY_COMMIT_ID', text: "${env.COMMIT_ID}"
|
||||
archiveArtifacts 'DEPLOY_COMMIT_ID'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
failure {
|
||||
mail bcc: '', body: '''Project: ${env.JOB_NAME}
|
||||
Build Number: ${env.BUILD_NUMBER}
|
||||
URL: ${env.BUILD_URL}''', cc: '', from: '', replyTo: '', subject: 'Apache Dubbo snapshot deployment fail', to: 'dev@dubbo.apache.org'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
*
|
||||
* 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}'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
89
LICENSE
89
LICENSE
|
|
@ -187,7 +187,7 @@
|
|||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 1999-2011 Alibaba Group.
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
|
@ -200,3 +200,90 @@
|
|||
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.
|
||||
|
||||
|
||||
Apache Dubbo Submodules:
|
||||
|
||||
Apache Dubbo includes a number of submodules with separate copyright notices
|
||||
and license terms. Your use of these submodules is subject to the terms and
|
||||
conditions of the following licenses.
|
||||
|
||||
For the package org.apache.dubbo.common.threadlocal and org.apache.dubbo.common.timer:
|
||||
|
||||
This product contains a modified portion of 'Netty', an event-driven asynchronous network application framework also
|
||||
under a "Apache License 2.0" license, see https://github.com/netty/netty/blob/4.1/LICENSE.txt:
|
||||
|
||||
* io.netty.util.concurrent.FastThreadLocal
|
||||
* io.netty.util.internal.InternalThreadLocalMap
|
||||
* io.netty.util.Timer
|
||||
* io.netty.util.TimerTask
|
||||
* io.netty.util.Timeout
|
||||
* io.netty.util.HashedWheelTimer
|
||||
|
||||
For the org.apache.dubbo.common.utils.CIDRUtils :
|
||||
|
||||
This product contains a modified portion of 'edazdarevic.commons.net.CIDRUtils' published at
|
||||
https://github.com/edazdarevic/CIDRUtils. The project is licensed under a MIT License:
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2013 Edin Dazdarevic (edin.dazdarevic@gmail.com)
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
|
||||
For the file org.apache.dubbo.common.utils.Utf8Utils.java:
|
||||
|
||||
This product contains a portion of the Protocol Buffers project, which is published at
|
||||
https://developers.google.com/protocol-buffers/ and is licensed under the following License:
|
||||
|
||||
Copyright 2008 Google Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Code generated by the Protocol Buffer compiler is owned by the owner
|
||||
of the input file used when generating it. This code is not
|
||||
standalone and requires a support library to be linked with it. This
|
||||
support library is itself covered by the above license.
|
||||
|
||||
For the ca.proto in dubbo-registry-xds:
|
||||
|
||||
This product contains a modified portion of 'Istio', an open platform to connect, manage, and secure microservices also
|
||||
under a "Apache License 2.0" license, see https://github.com/istio/api/blob/master/LICENSE:
|
||||
|
||||
* security/v1alpha1/ca.proto
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
Apache Dubbo
|
||||
Copyright 2018-2024 The Apache Software Foundation
|
||||
|
||||
This product includes software developed at
|
||||
The Apache Software Foundation (http://www.apache.org/).
|
||||
|
||||
This product contains code form the Netty Project:
|
||||
|
||||
The Netty Project
|
||||
=================
|
||||
Please visit the Netty web site for more information:
|
||||
* http://netty.io/
|
||||
|
||||
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)
|
||||
108
README
108
README
|
|
@ -1,108 +0,0 @@
|
|||
0. Install the subversion and maven command line:
|
||||
|
||||
yum install subversion
|
||||
or: apt-get install subversion
|
||||
|
||||
cd ~
|
||||
wget http://www.apache.org/dist//maven/binaries/apache-maven-2.2.1-bin.tar.gz
|
||||
tar zxvf apache-maven-2.2.1-bin.tar.gz
|
||||
vi .bash_profile
|
||||
- edit: export PATH=$PATH:~/apache-maven-2.2.1/bin
|
||||
source .bash_profile
|
||||
|
||||
1. Checkout the dubbo source code:
|
||||
|
||||
cd ~
|
||||
svn co http://code.alibabatech.com/svn/dubbo/trunk dubbo
|
||||
|
||||
2. Build the dubbo binary package:
|
||||
|
||||
cd ~/dubbo
|
||||
mvn clean install -Dmaven.test.skip
|
||||
cd dubbo/target
|
||||
ls
|
||||
|
||||
3. Import the dubbo source code to eclipse project:
|
||||
|
||||
cd ~/dubbo
|
||||
mvn eclipse:eclipse
|
||||
Eclipse -> Menu -> File -> Import -> Exsiting Projects to Workspace -> Browse -> Finish
|
||||
|
||||
4. Install the demo provider:
|
||||
|
||||
cd ~/dubbo/dubbo-demo-provider/target
|
||||
tar zxvf dubbo-demo-provider-2.0.10-assembly.tar.gz
|
||||
cd dubbo-demo-provider-2.0.10/bin
|
||||
./start.sh
|
||||
|
||||
5. Install the demo consumer:
|
||||
|
||||
cd ~/dubbo/dubbo-demo-consumer/target
|
||||
tar zxvf dubbo-demo-consumer-2.0.10-assembly.tar.gz
|
||||
cd dubbo-demo-consumer-2.0.10/bin
|
||||
./start.sh
|
||||
cd ../logs
|
||||
tail -f stdout.log
|
||||
|
||||
6. Install the simple monitor:
|
||||
|
||||
cd ~/dubbo/dubbo-simple-monitor/target
|
||||
tar zxvf dubbo-simple-monitor-2.0.10-assembly.tar.gz
|
||||
cd dubbo-simple-monitor-2.0.10/bin
|
||||
./start.sh
|
||||
http://127.0.0.1:8080
|
||||
|
||||
7. Install the simple registry:
|
||||
|
||||
cd ~/dubbo/dubbo-simple-registry/target
|
||||
tar zxvf dubbo-simple-registry-2.0.10-assembly.tar.gz
|
||||
cd dubbo-simple-registry-2.0.10/bin
|
||||
./start.sh
|
||||
|
||||
cd ~/dubbo/dubbo-demo-provider/conf
|
||||
vi dubbo.properties
|
||||
- edit: dubbo.registry.adddress=dubbo://127.0.0.1:9090
|
||||
cd ../bin
|
||||
./restart.sh
|
||||
|
||||
cd ~/dubbo/dubbo-demo-consumer/conf
|
||||
vi dubbo.properties
|
||||
- edit: dubbo.registry.adddress=dubbo://127.0.0.1:9090
|
||||
cd ../bin
|
||||
./restart.sh
|
||||
|
||||
cd ~/dubbo/dubbo-simple-monitor/conf
|
||||
vi dubbo.properties
|
||||
- edit: dubbo.registry.adddress=dubbo://127.0.0.1:9090
|
||||
cd ../bin
|
||||
./restart.sh
|
||||
|
||||
8. Install the zookeeper registry:
|
||||
|
||||
cd ~
|
||||
wget http://www.apache.org/dist//zookeeper/zookeeper-3.3.3/zookeeper-3.3.3.tar.gz
|
||||
tar zxvf zookeeper-3.3.3.tar.gz
|
||||
cd zookeeper-3.3.3/conf
|
||||
cp zoo_sample.cfg zoo.cfg
|
||||
vi zoo.cfg
|
||||
- edit: dataDir=/home/xxx/data
|
||||
cd ../bin
|
||||
./zkServer.sh start
|
||||
|
||||
cd ~/dubbo/dubbo-demo-provider/conf
|
||||
vi dubbo.properties
|
||||
- edit: dubbo.registry.adddress=zookeeper://127.0.0.1:2181
|
||||
cd ../bin
|
||||
./restart.sh
|
||||
|
||||
cd ~/dubbo/dubbo-demo-consumer/conf
|
||||
vi dubbo.properties
|
||||
- edit: dubbo.registry.adddress=zookeeper://127.0.0.1:2181
|
||||
cd ../bin
|
||||
./restart.sh
|
||||
|
||||
cd ~/dubbo/dubbo-simple-monitor/conf
|
||||
vi dubbo.properties
|
||||
- edit: dubbo.registry.adddress=zookeeper://127.0.0.1:2181
|
||||
cd ../bin
|
||||
./restart.sh
|
||||
|
|
@ -0,0 +1,272 @@
|
|||
# Apache Dubbo Project
|
||||
|
||||
[](https://github.com/apache/dubbo/actions/workflows/build-and-test-pr.yml)
|
||||
[](https://codecov.io/gh/apache/dubbo)
|
||||

|
||||

|
||||
[](http://isitmaintained.com/project/apache/dubbo "Average time to resolve an issue")
|
||||
[](http://isitmaintained.com/project/apache/dubbo "Percentage of issues still open")
|
||||
|
||||
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 :)
|
||||
|
||||
## Architecture
|
||||
|
||||

|
||||
|
||||
## Features
|
||||
|
||||
* Transparent interface based RPC
|
||||
* Intelligent load balancing
|
||||
* Automatic service registration and discovery
|
||||
* High extensibility
|
||||
* Runtime traffic routing
|
||||
* Visualized service governance
|
||||
|
||||
## 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.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/apache/dubbo-samples.git
|
||||
cd dubbo-samples/1-basic/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:
|
||||
|
||||
### Maven dependency
|
||||
|
||||
```xml
|
||||
<properties>
|
||||
<dubbo.version>3.2.13-SNAPSHOT</dubbo.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo</artifactId>
|
||||
<version>${dubbo.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-dependencies-zookeeper</artifactId>
|
||||
<version>${dubbo.version}</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
|
||||
### Define service interfaces
|
||||
|
||||
```java
|
||||
package org.apache.dubbo.samples.api;
|
||||
|
||||
public interface GreetingsService {
|
||||
String sayHi(String name);
|
||||
}
|
||||
```
|
||||
|
||||
*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.*
|
||||
|
||||
### Implement service interface for the provider
|
||||
|
||||
```java
|
||||
package org.apache.dubbo.samples.provider;
|
||||
|
||||
import org.apache.dubbo.samples.api.GreetingsService;
|
||||
|
||||
public class GreetingsServiceImpl implements GreetingsService {
|
||||
@Override
|
||||
public String sayHi(String name) {
|
||||
return "hi, " + name;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*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.*
|
||||
|
||||
### Start service provider
|
||||
|
||||
```java
|
||||
package org.apache.dubbo.samples.provider;
|
||||
|
||||
|
||||
import org.apache.dubbo.config.ApplicationConfig;
|
||||
import org.apache.dubbo.config.RegistryConfig;
|
||||
import org.apache.dubbo.config.ServiceConfig;
|
||||
import org.apache.dubbo.samples.api.GreetingsService;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
public class Application {
|
||||
private static String zookeeperHost = System.getProperty("zookeeper.address", "127.0.0.1");
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ServiceConfig<GreetingsService> service = new ServiceConfig<>();
|
||||
service.setApplication(new ApplicationConfig("first-dubbo-provider"));
|
||||
service.setRegistry(new RegistryConfig("zookeeper://" + zookeeperHost + ":2181"));
|
||||
service.setInterface(GreetingsService.class);
|
||||
service.setRef(new GreetingsServiceImpl());
|
||||
service.export();
|
||||
|
||||
System.out.println("dubbo service started");
|
||||
new CountDownLatch(1).await();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*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.*
|
||||
|
||||
### Build and run the provider
|
||||
|
||||
```bash
|
||||
mvn clean package
|
||||
mvn -Djava.net.preferIPv4Stack=true -Dexec.mainClass=org.apache.dubbo.samples.provider.Application exec:java
|
||||
```
|
||||
|
||||
### Call remote service in the consumer
|
||||
|
||||
```java
|
||||
package org.apache.dubbo.samples.client;
|
||||
|
||||
|
||||
import org.apache.dubbo.config.ApplicationConfig;
|
||||
import org.apache.dubbo.config.ReferenceConfig;
|
||||
import org.apache.dubbo.config.RegistryConfig;
|
||||
import org.apache.dubbo.samples.api.GreetingsService;
|
||||
|
||||
public class Application {
|
||||
private static String zookeeperHost = System.getProperty("zookeeper.address", "127.0.0.1");
|
||||
|
||||
public static void main(String[] args) {
|
||||
ReferenceConfig<GreetingsService> reference = new ReferenceConfig<>();
|
||||
reference.setApplication(new ApplicationConfig("first-dubbo-consumer"));
|
||||
reference.setRegistry(new RegistryConfig("zookeeper://" + zookeeperHost + ":2181"));
|
||||
reference.setInterface(GreetingsService.class);
|
||||
GreetingsService service = reference.get();
|
||||
String message = service.sayHi("dubbo");
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
```
|
||||
*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.*
|
||||
|
||||
### Build and run the consumer
|
||||
|
||||
```bash
|
||||
mvn clean package
|
||||
mvn -Djava.net.preferIPv4Stack=true -Dexec.mainClass=org.apache.dubbo.samples.client.Application exec:java
|
||||
```
|
||||
|
||||
The consumer will print out `hi, dubbo` on the screen.
|
||||
|
||||
|
||||
### 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.
|
||||
* [Dubbo user manual](https://dubbo.apache.org/en/overview/what/) - 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 admin manual](https://dubbo.apache.org/en/docs/v2.7/admin/ops/) - How to admin and manage Dubbo services.
|
||||
|
||||
## Building
|
||||
|
||||
If you want to try out the cutting-edge features, you can build with the following commands. (Java 1.8 is needed to build the master branch)
|
||||
|
||||
```
|
||||
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
|
||||
|
||||
* 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)
|
||||
|
||||
* Bugs: [Issues](https://github.com/apache/dubbo/issues/new?template=dubbo-issue-report-template.md)
|
||||
* Gitter: [Gitter channel](https://gitter.im/alibaba/dubbo)
|
||||
* Twitter: [@ApacheDubbo](https://twitter.com/ApacheDubbo)
|
||||
|
||||
## 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 Website](https://github.com/apache/dubbo-website) - Apache Dubbo official website
|
||||
* [Dubbo Samples](https://github.com/apache/dubbo-samples) - samples for Apache Dubbo
|
||||
* [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
|
||||
|
||||
#### Language
|
||||
|
||||
* [Go](https://github.com/apache/dubbo-go) (recommended)
|
||||
* [Rust](https://github.com/apache/dubbo-rust)
|
||||
* [Node.js](https://github.com/apache/dubbo-js)
|
||||
* [Python](https://github.com/dubbo/py-client-for-apache-dubbo)
|
||||
* [PHP](https://github.com/apache/dubbo-php-framework)
|
||||
* [Erlang](https://github.com/apache/dubbo-erlang)
|
||||
|
||||
## 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.
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Below is a table that shows versions that we accept security fixes.
|
||||
|
||||
| Version | Supported |
|
||||
|---------| ------------------ |
|
||||
| 3.3.x | :white_check_mark: |
|
||||
| 3.2.x | :white_check_mark: |
|
||||
| 3.1.x | :white_check_mark: |
|
||||
| 3.0.x | :x: |
|
||||
| 2.7.x | :x: |
|
||||
| 2.6.x | :x: |
|
||||
| 2.5.x | :x: |
|
||||
|
||||
## 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.
|
||||
|
||||
If you have apprehensions regarding Dubbo's security or you discover vulnerability or potential threat, don’t hesitate to get in touch with the Apache Dubbo Security Team by dropping a mail at security@dubbo.apache.org. In the email, specify the description of the issue or potential threat. You are also urged to recommend the way to reproduce and replicate the issue. The Dubbo community will get back to you after assessing and analysing the findings.
|
||||
|
||||
PLEASE PAY ATTENTION to report the security issue on the security email before disclosing it on public domain.
|
||||
|
||||
## Vulnerability Handling
|
||||
|
||||
An overview of the vulnerability handling process is:
|
||||
|
||||
* The reporter reports the vulnerability privately to Apache.
|
||||
* The appropriate project's security team works privately with the reporter to resolve the vulnerability.
|
||||
* A new release of the Apache product concerned is made that includes the fix.
|
||||
* The vulnerability is publicly announced.
|
||||
|
||||
A more detailed description of the process can be found [here](https://www.apache.org/security/committers.html).
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
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
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE suppressions PUBLIC
|
||||
"-//Puppy Crawl//DTD Suppressions 1.1//EN"
|
||||
"http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
|
||||
<suppressions>
|
||||
<suppress files="[\\/]src[\\/]main[\\/]java[\\/]com[\\/]alibaba[\\/]com[\\/]caucho[\\/]hessian" checks=".*"/>
|
||||
<suppress files="[\\/]build[\\/]generated[\\/]source[\\/]proto" checks=".*"/>
|
||||
<suppress files="[\\/]target[\\/]generated-sources[\\/]protobuf" checks=".*"/>
|
||||
<suppress files="Yylex\.java" checks="AvoidEscapedUnicodeCharacters"/>
|
||||
</suppressions>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module PUBLIC
|
||||
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
||||
"http://checkstyle.sourceforge.net/dtds/configuration_1_3.dtd">
|
||||
|
||||
<module name="Checker">
|
||||
<property name="charset" value="UTF-8"/>
|
||||
<property name="fileExtensions" value="java"/>
|
||||
|
||||
<module name="Header">
|
||||
<property name="headerFile" value="/checkstyle-header.txt"/>
|
||||
<property name="fileExtensions" value="java"/>
|
||||
</module>
|
||||
|
||||
<module name="FileTabCharacter">
|
||||
<property name="fileExtensions" value="java,xml"/>
|
||||
</module>
|
||||
|
||||
<!-- TreeWalker Checks -->
|
||||
<module name="TreeWalker">
|
||||
<module name="SuppressWarningsHolder"/>
|
||||
|
||||
<module name="AvoidStarImport"/>
|
||||
<module name="AvoidEscapedUnicodeCharacters">
|
||||
<property name="allowEscapesForControlCharacters" value="true"/>
|
||||
<property name="allowByTailComment" value="true"/>
|
||||
<property name="allowNonPrintableEscapes" value="true"/>
|
||||
</module>
|
||||
<module name="NoLineWrap"/>
|
||||
<module name="OuterTypeFilename"/>
|
||||
<module name="UnusedImports"/>
|
||||
<module name="RedundantImport"/>
|
||||
|
||||
<module name="EqualsHashCode"/>
|
||||
|
||||
<!--<module name="CustomImportOrder">-->
|
||||
<!--<property name="specialImportsRegExp" value="org.apache.dubbo.*"/>-->
|
||||
<!--<property name="sortImportsInGroupAlphabetically" value="false"/>-->
|
||||
<!--<property name="customImportOrderRules" value="SPECIAL_IMPORTS###THIRD_PARTY_PACKAGE###STANDARD_JAVA_PACKAGE###STATIC"/>-->
|
||||
<!--</module>-->
|
||||
</module>
|
||||
</module>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module PUBLIC
|
||||
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
||||
"http://checkstyle.sourceforge.net/dtds/configuration_1_3.dtd">
|
||||
|
||||
<module name="Checker">
|
||||
<module name="NewlineAtEndOfFile">
|
||||
<property name="lineSeparator" value="lf" />
|
||||
</module>
|
||||
</module>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<code_scheme name="dubbo_codestyle">
|
||||
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99"/>
|
||||
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99"/>
|
||||
<option name="IMPORT_LAYOUT_TABLE">
|
||||
<value>
|
||||
<package name="org.apache.dubbo" withSubpackages="true" static="false"/>
|
||||
<emptyLine/>
|
||||
<package name="" withSubpackages="true" static="false"/>
|
||||
<emptyLine/>
|
||||
<package name="javax" withSubpackages="true" static="false"/>
|
||||
<package name="java" withSubpackages="true" static="false"/>
|
||||
<emptyLine/>
|
||||
<package name="" withSubpackages="true" static="true"/>
|
||||
</value>
|
||||
</option>
|
||||
</code_scheme>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 430 B |
|
|
@ -0,0 +1,89 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-build-tools</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<maven.deploy.skip>true</maven.deploy.skip>
|
||||
<spotless-maven-plugin.version>2.43.0</spotless-maven-plugin.version>
|
||||
<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>
|
||||
<profile>
|
||||
<id>java11+</id>
|
||||
<activation>
|
||||
<jdk>[11,)</jdk>
|
||||
</activation>
|
||||
<build>
|
||||
<!--- newer versions of plugins requires JDK 11 -->
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.diffplug.spotless</groupId>
|
||||
<artifactId>spotless-maven-plugin</artifactId>
|
||||
<version>${spotless-maven-plugin.version}</version>
|
||||
<configuration>
|
||||
<java>
|
||||
<palantirJavaFormat>
|
||||
<version>${palantirJavaFormat.version}</version>
|
||||
</palantirJavaFormat>
|
||||
<removeUnusedImports />
|
||||
<importOrder>
|
||||
<file>dubbo-importorder.txt</file>
|
||||
</importOrder>
|
||||
<licenseHeader>
|
||||
<file>checkstyle-header.txt</file>
|
||||
</licenseHeader>
|
||||
</java>
|
||||
<pom>
|
||||
<sortPom>
|
||||
<expandEmptyElements>false</expandEmptyElements>
|
||||
<spaceBeforeCloseEmptyElement>true</spaceBeforeCloseEmptyElement>
|
||||
</sortPom>
|
||||
</pom>
|
||||
<upToDateChecking>
|
||||
<enabled>true</enabled>
|
||||
</upToDateChecking>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-shared-resources</artifactId>
|
||||
<version>${dubbo-shared-resources.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>${spotless.action}</goal>
|
||||
</goals>
|
||||
<phase>process-sources</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
|
@ -1,44 +1,118 @@
|
|||
<!--
|
||||
- Copyright 1999-2011 Alibaba Group.
|
||||
-
|
||||
- Licensed 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.
|
||||
-->
|
||||
<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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-parent</artifactId>
|
||||
<version>2.0.10</version>
|
||||
</parent>
|
||||
<artifactId>dubbo-cluster</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Dubbo Cluster Module</name>
|
||||
<description>The cluster module of dubbo project</description>
|
||||
<properties>
|
||||
<skip_maven_deploy>true</skip_maven_deploy>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-rpc</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.bsf</groupId>
|
||||
<artifactId>bsf-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-parent</artifactId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>dubbo-cluster</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>The cluster module of dubbo project</description>
|
||||
<properties>
|
||||
<skip_maven_deploy>false</skip_maven_deploy>
|
||||
<nashorn-core.version>15.4</nashorn-core.version>
|
||||
</properties>
|
||||
<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>
|
||||
<groupId>org.openjdk.nashorn</groupId>
|
||||
<artifactId>nashorn-core</artifactId>
|
||||
<version>${nashorn-core.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster;
|
||||
|
||||
import com.alibaba.dubbo.common.Adaptive;
|
||||
import com.alibaba.dubbo.common.Extension;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.cluster.support.FailoverCluster;
|
||||
|
||||
/**
|
||||
* Cluster. (SPI, Singleton, ThreadSafe)
|
||||
*
|
||||
* <a href="http://en.wikipedia.org/wiki/Computer_cluster">Cluster</a>
|
||||
* <a href="http://en.wikipedia.org/wiki/Fault-tolerant_system">Fault-Tolerant</a>
|
||||
*
|
||||
* @author william.liangf
|
||||
*/
|
||||
@Extension(FailoverCluster.NAME)
|
||||
public interface Cluster {
|
||||
|
||||
/**
|
||||
* Merge the directory invokers to a virtual invoker.
|
||||
*
|
||||
* @param <T>
|
||||
* @param directory
|
||||
* @return cluster invoker
|
||||
* @throws RpcException
|
||||
*/
|
||||
@Adaptive
|
||||
<T> Invoker<T> merge(Directory<T> directory) throws RpcException;
|
||||
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.dubbo.common.Node;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
|
||||
/**
|
||||
* Directory. (SPI, Singleton, ThreadSafe)
|
||||
*
|
||||
* <a href="http://en.wikipedia.org/wiki/Directory_service">Directory Service</a>
|
||||
*
|
||||
* @see com.alibaba.dubbo.rpc.cluster.Cluster#merge(Directory)
|
||||
* @author william.liangf
|
||||
*/
|
||||
public interface Directory<T> extends Node {
|
||||
|
||||
/**
|
||||
* get service type.
|
||||
*
|
||||
* @return service type.
|
||||
*/
|
||||
Class<T> getInterface();
|
||||
|
||||
/**
|
||||
* list invokers.
|
||||
*
|
||||
* @return invokers
|
||||
*/
|
||||
List<Invoker<T>> list(Invocation invocation) throws RpcException;
|
||||
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.dubbo.common.Extension;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.cluster.loadbalance.RandomLoadBalance;
|
||||
|
||||
/**
|
||||
* LoadBalance. (SPI, Singleton, ThreadSafe)
|
||||
*
|
||||
* <a href="http://en.wikipedia.org/wiki/Load_balancing_(computing)">Load-Balancing</a>
|
||||
*
|
||||
* @see com.alibaba.dubbo.rpc.cluster.Cluster#merge(Directory)
|
||||
* @author qian.lei
|
||||
* @author william.liangf
|
||||
*/
|
||||
@Extension(RandomLoadBalance.NAME)
|
||||
public interface LoadBalance {
|
||||
|
||||
/**
|
||||
* select one invoker in list.
|
||||
*
|
||||
* @param invokers invokers.
|
||||
* @param invocation invocation.
|
||||
* @return selected invoker.
|
||||
*/
|
||||
<T> Invoker<T> select(List<Invoker<T>> invokers, Invocation invocation) throws RpcException;
|
||||
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
|
||||
/**
|
||||
* Router.
|
||||
*
|
||||
* @author chao.liuc
|
||||
*/
|
||||
public interface Router {
|
||||
|
||||
/**
|
||||
* route.
|
||||
*
|
||||
* @param invokers
|
||||
* @param invocation
|
||||
* @return routed invokers
|
||||
* @throws RpcException
|
||||
*/
|
||||
<T> List<Invoker<T>> route(List<Invoker<T>> invokers, Invocation invocation) throws RpcException;
|
||||
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster;
|
||||
|
||||
import com.alibaba.dubbo.common.Adaptive;
|
||||
import com.alibaba.dubbo.common.Extension;
|
||||
import com.alibaba.dubbo.common.URL;
|
||||
|
||||
/**
|
||||
* RouterFactory. (SPI, Singleton, ThreadSafe)
|
||||
*
|
||||
* @author chao.liuc
|
||||
*/
|
||||
@Extension
|
||||
public interface RouterFactory {
|
||||
|
||||
/**
|
||||
* Create router.
|
||||
*
|
||||
* @param url
|
||||
* @return router
|
||||
*/
|
||||
@Adaptive("protocol")
|
||||
Router getRouter(URL url);
|
||||
|
||||
}
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.directory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.dubbo.common.URL;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.cluster.Router;
|
||||
import com.alibaba.dubbo.rpc.cluster.support.AbstractDirectory;
|
||||
|
||||
/**
|
||||
* StaticDirectory
|
||||
*
|
||||
* @author william.liangf
|
||||
*/
|
||||
public class StaticDirectory<T> extends AbstractDirectory<T> {
|
||||
|
||||
private final List<Invoker<T>> invokers;
|
||||
|
||||
public StaticDirectory(List<Invoker<T>> invokers){
|
||||
this(null, invokers, null);
|
||||
}
|
||||
|
||||
public StaticDirectory(List<Invoker<T>> invokers, List<Router> routers){
|
||||
this(null, invokers, routers);
|
||||
}
|
||||
|
||||
public StaticDirectory(URL url, List<Invoker<T>> invokers) {
|
||||
this(url, invokers, null);
|
||||
}
|
||||
|
||||
public StaticDirectory(URL url, List<Invoker<T>> invokers, List<Router> routers) {
|
||||
super(url == null && invokers != null && invokers.size() > 0 ? invokers.get(0).getUrl() : url, routers);
|
||||
if (invokers == null || invokers.size() == 0)
|
||||
throw new IllegalArgumentException("invokers == null");
|
||||
this.invokers = invokers;
|
||||
}
|
||||
|
||||
public Class<T> getInterface() {
|
||||
return invokers.get(0).getInterface();
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
if (destroyed) return false;
|
||||
for (Invoker<T> invoker : invokers) {
|
||||
if (invoker.isAvailable()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
if(destroyed) {
|
||||
return;
|
||||
}
|
||||
super.destroy();
|
||||
for (Invoker<T> invoker : invokers) {
|
||||
invoker.destroy();
|
||||
}
|
||||
invokers.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Invoker<T>> doList(Invocation invocation) throws RpcException {
|
||||
|
||||
return invokers;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.loadbalance;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.dubbo.common.Constants;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.cluster.LoadBalance;
|
||||
|
||||
/**
|
||||
* AbstractLoadBalance
|
||||
*
|
||||
* @author william.liangf
|
||||
*/
|
||||
public abstract class AbstractLoadBalance implements LoadBalance {
|
||||
|
||||
public <T> Invoker<T> select(List<Invoker<T>> invokers, Invocation invocation) {
|
||||
if (invokers == null || invokers.size() == 0)
|
||||
return null;
|
||||
if (invokers.size() == 1)
|
||||
return invokers.get(0);
|
||||
return doSelect(invokers, invocation);
|
||||
}
|
||||
|
||||
protected abstract <T> Invoker<T> doSelect(List<Invoker<T>> invokers, Invocation invocation);
|
||||
|
||||
protected int getWeight(Invoker<?> invoker, Invocation invocation) {
|
||||
return invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.loadbalance;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import com.alibaba.dubbo.common.Constants;
|
||||
import com.alibaba.dubbo.common.Extension;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.RpcStatus;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
|
||||
/**
|
||||
* LeastActiveLoadBalance
|
||||
*
|
||||
* @author william.liangf
|
||||
*/
|
||||
@Extension(LeastActiveLoadBalance.NAME)
|
||||
public class LeastActiveLoadBalance extends AbstractLoadBalance {
|
||||
public static final String NAME = "leastactive";
|
||||
|
||||
private final Random random = new Random();
|
||||
|
||||
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, Invocation invocation) {
|
||||
int length = invokers.size(); // 总个数
|
||||
int leastActive = -1; // 最小的活跃数
|
||||
int leastCount = 0; // 相同最小活跃数的个数
|
||||
int[] leastIndexs = new int[length]; // 相同最小活跃数的下标
|
||||
int totalWeight = 0; // 总权重
|
||||
int firstWeight = 0; // 第一个权重,用于于计算是否相同
|
||||
boolean sameWeight = true; // 是否所有权重相同
|
||||
for (int i = 0; i < length; i++) {
|
||||
Invoker<T> invoker = invokers.get(i);
|
||||
int active = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName()).getActive(); // 活跃数
|
||||
int weight = invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT); // 权重
|
||||
if (leastActive == -1 || active < leastActive) { // 发现更小的活跃数,重新开始
|
||||
leastActive = active; // 记录最小活跃数
|
||||
leastCount = 1; // 重新统计相同最小活跃数的个数
|
||||
leastIndexs[0] = i; // 重新记录最小活跃数下标
|
||||
totalWeight = weight; // 重新累计总权重
|
||||
firstWeight = weight; // 记录第一个权重
|
||||
sameWeight = true; // 还原权重相同标识
|
||||
} else if (active == leastActive) { // 累计相同最小的活跃数
|
||||
leastIndexs[leastCount ++] = i; // 累计相同最小活跃数下标
|
||||
totalWeight += weight; // 累计总权重
|
||||
// 判断所有权重是否一样
|
||||
if (sameWeight && i > 0
|
||||
&& weight != firstWeight) {
|
||||
sameWeight = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// assert(leastCount > 0)
|
||||
if (leastCount == 1) {
|
||||
// 如果只有一个最小则直接返回
|
||||
return invokers.get(leastIndexs[0]);
|
||||
}
|
||||
if (! sameWeight && totalWeight > 0) {
|
||||
// 如果权重不相同且权重大于0则按总权重数随机
|
||||
int offsetWeight = random.nextInt(totalWeight);
|
||||
// 并确定随机值落在哪个片断上
|
||||
for (int i = 0; i < leastCount; i++) {
|
||||
int leastIndex = leastIndexs[i];
|
||||
offsetWeight -= getWeight(invokers.get(leastIndex), invocation);
|
||||
if (offsetWeight <= 0)
|
||||
return invokers.get(leastIndex);
|
||||
}
|
||||
}
|
||||
// 如果权重相同或权重为0则均等随机
|
||||
return invokers.get(leastIndexs[random.nextInt(leastCount)]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.loadbalance;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.dubbo.common.Adaptive;
|
||||
import com.alibaba.dubbo.common.Constants;
|
||||
import com.alibaba.dubbo.common.ExtensionLoader;
|
||||
import com.alibaba.dubbo.common.URL;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.cluster.LoadBalance;
|
||||
|
||||
/**
|
||||
* LoadBalanceAdptive
|
||||
*
|
||||
* @author ding.lid
|
||||
* @author william.liangf
|
||||
*/
|
||||
@Adaptive
|
||||
public class LoadBalanceAdptive implements LoadBalance {
|
||||
public <T> Invoker<T> select(List<Invoker<T>> invokers, Invocation invocation) throws RpcException {
|
||||
if (invokers == null || invokers.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
URL url = invokers.get(0).getUrl();
|
||||
String method = invocation.getMethodName();
|
||||
String name;
|
||||
if (method == null || method.length() == 0) {
|
||||
name = url.getParameter(Constants.LOADBALANCE_KEY, Constants.DEFAULT_LOADBALANCE);
|
||||
} else {
|
||||
name = url.getMethodParameter(method, Constants.LOADBALANCE_KEY, Constants.DEFAULT_LOADBALANCE);
|
||||
}
|
||||
LoadBalance loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(name);
|
||||
return loadbalance.select(invokers, invocation);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.loadbalance;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import com.alibaba.dubbo.common.Extension;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
|
||||
/**
|
||||
* random load balance.
|
||||
*
|
||||
* @author qianlei
|
||||
* @author william.liangf
|
||||
*/
|
||||
@Extension(RandomLoadBalance.NAME)
|
||||
public class RandomLoadBalance extends AbstractLoadBalance {
|
||||
public static final String NAME = "random";
|
||||
|
||||
private final Random random = new Random();
|
||||
|
||||
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, Invocation invocation) {
|
||||
int length = invokers.size(); // 总个数
|
||||
int totalWeight = 0; // 总权重
|
||||
boolean sameWeight = true; // 权重是否都一样
|
||||
for (int i = 0; i < length; i++) {
|
||||
// 获取权重
|
||||
int weight = getWeight(invokers.get(i), invocation);
|
||||
// 累计总权重
|
||||
totalWeight += weight;
|
||||
// 判断所有权重是否一样
|
||||
if (sameWeight && i > 0
|
||||
&& weight != getWeight(invokers.get(i - 1), invocation)) {
|
||||
sameWeight = false;
|
||||
}
|
||||
}
|
||||
if (!sameWeight && totalWeight > 0) {
|
||||
// 如果权重不相同且权重大于0则按总权重数随机
|
||||
int offset = random.nextInt(totalWeight);
|
||||
// 并确定随机值落在哪个片断上
|
||||
for (int i = 0; i < length; i++) {
|
||||
offset -= getWeight(invokers.get(i), invocation);
|
||||
if (offset < 0) {
|
||||
return invokers.get(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 如果权重相同或权重为0则均等随机
|
||||
return invokers.get(random.nextInt(length));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.loadbalance;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import com.alibaba.dubbo.common.Extension;
|
||||
import com.alibaba.dubbo.common.utils.AtomicPositiveInteger;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
|
||||
/**
|
||||
* Round robin load balance.
|
||||
*
|
||||
* @author qian.lei
|
||||
* @author william.liangf
|
||||
*/
|
||||
@Extension(RoundRobinLoadBalance.NAME)
|
||||
public class RoundRobinLoadBalance extends AbstractLoadBalance {
|
||||
public static final String NAME = "roundrobin";
|
||||
|
||||
private final ConcurrentMap<String, AtomicPositiveInteger> sequences = new ConcurrentHashMap<String, AtomicPositiveInteger>();
|
||||
|
||||
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, Invocation invocation) {
|
||||
String key = invokers.get(0).getInterface().getName() + "." + invocation.getMethodName();// + System.identityHashCode(invokers);
|
||||
AtomicPositiveInteger sequence = sequences.get(key);
|
||||
if (sequence == null) {
|
||||
sequences.putIfAbsent(key, new AtomicPositiveInteger());
|
||||
sequence = sequences.get(key);
|
||||
}
|
||||
// 取模轮循
|
||||
return invokers.get(sequence.getAndIncrement() % invokers.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.router;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.alibaba.dubbo.common.Extension;
|
||||
import com.alibaba.dubbo.common.URL;
|
||||
import com.alibaba.dubbo.common.utils.IOUtils;
|
||||
import com.alibaba.dubbo.rpc.RpcConstants;
|
||||
import com.alibaba.dubbo.rpc.cluster.Router;
|
||||
import com.alibaba.dubbo.rpc.cluster.RouterFactory;
|
||||
|
||||
@Extension(FileRouterFactory.NAME)
|
||||
public class FileRouterFactory implements RouterFactory {
|
||||
|
||||
public static final String NAME = "file";
|
||||
|
||||
private RouterFactory routerFactory;
|
||||
|
||||
public void setRouterFactory(RouterFactory routerFactory) {
|
||||
this.routerFactory = routerFactory;
|
||||
}
|
||||
|
||||
public Router getRouter(URL url) {
|
||||
try {
|
||||
// File URL 转换成 其它Route URL,然后Load
|
||||
// file:///d:/path/to/route.js?router=script ==> script:///d:/path/to/route.js?type=js&rule=<file-content>
|
||||
String protocol = url.getParameter(RpcConstants.ROUTER_KEY, ScriptRouterFactory.NAME); // 将原类型转为协议
|
||||
String type = null; // 使用文件后缀做为类型
|
||||
String path = url.getPath();
|
||||
if (path != null) {
|
||||
int i = path.lastIndexOf('.');
|
||||
if (i > 0) {
|
||||
type = path.substring(i + 1);
|
||||
}
|
||||
}
|
||||
String rule = IOUtils.read(new FileReader(new File(url.getAbsolutePath())));
|
||||
URL script = url.setProtocol(protocol).addParameter(RpcConstants.TYPE_KEY, type).addParameterAndEncoded(RpcConstants.RULE_KEY, rule);
|
||||
|
||||
return routerFactory.getRouter(script);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.router;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.script.Bindings;
|
||||
import javax.script.Compilable;
|
||||
import javax.script.CompiledScript;
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
import com.alibaba.dubbo.common.URL;
|
||||
import com.alibaba.dubbo.common.logger.Logger;
|
||||
import com.alibaba.dubbo.common.logger.LoggerFactory;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.RpcConstants;
|
||||
import com.alibaba.dubbo.rpc.RpcContext;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.cluster.Router;
|
||||
|
||||
/**
|
||||
* ScriptRouter
|
||||
*
|
||||
* @author william.liangf
|
||||
*/
|
||||
public class ScriptRouter implements Router {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ScriptRouter.class);
|
||||
|
||||
private static final Map<String, ScriptEngine> engines = new ConcurrentHashMap<String, ScriptEngine>();
|
||||
|
||||
private final ScriptEngine engine;
|
||||
|
||||
private final String rule;
|
||||
|
||||
public ScriptRouter(URL url) {
|
||||
String type = url.getParameter(RpcConstants.TYPE_KEY);
|
||||
String rule = url.getParameterAndDecoded(RpcConstants.RULE_KEY);
|
||||
if (type == null || type.length() == 0){
|
||||
type = RpcConstants.DEFAULT_SCRIPT_TYPE_KEY;
|
||||
}
|
||||
if (rule == null || rule.length() == 0){
|
||||
throw new IllegalStateException(new IllegalStateException("route rule can not be empty. rule:" + rule));
|
||||
}
|
||||
ScriptEngine engine = engines.get(type);
|
||||
if (engine == null){
|
||||
engine = new ScriptEngineManager().getEngineByName(type);
|
||||
if (engine == null) {
|
||||
throw new IllegalStateException(new IllegalStateException("Unsupported route rule type: " + type + ", rule: " + rule));
|
||||
}
|
||||
engines.put(type, engine);
|
||||
}
|
||||
this.engine = engine;
|
||||
this.rule = rule;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, Invocation invocation) throws RpcException {
|
||||
try {
|
||||
List<Invoker<T>> invokersCopy = new ArrayList<Invoker<T>>(invokers);
|
||||
Compilable compilable = (Compilable) engine;
|
||||
Bindings bindings = engine.createBindings();
|
||||
bindings.put("invokers", invokersCopy);
|
||||
bindings.put("invocation", invocation);
|
||||
bindings.put("context", RpcContext.getContext());
|
||||
CompiledScript function = compilable.compile(rule);
|
||||
Object obj = function.eval(bindings);
|
||||
if (obj instanceof Invoker[]) {
|
||||
invokersCopy = Arrays.asList((Invoker<T>[]) obj);
|
||||
} else if (obj instanceof Object[]) {
|
||||
invokersCopy = new ArrayList<Invoker<T>>();
|
||||
for (Object inv : (Object[]) obj) {
|
||||
invokersCopy.add((Invoker<T>)inv);
|
||||
}
|
||||
} else {
|
||||
invokersCopy = (List<Invoker<T>>) obj;
|
||||
}
|
||||
return invokersCopy;
|
||||
} catch (ScriptException e) {
|
||||
//fail then ignore rule .invokers.
|
||||
logger.error("route error , rule has been ignored .rule :"+ rule + ",invocation:" + invocation + ",url :"+(RpcContext.getContext().getInvoker() == null ? "" : RpcContext.getContext().getInvoker().getUrl()), e);
|
||||
return invokers;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.router;
|
||||
|
||||
import com.alibaba.dubbo.common.Extension;
|
||||
import com.alibaba.dubbo.common.URL;
|
||||
import com.alibaba.dubbo.rpc.cluster.Router;
|
||||
import com.alibaba.dubbo.rpc.cluster.RouterFactory;
|
||||
|
||||
/**
|
||||
* ScriptRouterFactory
|
||||
*
|
||||
* Script Router Factory用到的URL形如:
|
||||
* <ol>
|
||||
* <li> script://registyAddress?type=js&rule=xxxx
|
||||
* <li> script:///path/to/routerfile.js?type=js&rule=xxxx
|
||||
* <li> script://D:\path\to\routerfile.js?type=js&rule=xxxx
|
||||
* <li> script://C:/path/to/routerfile.js?type=js&rule=xxxx
|
||||
* </ol>
|
||||
* URL的Host一段包含的是Script Router内容的来源,Registry、File etc
|
||||
*
|
||||
* @author william.liangf
|
||||
*/
|
||||
@Extension(ScriptRouterFactory.NAME)
|
||||
public class ScriptRouterFactory implements RouterFactory {
|
||||
|
||||
public static final String NAME = "script";
|
||||
|
||||
public Router getRouter(URL url) {
|
||||
return new ScriptRouter(url);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,240 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.dubbo.common.Constants;
|
||||
import com.alibaba.dubbo.common.ExtensionLoader;
|
||||
import com.alibaba.dubbo.common.URL;
|
||||
import com.alibaba.dubbo.common.Version;
|
||||
import com.alibaba.dubbo.common.logger.Logger;
|
||||
import com.alibaba.dubbo.common.logger.LoggerFactory;
|
||||
import com.alibaba.dubbo.common.utils.NetUtils;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.Result;
|
||||
import com.alibaba.dubbo.rpc.RpcConstants;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.cluster.Directory;
|
||||
import com.alibaba.dubbo.rpc.cluster.LoadBalance;
|
||||
|
||||
/**
|
||||
* AbstractRpcRouter
|
||||
*
|
||||
* @author william.liangf
|
||||
* @author chao.liuc
|
||||
*/
|
||||
public abstract class AbstractClusterInvoker<T> implements Invoker<T> {
|
||||
|
||||
private static final Logger logger = LoggerFactory
|
||||
.getLogger(AbstractClusterInvoker.class);
|
||||
protected final Directory<T> directory;
|
||||
|
||||
protected final boolean availablecheck;
|
||||
|
||||
private volatile boolean destroyed = false;
|
||||
|
||||
private volatile Invoker<T> stickyInvoker = null;
|
||||
|
||||
|
||||
public AbstractClusterInvoker(Directory<T> directory) {
|
||||
this(directory, directory.getUrl());
|
||||
}
|
||||
public AbstractClusterInvoker(Directory<T> directory, URL url) {
|
||||
if (directory == null)
|
||||
throw new IllegalArgumentException("service directory == null");
|
||||
|
||||
this.directory = directory ;
|
||||
this.availablecheck = url.getParameter(RpcConstants.CLUSTER_AVAILABLE_CHECK_KEY, RpcConstants.DEFAULT_CLUSTER_AVAILABLE_CHECK) ;
|
||||
}
|
||||
|
||||
public Class<T> getInterface() {
|
||||
return directory.getInterface();
|
||||
}
|
||||
|
||||
public URL getUrl() {
|
||||
return directory.getUrl();
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
Invoker<T> invoker = stickyInvoker;
|
||||
if (invoker != null) {
|
||||
return invoker.isAvailable();
|
||||
}
|
||||
return directory.isAvailable();
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
directory.destroy();
|
||||
destroyed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用loadbalance选择invoker.</br>
|
||||
* a)先lb选择,如果在selected列表中 或者 不可用且做检验时,进入下一步(重选),否则直接返回</br>
|
||||
* b)重选验证规则:selected > available .保证重选出的结果尽量不在select中,并且是可用的
|
||||
*
|
||||
* @param availablecheck 如果设置true,在选择的时候先选invoker.available == true
|
||||
* @param selected 已选过的invoker.注意:输入保证不重复
|
||||
*
|
||||
*/
|
||||
protected Invoker<T> select(LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, List<Invoker<T>> selected) throws RpcException {
|
||||
if (invokers == null || invokers.size() == 0)
|
||||
return null;
|
||||
String methodName = invocation == null ? "" : invocation.getMethodName();
|
||||
|
||||
boolean sticky = invokers.get(0).getUrl().getMethodParameter(methodName,RpcConstants.CLUSTER_STICKY_KEY, RpcConstants.DEFAULT_CLUSTER_STICKY) ;
|
||||
{
|
||||
//ignore overloaded method
|
||||
if ( stickyInvoker != null && !invokers.contains(stickyInvoker) ){
|
||||
stickyInvoker = null;
|
||||
}
|
||||
//ignore cucurrent problem
|
||||
if (sticky && stickyInvoker != null && (selected == null || !selected.contains(stickyInvoker))){
|
||||
if (availablecheck && stickyInvoker.isAvailable()){
|
||||
return stickyInvoker;
|
||||
}
|
||||
}
|
||||
}
|
||||
Invoker<T> invoker = doselect(loadbalance, invocation, invokers, selected);
|
||||
|
||||
if (sticky){
|
||||
stickyInvoker = invoker;
|
||||
}
|
||||
return invoker;
|
||||
}
|
||||
|
||||
private Invoker<T> doselect(LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, List<Invoker<T>> selected) throws RpcException {
|
||||
if (invokers == null || invokers.size() == 0)
|
||||
return null;
|
||||
if (invokers.size() == 1)
|
||||
return invokers.get(0);
|
||||
// 如果只有两个invoker,退化成轮循
|
||||
if (invokers.size() == 2 && selected != null && selected.size() > 0) {
|
||||
return selected.get(0) == invokers.get(0) ? invokers.get(1) : invokers.get(0);
|
||||
}
|
||||
Invoker<T> invoker = loadbalance.select(invokers, invocation);
|
||||
|
||||
//如果 selected中包含(优先判断) 或者 不可用&&availablecheck=true 则重试.
|
||||
if( (selected != null && selected.contains(invoker))
|
||||
||(!invoker.isAvailable() && getUrl()!=null && availablecheck)){
|
||||
try{
|
||||
Invoker<T> rinvoker = reselect(loadbalance, invocation, invokers, selected, availablecheck);
|
||||
if(rinvoker != null){
|
||||
invoker = rinvoker;
|
||||
}else{
|
||||
//看下第一次选的位置,如果不是最后,选+1位置.
|
||||
int index = invokers.indexOf(invoker);
|
||||
try{
|
||||
//最后在避免碰撞
|
||||
invoker = index <invokers.size()-1?invokers.get(index+1) :invoker;
|
||||
}catch (Exception e) {
|
||||
logger.warn(e.getMessage()+" may because invokers list dynamic change, ignore.",e);
|
||||
}
|
||||
}
|
||||
}catch (Throwable t){
|
||||
logger.error("clustor relselect fail reason is :"+t.getMessage() +" if can not slove ,you can set cluster.availablecheck=false in url",t);
|
||||
}
|
||||
}
|
||||
return invoker;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重选,先从非selected的列表中选择,没有在从selected列表中选择.
|
||||
* @param loadbalance
|
||||
* @param invocation
|
||||
* @param invokers
|
||||
* @param selected
|
||||
* @return
|
||||
* @throws RpcException
|
||||
*/
|
||||
private Invoker<T> reselect(LoadBalance loadbalance,Invocation invocation,
|
||||
List<Invoker<T>> invokers, List<Invoker<T>> selected ,boolean availablecheck)
|
||||
throws RpcException {
|
||||
|
||||
//预先分配一个,这个列表是一定会用到的.
|
||||
List<Invoker<T>> reselectInvokers = new ArrayList<Invoker<T>>(invokers.size()>1?(invokers.size()-1):invokers.size());
|
||||
|
||||
//先从非select中选
|
||||
if( availablecheck ){ //选isAvailable 的非select
|
||||
for(Invoker<T> invoker : invokers){
|
||||
if(invoker.isAvailable()){
|
||||
if(selected ==null || !selected.contains(invoker)){
|
||||
reselectInvokers.add(invoker);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(reselectInvokers.size()>0){
|
||||
return loadbalance.select(reselectInvokers, invocation);
|
||||
}
|
||||
}else{ //选全部非select
|
||||
for(Invoker<T> invoker : invokers){
|
||||
if(selected ==null || !selected.contains(invoker)){
|
||||
reselectInvokers.add(invoker);
|
||||
}
|
||||
}
|
||||
if(reselectInvokers.size()>0){
|
||||
return loadbalance.select(reselectInvokers, invocation);
|
||||
}
|
||||
}
|
||||
//最后从select中选可用的.
|
||||
{
|
||||
if(selected != null){
|
||||
for(Invoker<T> invoker : selected){
|
||||
if((invoker.isAvailable()) //优先选available
|
||||
&& !reselectInvokers.contains(invoker)){
|
||||
reselectInvokers.add(invoker);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(reselectInvokers.size()>0){
|
||||
return loadbalance.select(reselectInvokers, invocation);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Result invoke(final Invocation invocation) throws RpcException {
|
||||
|
||||
if(destroyed){
|
||||
throw new RpcException("Rpc invoker for " + getInterface() + " on consumer " + NetUtils.getLocalHost()
|
||||
+ " use dubbo version " + Version.getVersion()
|
||||
+ " is not destroyed! Can not invoke any more.");
|
||||
}
|
||||
|
||||
LoadBalance loadbalance;
|
||||
|
||||
List<Invoker<T>> invokers = directory.list(invocation);
|
||||
if (invokers != null && invokers.size() > 0) {
|
||||
loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(invokers.get(0).getUrl()
|
||||
.getMethodParameter(invocation.getMethodName(),Constants.LOADBALANCE_KEY, Constants.DEFAULT_LOADBALANCE));
|
||||
} else {
|
||||
loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(Constants.DEFAULT_LOADBALANCE);
|
||||
}
|
||||
return doInvoke(invocation, invokers, loadbalance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getInterface() + " -> " + getUrl().toString();
|
||||
}
|
||||
|
||||
protected abstract Result doInvoke(Invocation invocation, List<Invoker<T>> invokers,
|
||||
LoadBalance loadbalance) throws RpcException;
|
||||
|
||||
}
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.dubbo.common.Constants;
|
||||
import com.alibaba.dubbo.common.ExtensionLoader;
|
||||
import com.alibaba.dubbo.common.URL;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.cluster.Directory;
|
||||
import com.alibaba.dubbo.rpc.cluster.Router;
|
||||
import com.alibaba.dubbo.rpc.cluster.RouterFactory;
|
||||
|
||||
/**
|
||||
* 增加router的Directory
|
||||
* @author chao.liuc
|
||||
*/
|
||||
public abstract class AbstractDirectory<T> implements Directory<T> {
|
||||
|
||||
private final URL url ;
|
||||
protected volatile boolean destroyed = false;
|
||||
|
||||
private List<Router> routers = new ArrayList<Router>();
|
||||
|
||||
public AbstractDirectory(URL url) {
|
||||
this(url, null);
|
||||
}
|
||||
|
||||
public AbstractDirectory(URL url, List<Router> routers) {
|
||||
if (url == null)
|
||||
throw new IllegalArgumentException("url == null");
|
||||
if (routers == null){
|
||||
routers = new ArrayList<Router>();
|
||||
}
|
||||
|
||||
this.url = url;
|
||||
String routerkey = url.getParameter(Constants.ROUTER_KEY);
|
||||
if (routerkey != null && routerkey.length()>0 ){
|
||||
RouterFactory routerFactory = ExtensionLoader.getExtensionLoader(RouterFactory.class).getExtension(routerkey);
|
||||
routers.add(routerFactory.getRouter(url));
|
||||
}
|
||||
if (routers != null) {
|
||||
setRouters(routers);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Invoker<T>> list(Invocation invocation) throws RpcException {
|
||||
if (destroyed){
|
||||
throw new RpcException("Directory already destroyed .url: "+ getUrl());
|
||||
}
|
||||
List<Invoker<T>> invokers = doList(invocation);
|
||||
for (Router router: routers){
|
||||
invokers = router.route(invokers, invocation);
|
||||
}
|
||||
return invokers;
|
||||
}
|
||||
|
||||
public URL getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public List<Router> getRouters(){
|
||||
return routers;
|
||||
}
|
||||
|
||||
protected abstract List<Invoker<T>> doList(Invocation invocation) throws RpcException ;
|
||||
|
||||
protected void setRouters(List<Router> r){
|
||||
routers = r;
|
||||
}
|
||||
|
||||
public void destroy(){
|
||||
destroyed = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.support;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.dubbo.common.Extension;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.Result;
|
||||
import com.alibaba.dubbo.rpc.cluster.Cluster;
|
||||
import com.alibaba.dubbo.rpc.cluster.Directory;
|
||||
import com.alibaba.dubbo.rpc.cluster.LoadBalance;
|
||||
|
||||
/**
|
||||
* AvailableCluster
|
||||
*
|
||||
* @author william.liangf
|
||||
*/
|
||||
@Extension(AvailableCluster.NAME)
|
||||
public class AvailableCluster implements Cluster {
|
||||
|
||||
public static final String NAME = "available";
|
||||
|
||||
public <T> Invoker<T> merge(Directory<T> directory) throws RpcException {
|
||||
|
||||
return new AbstractClusterInvoker<T>(directory) {
|
||||
public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
|
||||
for (Invoker<T> invoker : invokers) {
|
||||
if (invoker.isAvailable()) {
|
||||
return invoker.invoke(invocation);
|
||||
}
|
||||
}
|
||||
throw new RpcException("No provider available in " + invokers);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.support;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.Result;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.cluster.Directory;
|
||||
import com.alibaba.dubbo.rpc.cluster.LoadBalance;
|
||||
|
||||
/**
|
||||
* AvailableCluster
|
||||
*
|
||||
* @author william.liangf
|
||||
*/
|
||||
public class AvailableClusterInvoker<T> extends AbstractClusterInvoker<T> {
|
||||
public AvailableClusterInvoker(Directory<T> directory) {
|
||||
super(directory);
|
||||
}
|
||||
|
||||
public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
|
||||
for (Invoker<T> invoker : invokers) {
|
||||
if (invoker.isAvailable()) {
|
||||
return invoker.invoke(invocation);
|
||||
}
|
||||
}
|
||||
throw new RpcException("No provider available in " + invokers);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.support;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.dubbo.common.Constants;
|
||||
import com.alibaba.dubbo.common.URL;
|
||||
|
||||
/**
|
||||
* ClusterUtils
|
||||
*
|
||||
* @author william.liangf
|
||||
*/
|
||||
public class ClusterUtils {
|
||||
|
||||
public static URL mergeUrl(URL remoteUrl, Map<String, String> localMap) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
Map<String, String> remoteMap = remoteUrl.getParameters();
|
||||
|
||||
|
||||
if (remoteMap != null && remoteMap.size() > 0) {
|
||||
map.putAll(remoteMap);
|
||||
|
||||
//线程池配置不使用提供者的
|
||||
map.remove(Constants.THREAD_NAME_KEY);
|
||||
map.remove(Constants.THREADS_KEY);
|
||||
map.remove(Constants.QUEUES_KEY);
|
||||
map.remove(Constants.THREAD_ALIVE_KEY);
|
||||
}
|
||||
|
||||
if (localMap != null && localMap.size() > 0) {
|
||||
map.putAll(localMap);
|
||||
}
|
||||
if (remoteMap != null && remoteMap.size() > 0) {
|
||||
// 版本号使用提供者的
|
||||
String dubbo = remoteMap.get(Constants.DUBBO_VERSION_KEY);
|
||||
if (dubbo != null && dubbo.length() > 0) {
|
||||
map.put(Constants.DUBBO_VERSION_KEY, dubbo);
|
||||
}
|
||||
String version = remoteMap.get(Constants.VERSION_KEY);
|
||||
if (version != null && version.length() > 0) {
|
||||
map.put(Constants.VERSION_KEY, version);
|
||||
}
|
||||
String group = remoteMap.get(Constants.GROUP_KEY);
|
||||
if (group != null && group.length() > 0) {
|
||||
map.put(Constants.GROUP_KEY, group);
|
||||
}
|
||||
String methods = remoteMap.get(Constants.METHODS_KEY);
|
||||
if (methods != null && methods.length() > 0) {
|
||||
map.put(Constants.METHODS_KEY, methods);
|
||||
}
|
||||
// 合并filter和listener
|
||||
String remoteFilter = remoteMap.get(Constants.REFERENCE_FILTER_KEY);
|
||||
String localFilter = localMap.get(Constants.REFERENCE_FILTER_KEY);
|
||||
if (remoteFilter != null && remoteFilter.length() > 0
|
||||
&& localFilter != null && localFilter.length() > 0) {
|
||||
localMap.put(Constants.REFERENCE_FILTER_KEY, remoteFilter + "," + localFilter);
|
||||
}
|
||||
String remoteListener = remoteMap.get(Constants.INVOKER_LISTENER_KEY);
|
||||
String localListener = localMap.get(Constants.INVOKER_LISTENER_KEY);
|
||||
if (remoteListener != null && remoteListener.length() > 0
|
||||
&& localListener != null && localListener.length() > 0) {
|
||||
localMap.put(Constants.INVOKER_LISTENER_KEY, remoteListener + "," + localListener);
|
||||
}
|
||||
}
|
||||
return remoteUrl.addParameters(map);
|
||||
}
|
||||
|
||||
private ClusterUtils() {}
|
||||
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.support;
|
||||
|
||||
import com.alibaba.dubbo.common.Extension;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.cluster.Cluster;
|
||||
import com.alibaba.dubbo.rpc.cluster.Directory;
|
||||
|
||||
/**
|
||||
* 失败自动恢复,后台记录失败请求,定时重发,通常用于消息通知操作。
|
||||
*
|
||||
* <a href="http://en.wikipedia.org/wiki/Failback">Failback</a>
|
||||
*
|
||||
* @author william.liangf
|
||||
*/
|
||||
@Extension(FailbackCluster.NAME)
|
||||
public class FailbackCluster implements Cluster {
|
||||
public final static String NAME = "failback";
|
||||
|
||||
public <T> Invoker<T> merge(Directory<T> directory) throws RpcException {
|
||||
return new FailbackClusterInvoker<T>(directory);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.support;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.alibaba.dubbo.common.Version;
|
||||
import com.alibaba.dubbo.common.logger.Logger;
|
||||
import com.alibaba.dubbo.common.logger.LoggerFactory;
|
||||
import com.alibaba.dubbo.common.utils.NamedThreadFactory;
|
||||
import com.alibaba.dubbo.common.utils.NetUtils;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.Result;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.RpcResult;
|
||||
import com.alibaba.dubbo.rpc.cluster.Directory;
|
||||
import com.alibaba.dubbo.rpc.cluster.LoadBalance;
|
||||
|
||||
/**
|
||||
* 失败自动恢复,后台记录失败请求,定时重发,通常用于消息通知操作。
|
||||
*
|
||||
* @author tony.chenl
|
||||
*/
|
||||
public class FailbackClusterInvoker<T> extends AbstractClusterInvoker<T> {
|
||||
|
||||
public FailbackClusterInvoker(Directory<T> directory){
|
||||
super(directory);
|
||||
}
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(FailbackClusterInvoker.class);
|
||||
|
||||
private static final long RETRY_FAILED_PERIOD = 5 * 1000;
|
||||
|
||||
private final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2,
|
||||
new NamedThreadFactory(
|
||||
"failback-cluster-timer",
|
||||
true));
|
||||
|
||||
private volatile ScheduledFuture<?> retryFuture;
|
||||
|
||||
private final ConcurrentMap<Invocation, AbstractClusterInvoker<?>> failed = new ConcurrentHashMap<Invocation, AbstractClusterInvoker<?>>();
|
||||
|
||||
private void addFailed(Invocation invocation, AbstractClusterInvoker<?> router) {
|
||||
if (retryFuture == null) {
|
||||
synchronized (this) {
|
||||
if (retryFuture == null) {
|
||||
retryFuture = scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
|
||||
|
||||
public void run() {
|
||||
// 收集统计信息
|
||||
try {
|
||||
retryFailed();
|
||||
} catch (Throwable t) { // 防御性容错
|
||||
logger.error("Unexpected error occur at collect statistic", t);
|
||||
}
|
||||
}
|
||||
}, RETRY_FAILED_PERIOD, RETRY_FAILED_PERIOD, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
failed.put(invocation, router);
|
||||
}
|
||||
|
||||
void retryFailed() {
|
||||
if (failed.size() == 0) {
|
||||
return;
|
||||
}
|
||||
for (Map.Entry<Invocation, AbstractClusterInvoker<?>> entry : new HashMap<Invocation, AbstractClusterInvoker<?>>(
|
||||
failed).entrySet()) {
|
||||
Invocation invocation = entry.getKey();
|
||||
Invoker<?> invoker = entry.getValue();
|
||||
try {
|
||||
invoker.invoke(invocation);
|
||||
failed.remove(invocation);
|
||||
} catch (Throwable e) {
|
||||
logger.error("Failed retry to invoke " + invocation + ", waiting again.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
|
||||
try {
|
||||
if (invokers == null || invokers.size() == 0)
|
||||
throw new RpcException("No provider available for service " + getInterface().getName() + " on consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", Please check whether the service do exist or version is right firstly, and check the provider has started.");
|
||||
Invoker<T> invoker = select(loadbalance, invocation, invokers, null);
|
||||
return invoker.invoke(invocation);
|
||||
} catch (Throwable e) {
|
||||
logger.error("Failback to invoke " + invocation + ", wait for retry in background. Ignored exception: "
|
||||
+ e.getMessage() + ", ", e);
|
||||
addFailed(invocation, this);
|
||||
return new RpcResult(); // ignore
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.support;
|
||||
|
||||
import com.alibaba.dubbo.common.Extension;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.cluster.Cluster;
|
||||
import com.alibaba.dubbo.rpc.cluster.Directory;
|
||||
|
||||
/**
|
||||
* 快速失败,只发起一次调用,失败立即报错,通常用于非幂等性的写操作。</br>
|
||||
* <a href="http://en.wikipedia.org/wiki/Fail-fast">Fail-fast</a>
|
||||
*
|
||||
* @author william.liangf
|
||||
*/
|
||||
@Extension(FailfastCluster.NAME)
|
||||
public class FailfastCluster implements Cluster {
|
||||
public final static String NAME = "failfast";
|
||||
|
||||
public <T> Invoker<T> merge(Directory<T> directory) throws RpcException {
|
||||
return new FailfastClusterInvoker<T>(directory);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.support;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.dubbo.common.Extension;
|
||||
import com.alibaba.dubbo.common.Version;
|
||||
import com.alibaba.dubbo.common.utils.NetUtils;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.Result;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.cluster.Directory;
|
||||
import com.alibaba.dubbo.rpc.cluster.LoadBalance;
|
||||
|
||||
/**
|
||||
* 快速失败,只发起一次调用,失败立即报错,通常用于非幂等性的写操作。</br>
|
||||
* <a href="http://en.wikipedia.org/wiki/Fail-fast">Fail-fast</a>
|
||||
*
|
||||
* @author william.liangf
|
||||
* @author chao.liuc
|
||||
*
|
||||
*/
|
||||
public class FailfastClusterInvoker<T> extends AbstractClusterInvoker<T>{
|
||||
public FailfastClusterInvoker(Directory<T> directory) {
|
||||
super(directory);
|
||||
}
|
||||
|
||||
public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
|
||||
if (invokers == null || invokers.size() == 0)
|
||||
throw new RpcException("No provider available for service " + getInterface().getName() + " on consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", Please check whether the service do exist or version is right firstly, and check the provider has started.");
|
||||
Invoker<T> invoker = select(loadbalance, invocation, invokers, null);
|
||||
try {
|
||||
return invoker.invoke(invocation);
|
||||
} catch (Throwable e) {
|
||||
throw new RpcException(e instanceof RpcException ? ((RpcException)e).getCode() : 0, "Failfast invoke providers " + invoker.getUrl() + " " + loadbalance.getClass().getAnnotation(Extension.class).value() + " select from all providers " + invokers + " for service " + getInterface().getName() + " method " + invocation.getMethodName() + " on consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", but no luck to perform the invocation. Last error is: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.support;
|
||||
|
||||
import com.alibaba.dubbo.common.Extension;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.cluster.Cluster;
|
||||
import com.alibaba.dubbo.rpc.cluster.Directory;
|
||||
|
||||
/**
|
||||
* 失败转移,当出现失败,重试其它服务器,通常用于读操作,但重试会带来更长延迟。 <a
|
||||
* href="http://en.wikipedia.org/wiki/Failover">Failover</a>
|
||||
*
|
||||
* @author william.liangf
|
||||
*/
|
||||
@Extension(FailoverCluster.NAME)
|
||||
public class FailoverCluster implements Cluster {
|
||||
|
||||
public final static String NAME = "failover";
|
||||
|
||||
public <T> Invoker<T> merge(Directory<T> directory) throws RpcException {
|
||||
|
||||
return new FailoverClusterInvoker<T>(directory);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.alibaba.dubbo.common.Constants;
|
||||
import com.alibaba.dubbo.common.Extension;
|
||||
import com.alibaba.dubbo.common.URL;
|
||||
import com.alibaba.dubbo.common.Version;
|
||||
import com.alibaba.dubbo.common.logger.Logger;
|
||||
import com.alibaba.dubbo.common.logger.LoggerFactory;
|
||||
import com.alibaba.dubbo.common.utils.NetUtils;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.Result;
|
||||
import com.alibaba.dubbo.rpc.RpcContext;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.cluster.Directory;
|
||||
import com.alibaba.dubbo.rpc.cluster.LoadBalance;
|
||||
|
||||
/**
|
||||
* 失败转移,当出现失败,重试其它服务器,通常用于读操作,但重试会带来更长延迟。
|
||||
*
|
||||
* <a href="http://en.wikipedia.org/wiki/Failover">Failover</a>
|
||||
* @author william.liangf
|
||||
*
|
||||
*/
|
||||
public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T>{
|
||||
private static final Logger logger = LoggerFactory.getLogger(FailoverClusterInvoker.class);
|
||||
|
||||
public FailoverClusterInvoker(Directory<T> directory) {
|
||||
super(directory);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
|
||||
if (invokers == null || invokers.size() == 0)
|
||||
throw new RpcException("No provider available for service " + getInterface().getName() + " on consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", Please check whether the service do exist or version is right firstly, and check the provider has started.");
|
||||
|
||||
int len = getUrl().getMethodParameter(invocation.getMethodName(), Constants.RETRIES_KEY, Constants.DEFAULT_RETRIES) + 1;
|
||||
if (len <= 0)
|
||||
len = 1;
|
||||
|
||||
// retry loop.
|
||||
RpcException le = null; // last exception.
|
||||
List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(invokers.size()); // invoked invokers.
|
||||
Set<URL> providers = new HashSet<URL>(len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
Invoker<T> invoker = select(loadbalance, invocation, invokers, invoked);
|
||||
invoked.add(invoker);
|
||||
providers.add(invoker.getUrl());
|
||||
RpcContext.getContext().setInvokers((List)invoked);
|
||||
try {
|
||||
return invoker.invoke(invocation);
|
||||
} catch (RpcException e) {
|
||||
// FIXME 与Failfast的逻辑不一致,有问题!
|
||||
if (e.isBiz()) throw e;
|
||||
|
||||
le = e;
|
||||
logger.warn("" + (i + 1) + "/" + len + " time fail to invoke providers " + providers + " " + loadbalance.getClass().getAnnotation(Extension.class).value()
|
||||
+ " select from all providers " + invokers + " for service " + getInterface().getName() + " method " + invocation.getMethodName()
|
||||
+ " on consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ": " + e.getMessage(), e);
|
||||
} catch (Throwable e) // biz exception.
|
||||
{
|
||||
throw new RpcException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
List<URL> urls = new ArrayList<URL>(invokers.size());
|
||||
for(Invoker<T> invoker : invokers){
|
||||
if(invoker != null )
|
||||
urls.add(invoker.getUrl());
|
||||
}
|
||||
throw new RpcException(le != null ? le.getCode() : 0,
|
||||
"Tried " + len + " times to invoke providers " + providers + " " + loadbalance.getClass().getAnnotation(Extension.class).value()
|
||||
+ " select from all providers " + invokers + " for service " + getInterface().getName() + " method " + invocation.getMethodName()
|
||||
+ " on consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion()
|
||||
+ ", but no luck to perform the invocation. Last error is: " + (le != null ? le.getMessage() : ""), le);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.support;
|
||||
|
||||
import com.alibaba.dubbo.common.Extension;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.cluster.Cluster;
|
||||
import com.alibaba.dubbo.rpc.cluster.Directory;
|
||||
|
||||
/**
|
||||
* 失败安全,出现异常时,直接忽略,通常用于写入审计日志等操作。 <a
|
||||
* href="http://en.wikipedia.org/wiki/Fail-safe">Fail-safe</a>
|
||||
*
|
||||
* @author william.liangf
|
||||
*/
|
||||
@Extension(FailsafeCluster.NAME)
|
||||
public class FailsafeCluster implements Cluster {
|
||||
|
||||
public final static String NAME = "failsafe";
|
||||
|
||||
public <T> Invoker<T> merge(Directory<T> directory) throws RpcException {
|
||||
return new FailsafeClusterInvoker<T>(directory);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.support;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.dubbo.common.Version;
|
||||
import com.alibaba.dubbo.common.logger.Logger;
|
||||
import com.alibaba.dubbo.common.logger.LoggerFactory;
|
||||
import com.alibaba.dubbo.common.utils.NetUtils;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.Result;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.RpcResult;
|
||||
import com.alibaba.dubbo.rpc.cluster.Directory;
|
||||
import com.alibaba.dubbo.rpc.cluster.LoadBalance;
|
||||
|
||||
/**
|
||||
* 失败安全,出现异常时,直接忽略,通常用于写入审计日志等操作。
|
||||
*
|
||||
* <a href="http://en.wikipedia.org/wiki/Fail-safe">Fail-safe</a>
|
||||
*
|
||||
* @author william.liangf
|
||||
*/
|
||||
public class FailsafeClusterInvoker<T> extends AbstractClusterInvoker<T>{
|
||||
private static final Logger logger = LoggerFactory.getLogger(FailsafeClusterInvoker.class);
|
||||
|
||||
public FailsafeClusterInvoker(Directory<T> directory) {
|
||||
super(directory);
|
||||
}
|
||||
|
||||
public Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
|
||||
try {
|
||||
if (invokers == null || invokers.size() == 0)
|
||||
throw new RpcException("No provider available for service " + getInterface().getName() + " on consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", Please check whether the service do exist or version is right firstly, and check the provider has started.");
|
||||
Invoker<T> invoker = select(loadbalance, invocation, invokers, null);
|
||||
return invoker.invoke(invocation);
|
||||
} catch (Throwable e) {
|
||||
logger.error("Failsafe ignore exception: " + e.getMessage(), e);
|
||||
return new RpcResult(); // ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.support;
|
||||
|
||||
import com.alibaba.dubbo.common.Extension;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.cluster.Cluster;
|
||||
import com.alibaba.dubbo.rpc.cluster.Directory;
|
||||
|
||||
/**
|
||||
* 并行调用,只要一个成功即返回,通常用于实时性要求较高的操作,但需要浪费更多服务资源。
|
||||
*
|
||||
* @author william.liangf
|
||||
*/
|
||||
@Extension(ForkingCluster.NAME)
|
||||
public class ForkingCluster implements Cluster {
|
||||
|
||||
public final static String NAME = "forking";
|
||||
|
||||
public <T> Invoker<T> merge(Directory<T> directory) throws RpcException {
|
||||
return new ForkingClusterInvoker<T>(directory);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed 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 com.alibaba.dubbo.rpc.cluster.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.alibaba.dubbo.common.Constants;
|
||||
import com.alibaba.dubbo.common.Version;
|
||||
import com.alibaba.dubbo.common.utils.NamedThreadFactory;
|
||||
import com.alibaba.dubbo.common.utils.NetUtils;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.Result;
|
||||
import com.alibaba.dubbo.rpc.RpcContext;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.cluster.Directory;
|
||||
import com.alibaba.dubbo.rpc.cluster.LoadBalance;
|
||||
|
||||
/**
|
||||
* 并行调用,只要一个成功即返回,通常用于实时性要求较高的操作,但需要浪费更多服务资源。
|
||||
*
|
||||
* @author william.liangf
|
||||
*/
|
||||
public class ForkingClusterInvoker<T> extends AbstractClusterInvoker<T>{
|
||||
|
||||
public ForkingClusterInvoker(Directory<T> directory) {
|
||||
super(directory);
|
||||
}
|
||||
|
||||
private final ExecutorService executor = Executors.newCachedThreadPool(new NamedThreadFactory("forking-cluster-timer", true));
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public Result doInvoke(final Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
|
||||
if (invokers == null || invokers.size() == 0)
|
||||
throw new RpcException("No provider available for service " + getInterface().getName() + " on consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", Please check whether the service do exist or version is right firstly, and check the provider has started.");
|
||||
final List<Invoker<T>> selected;
|
||||
final int forks = getUrl().getParameter(Constants.FORKS_KEY, Constants.DEFAULT_FORKS);
|
||||
final int timeout = getUrl().getParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
|
||||
if (forks <= 0 || forks >= invokers.size()) {
|
||||
selected = invokers;
|
||||
} else {
|
||||
selected = new ArrayList<Invoker<T>>();
|
||||
for (int i = 0; i < forks; i++) {
|
||||
//在invoker列表(排除selected)后,如果没有选够,则存在重复循环问题.见select实现.
|
||||
Invoker<T> invoker = select(loadbalance, invocation, invokers, selected);
|
||||
if(!selected.contains(invoker)){//防止重复添加invoker
|
||||
selected.add(invoker);
|
||||
}
|
||||
}
|
||||
}
|
||||
RpcContext.getContext().setInvokers((List)selected);
|
||||
final AtomicInteger count = new AtomicInteger();
|
||||
final BlockingQueue<Object> ref = new LinkedBlockingQueue<Object>();
|
||||
for (final Invoker<T> invoker : selected) {
|
||||
executor.execute(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
Result result = invoker.invoke(invocation);
|
||||
ref.offer(result);
|
||||
} catch(Throwable e) {
|
||||
int value = count.incrementAndGet();
|
||||
if (value >= selected.size()) {
|
||||
ref.offer(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
try {
|
||||
Object ret = ref.poll(timeout, TimeUnit.MILLISECONDS);
|
||||
if (ret instanceof Throwable) {
|
||||
Throwable e = (Throwable) ret;
|
||||
throw new RpcException(e instanceof RpcException ? ((RpcException)e).getCode() : 0, "Failed to forking invoke provider " + selected + ", but no luck to perform the invocation. Last error is: " + e.getMessage(), e);
|
||||
}
|
||||
return (Result) ret;
|
||||
} catch (InterruptedException e) {
|
||||
throw new RpcException("Failed to forking invoke provider " + selected + ", but no luck to perform the invocation. Last error is: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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.registry;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.extension.ExtensionScope;
|
||||
import org.apache.dubbo.common.extension.SPI;
|
||||
import org.apache.dubbo.rpc.cluster.Directory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@SPI(scope = ExtensionScope.MODULE)
|
||||
public interface AddressListener {
|
||||
|
||||
/**
|
||||
* processing when receiving the address list
|
||||
*
|
||||
* @param addresses provider address list
|
||||
* @param consumerUrl
|
||||
* @param registryDirectory
|
||||
*/
|
||||
List<URL> notify(List<URL> addresses, URL consumerUrl, Directory registryDirectory);
|
||||
|
||||
default void destroy(URL consumerUrl, Directory registryDirectory) {}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.utils.ConcurrentHashMapUtils;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* If you want to provide a router implementation based on design of v2.7.0, please extend from this abstract class.
|
||||
* For 2.6.x style router, please implement and use RouterFactory directly.
|
||||
*/
|
||||
public abstract class CacheableRouterFactory implements RouterFactory {
|
||||
private ConcurrentMap<String, Router> routerMap = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public Router getRouter(URL url) {
|
||||
return ConcurrentHashMapUtils.computeIfAbsent(routerMap, url.getServiceKey(), k -> createRouter(url));
|
||||
}
|
||||
|
||||
protected abstract Router createRouter(URL url);
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* 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.extension.Adaptive;
|
||||
import org.apache.dubbo.common.extension.SPI;
|
||||
import org.apache.dubbo.common.utils.StringUtils;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
import org.apache.dubbo.rpc.model.ScopeModel;
|
||||
import org.apache.dubbo.rpc.model.ScopeModelUtil;
|
||||
|
||||
/**
|
||||
* Cluster. (SPI, Singleton, ThreadSafe)
|
||||
* <p>
|
||||
* <a href="http://en.wikipedia.org/wiki/Computer_cluster">Cluster</a>
|
||||
* <a href="http://en.wikipedia.org/wiki/Fault-tolerant_system">Fault-Tolerant</a>
|
||||
*
|
||||
*/
|
||||
@SPI(Cluster.DEFAULT)
|
||||
public interface Cluster {
|
||||
|
||||
String DEFAULT = "failover";
|
||||
|
||||
/**
|
||||
* Merge the directory invokers to a virtual invoker.
|
||||
*
|
||||
* @param <T>
|
||||
* @param directory
|
||||
* @return cluster invoker
|
||||
* @throws RpcException
|
||||
*/
|
||||
@Adaptive
|
||||
<T> Invoker<T> join(Directory<T> directory, boolean buildFilterChain) throws RpcException;
|
||||
|
||||
static Cluster getCluster(ScopeModel scopeModel, String name) {
|
||||
return getCluster(scopeModel, name, true);
|
||||
}
|
||||
|
||||
static Cluster getCluster(ScopeModel scopeModel, String name, boolean wrap) {
|
||||
if (StringUtils.isEmpty(name)) {
|
||||
name = Cluster.DEFAULT;
|
||||
}
|
||||
return ScopeModelUtil.getApplicationModel(scopeModel)
|
||||
.getExtensionLoader(Cluster.class)
|
||||
.getExtension(name, wrap);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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.rpc.Invoker;
|
||||
|
||||
/**
|
||||
* This is the final Invoker type referenced by the RPC proxy on Consumer side.
|
||||
* <p>
|
||||
* A ClusterInvoker holds a group of normal invokers, stored in a Directory, mapping to one Registry.
|
||||
* The ClusterInvoker implementation usually provides LB or HA policies, like FailoverClusterInvoker.
|
||||
* <p>
|
||||
* In multi-registry subscription scenario, the final ClusterInvoker will refer to several sub ClusterInvokers, with each
|
||||
* sub ClusterInvoker representing one Registry. Take ZoneAwareClusterInvoker as an example, it is specially customized for
|
||||
* multi-registry use cases: first, pick up one ClusterInvoker, then do LB inside the chose ClusterInvoker.
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public interface ClusterInvoker<T> extends Invoker<T> {
|
||||
|
||||
URL getRegistryUrl();
|
||||
|
||||
Directory<T> getDirectory();
|
||||
|
||||
boolean isDestroyed();
|
||||
|
||||
default boolean isServiceDiscovery() {
|
||||
Directory<T> directory = getDirectory();
|
||||
if (directory == null) {
|
||||
return false;
|
||||
}
|
||||
return directory.isServiceDiscovery();
|
||||
}
|
||||
|
||||
default boolean hasProxyInvokers() {
|
||||
Directory<T> directory = getDirectory();
|
||||
if (directory == null) {
|
||||
return false;
|
||||
}
|
||||
return !directory.isEmpty();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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.beans.factory.ScopeBeanFactory;
|
||||
import org.apache.dubbo.rpc.AdaptiveMetrics;
|
||||
import org.apache.dubbo.rpc.cluster.merger.MergerFactory;
|
||||
import org.apache.dubbo.rpc.cluster.router.RouterSnapshotSwitcher;
|
||||
import org.apache.dubbo.rpc.cluster.router.mesh.route.MeshRuleManager;
|
||||
import org.apache.dubbo.rpc.cluster.support.ClusterUtils;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.apache.dubbo.rpc.model.FrameworkModel;
|
||||
import org.apache.dubbo.rpc.model.ModuleModel;
|
||||
import org.apache.dubbo.rpc.model.ScopeModelInitializer;
|
||||
|
||||
public class ClusterScopeModelInitializer implements ScopeModelInitializer {
|
||||
@Override
|
||||
public void initializeFrameworkModel(FrameworkModel frameworkModel) {
|
||||
ScopeBeanFactory beanFactory = frameworkModel.getBeanFactory();
|
||||
beanFactory.registerBean(RouterSnapshotSwitcher.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeApplicationModel(ApplicationModel applicationModel) {
|
||||
ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
|
||||
beanFactory.registerBean(MergerFactory.class);
|
||||
beanFactory.registerBean(ClusterUtils.class);
|
||||
beanFactory.registerBean(AdaptiveMetrics.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeModuleModel(ModuleModel moduleModel) {
|
||||
ScopeBeanFactory beanFactory = moduleModel.getBeanFactory();
|
||||
beanFactory.registerBean(MeshRuleManager.class);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* 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.utils.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
|
||||
import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL;
|
||||
import static org.apache.dubbo.rpc.cluster.Constants.PRIORITY_KEY;
|
||||
|
||||
/**
|
||||
* Configurator. (SPI, Prototype, ThreadSafe)
|
||||
*
|
||||
*/
|
||||
public interface Configurator extends Comparable<Configurator> {
|
||||
|
||||
/**
|
||||
* Get the configurator url.
|
||||
*
|
||||
* @return configurator url.
|
||||
*/
|
||||
URL getUrl();
|
||||
|
||||
/**
|
||||
* Configure the provider url.
|
||||
*
|
||||
* @param url - old provider url.
|
||||
* @return new provider 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
|
||||
* calculated
|
||||
*
|
||||
* URL contract:
|
||||
* <ol>
|
||||
* <li>override://0.0.0.0/...( or override://ip:port...?anyhost=true)¶1=value1... means global rules
|
||||
* (all of the providers take effect)</li>
|
||||
* <li>override://ip:port...?anyhost=false Special rules (only for a certain provider)</li>
|
||||
* <li>override:// rule is not supported... ,needs to be calculated by registry itself</li>
|
||||
* <li>override://0.0.0.0/ without parameters means clearing the override</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param urls URL list to convert
|
||||
* @return converted configurator list
|
||||
*/
|
||||
static Optional<List<Configurator>> toConfigurators(List<URL> urls) {
|
||||
if (CollectionUtils.isEmpty(urls)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
ConfiguratorFactory configuratorFactory = urls.get(0)
|
||||
.getOrDefaultApplicationModel()
|
||||
.getExtensionLoader(ConfiguratorFactory.class)
|
||||
.getAdaptiveExtension();
|
||||
|
||||
List<Configurator> configurators = new ArrayList<>(urls.size());
|
||||
for (URL url : urls) {
|
||||
if (EMPTY_PROTOCOL.equals(url.getProtocol())) {
|
||||
configurators.clear();
|
||||
break;
|
||||
}
|
||||
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
|
||||
// url
|
||||
override.remove(ANYHOST_KEY);
|
||||
if (CollectionUtils.isEmptyMap(override)) {
|
||||
continue;
|
||||
}
|
||||
configurators.add(configuratorFactory.getConfigurator(url));
|
||||
}
|
||||
Collections.sort(configurators);
|
||||
return Optional.of(configurators);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort by host, then by priority
|
||||
* 1. the url with a specific host ip should have higher priority than 0.0.0.0
|
||||
* 2. if two url has the same host, compare by priority value;
|
||||
*/
|
||||
@Override
|
||||
default int compareTo(Configurator o) {
|
||||
if (o == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ipCompare = getUrl().getHost().compareTo(o.getUrl().getHost());
|
||||
// host is the same, sort by priority
|
||||
if (ipCompare == 0) {
|
||||
int i = getUrl().getParameter(PRIORITY_KEY, 0);
|
||||
int j = o.getUrl().getParameter(PRIORITY_KEY, 0);
|
||||
return Integer.compare(i, j);
|
||||
} else {
|
||||
return ipCompare;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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.constants.CommonConstants;
|
||||
import org.apache.dubbo.common.extension.Adaptive;
|
||||
import org.apache.dubbo.common.extension.SPI;
|
||||
|
||||
/**
|
||||
* ConfiguratorFactory. (SPI, Singleton, ThreadSafe)
|
||||
*
|
||||
*/
|
||||
@SPI
|
||||
public interface ConfiguratorFactory {
|
||||
|
||||
/**
|
||||
* get the configurator instance.
|
||||
*
|
||||
* @param url - configurator url.
|
||||
* @return configurator instance.
|
||||
*/
|
||||
@Adaptive(CommonConstants.PROTOCOL_KEY)
|
||||
Configurator getConfigurator(URL url);
|
||||
}
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
public interface Constants {
|
||||
|
||||
String FAIL_BACK_TASKS_KEY = "failbacktasks";
|
||||
|
||||
int DEFAULT_FAILBACK_TASKS = 100;
|
||||
|
||||
int DEFAULT_FORKS = 2;
|
||||
|
||||
String WEIGHT_KEY = "weight";
|
||||
|
||||
int DEFAULT_WEIGHT = 100;
|
||||
|
||||
String MOCK_PROTOCOL = "mock";
|
||||
|
||||
String FORCE_KEY = "force";
|
||||
|
||||
String RAW_RULE_KEY = "rawRule";
|
||||
|
||||
String VALID_KEY = "valid";
|
||||
|
||||
String ENABLED_KEY = "enabled";
|
||||
|
||||
String DYNAMIC_KEY = "dynamic";
|
||||
|
||||
String SCOPE_KEY = "scope";
|
||||
|
||||
String KEY_KEY = "key";
|
||||
|
||||
String CONDITIONS_KEY = "conditions";
|
||||
|
||||
String TAGS_KEY = "tags";
|
||||
|
||||
/**
|
||||
* To decide whether to exclude unavailable invoker from the cluster
|
||||
*/
|
||||
String CLUSTER_AVAILABLE_CHECK_KEY = "cluster.availablecheck";
|
||||
|
||||
/**
|
||||
* The default value of cluster.availablecheck
|
||||
*
|
||||
* @see #CLUSTER_AVAILABLE_CHECK_KEY
|
||||
*/
|
||||
boolean DEFAULT_CLUSTER_AVAILABLE_CHECK = true;
|
||||
|
||||
/**
|
||||
* To decide whether to enable sticky strategy for cluster
|
||||
*/
|
||||
String CLUSTER_STICKY_KEY = "sticky";
|
||||
|
||||
/**
|
||||
* The default value of sticky
|
||||
*
|
||||
* @see #CLUSTER_STICKY_KEY
|
||||
*/
|
||||
boolean DEFAULT_CLUSTER_STICKY = false;
|
||||
|
||||
/**
|
||||
* When this attribute appears in invocation's attachment, mock invoker will be used
|
||||
*/
|
||||
String INVOCATION_NEED_MOCK = "invocation.need.mock";
|
||||
|
||||
/**
|
||||
* when ROUTER_KEY's value is set to ROUTER_TYPE_CLEAR, RegistryDirectory will clean all current routers
|
||||
*/
|
||||
String ROUTER_TYPE_CLEAR = "clean";
|
||||
|
||||
String DEFAULT_SCRIPT_TYPE_KEY = "javascript";
|
||||
|
||||
String PRIORITY_KEY = "priority";
|
||||
|
||||
String RULE_KEY = "rule";
|
||||
|
||||
String TYPE_KEY = "type";
|
||||
|
||||
String RUNTIME_KEY = "runtime";
|
||||
|
||||
String WARMUP_KEY = "warmup";
|
||||
|
||||
int DEFAULT_WARMUP = 10 * 60 * 1000;
|
||||
|
||||
String CONFIG_VERSION_KEY = "configVersion";
|
||||
|
||||
String OVERRIDE_PROVIDERS_KEY = "providerAddresses";
|
||||
|
||||
/**
|
||||
* key for router type, for e.g., "script"/"file", corresponding to ScriptRouterFactory.NAME, FileRouterFactory.NAME
|
||||
*/
|
||||
String ROUTER_KEY = "router";
|
||||
|
||||
/**
|
||||
* The key name for reference URL in register center
|
||||
*/
|
||||
String REFER_KEY = "refer";
|
||||
|
||||
String ATTRIBUTE_KEY = "attribute";
|
||||
|
||||
/**
|
||||
* The key name for export URL in register center
|
||||
*/
|
||||
String EXPORT_KEY = "export";
|
||||
|
||||
String PEER_KEY = "peer";
|
||||
|
||||
String CONSUMER_URL_KEY = "CONSUMER_URL";
|
||||
|
||||
/**
|
||||
* prefix of arguments router key
|
||||
*/
|
||||
String ARGUMENTS = "arguments";
|
||||
|
||||
String NEED_REEXPORT = "need-reexport";
|
||||
|
||||
/**
|
||||
* The key of shortestResponseSlidePeriod
|
||||
*/
|
||||
String SHORTEST_RESPONSE_SLIDE_PERIOD = "shortestResponseSlidePeriod";
|
||||
|
||||
String SHOULD_FAIL_FAST_KEY = "dubbo.router.should-fail-fast";
|
||||
|
||||
String RULE_VERSION_V27 = "v2.7";
|
||||
|
||||
String RULE_VERSION_V30 = "v3.0";
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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.Node;
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Directory. (SPI, Prototype, ThreadSafe)
|
||||
* <p>
|
||||
* <a href="http://en.wikipedia.org/wiki/Directory_service">Directory Service</a>
|
||||
*
|
||||
* @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory)
|
||||
*/
|
||||
public interface Directory<T> extends Node {
|
||||
|
||||
/**
|
||||
* get service type.
|
||||
*
|
||||
* @return service type.
|
||||
*/
|
||||
Class<T> getInterface();
|
||||
|
||||
/**
|
||||
* list invokers.
|
||||
* filtered by invocation
|
||||
*
|
||||
* @return invokers
|
||||
*/
|
||||
List<Invoker<T>> list(Invocation invocation) throws RpcException;
|
||||
|
||||
/**
|
||||
* list invokers
|
||||
* include all invokers from registry
|
||||
*/
|
||||
List<Invoker<T>> getAllInvokers();
|
||||
|
||||
URL getConsumerUrl();
|
||||
|
||||
boolean isDestroyed();
|
||||
|
||||
default boolean isEmpty() {
|
||||
return CollectionUtils.isEmpty(getAllInvokers());
|
||||
}
|
||||
|
||||
default boolean isServiceDiscovery() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void discordAddresses();
|
||||
|
||||
RouterChain<T> getRouterChain();
|
||||
|
||||
/**
|
||||
* invalidate an invoker, add it into reconnect task, remove from list next time
|
||||
* will be recovered by address refresh notification or reconnect success notification
|
||||
*
|
||||
* @param invoker invoker to invalidate
|
||||
*/
|
||||
void addInvalidateInvoker(Invoker<T> invoker);
|
||||
|
||||
/**
|
||||
* disable an invoker, remove from list next time
|
||||
* will be removed when invoker is removed by address refresh notification
|
||||
* using in service offline notification
|
||||
*
|
||||
* @param invoker invoker to invalidate
|
||||
*/
|
||||
void addDisabledInvoker(Invoker<T> invoker);
|
||||
|
||||
/**
|
||||
* recover a disabled invoker
|
||||
*
|
||||
* @param invoker invoker to invalidate
|
||||
*/
|
||||
void recoverDisabledInvoker(Invoker<T> invoker);
|
||||
|
||||
default boolean isNotificationReceived() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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.extension.Adaptive;
|
||||
import org.apache.dubbo.common.extension.SPI;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
import org.apache.dubbo.rpc.cluster.loadbalance.RandomLoadBalance;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* LoadBalance. (SPI, Singleton, ThreadSafe)
|
||||
* <p>
|
||||
* <a href="http://en.wikipedia.org/wiki/Load_balancing_(computing)">Load-Balancing</a>
|
||||
*
|
||||
* @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory)
|
||||
*/
|
||||
@SPI(RandomLoadBalance.NAME)
|
||||
public interface LoadBalance {
|
||||
|
||||
/**
|
||||
* select one invoker in list.
|
||||
*
|
||||
* @param invokers invokers.
|
||||
* @param url refer url
|
||||
* @param invocation invocation.
|
||||
* @return selected invoker.
|
||||
*/
|
||||
@Adaptive("loadbalance")
|
||||
<T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException;
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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.extension.SPI;
|
||||
|
||||
@SPI
|
||||
public interface Merger<T> {
|
||||
|
||||
T merge(T... items);
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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.extension.SPI;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@SPI("default")
|
||||
public interface ProviderURLMergeProcessor {
|
||||
|
||||
/**
|
||||
* Merging the URL parameters of provider and consumer
|
||||
*
|
||||
* @param remoteUrl providerUrl
|
||||
* @param localParametersMap consumer url parameters
|
||||
* @return
|
||||
*/
|
||||
URL mergeUrl(URL remoteUrl, Map<String, String> localParametersMap);
|
||||
|
||||
default Map<String, String> mergeLocalParams(Map<String, String> localMap) {
|
||||
return localMap;
|
||||
}
|
||||
|
||||
default boolean accept(URL providerUrl, Map<String, String> localParametersMap) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* 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.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
import org.apache.dubbo.rpc.cluster.router.RouterResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Router. (SPI, Prototype, ThreadSafe)
|
||||
* <p>
|
||||
* <a href="http://en.wikipedia.org/wiki/Routing">Routing</a>
|
||||
*
|
||||
* @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory, boolean)
|
||||
* @see org.apache.dubbo.rpc.cluster.Directory#list(Invocation)
|
||||
*/
|
||||
public interface Router extends Comparable<Router> {
|
||||
|
||||
int DEFAULT_PRIORITY = Integer.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* Get the router url.
|
||||
*
|
||||
* @return url
|
||||
*/
|
||||
URL getUrl();
|
||||
|
||||
/**
|
||||
* Filter invokers with current routing rule and only return the invokers that comply with the rule.
|
||||
*
|
||||
* @param invokers invoker list
|
||||
* @param url refer url
|
||||
* @param invocation invocation
|
||||
* @return routed invokers
|
||||
* @throws RpcException
|
||||
*/
|
||||
@Deprecated
|
||||
default <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* ** This method can return the state of whether routerChain needed to continue route. **
|
||||
* Filter invokers with current routing rule and only return the invokers that comply with the rule.
|
||||
*
|
||||
* @param invokers invoker list
|
||||
* @param url refer url
|
||||
* @param invocation invocation
|
||||
* @param needToPrintMessage whether to print router state. Such as `use router branch a`.
|
||||
* @return state with route result
|
||||
* @throws RpcException
|
||||
*/
|
||||
default <T> RouterResult<Invoker<T>> route(
|
||||
List<Invoker<T>> invokers, URL url, Invocation invocation, boolean needToPrintMessage) throws RpcException {
|
||||
return new RouterResult<>(route(invokers, url, invocation));
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the router the invoker list. Invoker list may change from time to time. This method gives the router a
|
||||
* chance to prepare before {@link Router#route(List, URL, Invocation)} gets called.
|
||||
*
|
||||
* @param invokers invoker list
|
||||
* @param <T> invoker's type
|
||||
*/
|
||||
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
|
||||
* rule change.
|
||||
*
|
||||
* @return true if the router need to execute every time.
|
||||
*/
|
||||
boolean isRuntime();
|
||||
|
||||
/**
|
||||
* To decide whether this router should take effect when none of the invoker can match the router rule, which
|
||||
* means the {@link #route(List, URL, Invocation)} would be empty. Most of time, most router implementation would
|
||||
* default this value to false.
|
||||
*
|
||||
* @return true to execute if none of invokers matches the current router
|
||||
*/
|
||||
boolean isForce();
|
||||
|
||||
/**
|
||||
* Router's priority, used to sort routers.
|
||||
*
|
||||
* @return router's priority
|
||||
*/
|
||||
int getPriority();
|
||||
|
||||
default void stop() {
|
||||
// do nothing by default
|
||||
}
|
||||
|
||||
@Override
|
||||
default int compareTo(Router o) {
|
||||
if (o == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return Integer.compare(this.getPriority(), o.getPriority());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* 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.config.ConfigurationUtils;
|
||||
import org.apache.dubbo.common.constants.LoggerCodeConstants;
|
||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
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.StateRouterFactory;
|
||||
import org.apache.dubbo.rpc.model.ModuleModel;
|
||||
import org.apache.dubbo.rpc.model.ScopeModelUtil;
|
||||
|
||||
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 static org.apache.dubbo.rpc.cluster.Constants.ROUTER_KEY;
|
||||
|
||||
/**
|
||||
* Router chain
|
||||
*/
|
||||
public class RouterChain<T> {
|
||||
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(RouterChain.class);
|
||||
|
||||
private volatile SingleRouterChain<T> mainChain;
|
||||
private volatile SingleRouterChain<T> backupChain;
|
||||
private volatile SingleRouterChain<T> currentChain;
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
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();
|
||||
|
||||
List<RouterFactory> extensionFactories =
|
||||
moduleModel.getExtensionLoader(RouterFactory.class).getActivateExtension(url, ROUTER_KEY);
|
||||
|
||||
List<Router> routers = extensionFactories.stream()
|
||||
.map(factory -> factory.getRouter(url))
|
||||
.sorted(Router::compareTo)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<StateRouter<T>> stateRouters =
|
||||
moduleModel.getExtensionLoader(StateRouterFactory.class).getActivateExtension(url, ROUTER_KEY).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 =
|
||||
ScopeModelUtil.getFrameworkModel(moduleModel).getBeanFactory().getBean(RouterSnapshotSwitcher.class);
|
||||
|
||||
return new SingleRouterChain<>(routers, stateRouters, shouldFailFast, routerSnapshotSwitcher);
|
||||
}
|
||||
|
||||
public RouterChain(SingleRouterChain<T>[] chains) {
|
||||
if (chains.length != 2) {
|
||||
throw new IllegalArgumentException("chains' size should be 2.");
|
||||
}
|
||||
this.mainChain = chains[0];
|
||||
this.backupChain = chains[1];
|
||||
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
|
||||
*/
|
||||
@Deprecated
|
||||
public List<Invoker<T>> route(URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
|
||||
return getSingleChain(url, availableInvokers, invocation).route(url, availableInvokers, invocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify router chain of the initial addresses from registry at the first time.
|
||||
* Notify whenever addresses in registry change.
|
||||
*/
|
||||
public synchronized void setInvokers(BitList<Invoker<T>> invokers, Runnable switchAction) {
|
||||
try {
|
||||
// Lock to prevent directory continue list
|
||||
lock.writeLock().lock();
|
||||
|
||||
// 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
|
||||
backupChain.destroy();
|
||||
|
||||
// 2. switch
|
||||
lock.writeLock().lock();
|
||||
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();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public List<StateRouter<T>> getStateRouters() {
|
||||
return currentChain.getStateRouters();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.constants.CommonConstants;
|
||||
import org.apache.dubbo.common.extension.Adaptive;
|
||||
import org.apache.dubbo.common.extension.SPI;
|
||||
|
||||
/**
|
||||
* RouterFactory. (SPI, Singleton, ThreadSafe)
|
||||
* <p>
|
||||
* <a href="http://en.wikipedia.org/wiki/Routing">Routing</a>
|
||||
*
|
||||
* @see org.apache.dubbo.rpc.cluster.Cluster#join(Directory)
|
||||
* @see org.apache.dubbo.rpc.cluster.Directory#list(org.apache.dubbo.rpc.Invocation)
|
||||
* <p>
|
||||
* Note Router has a different behaviour since 2.7.0, for each type of Router, there will only has one Router instance
|
||||
* for each service. See {@link CacheableRouterFactory} and {@link RouterChain} for how to extend a new Router or how
|
||||
* the Router instances are loaded.
|
||||
*/
|
||||
@SPI
|
||||
public interface RouterFactory {
|
||||
|
||||
/**
|
||||
* Create router.
|
||||
* Since 2.7.0, most of the time, we will not use @Adaptive feature, so it's kept only for compatibility.
|
||||
*
|
||||
* @param url url
|
||||
* @return router instance
|
||||
*/
|
||||
@Adaptive(CommonConstants.PROTOCOL_KEY)
|
||||
Router getRouter(URL url);
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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.extension.SPI;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@SPI
|
||||
public interface RuleConverter {
|
||||
|
||||
List<URL> convert(URL subscribeUrl, Object source);
|
||||
}
|
||||
|
|
@ -0,0 +1,371 @@
|
|||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
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.StringUtils;
|
||||
import org.apache.dubbo.remoting.Constants;
|
||||
import org.apache.dubbo.rpc.cluster.Configurator;
|
||||
import org.apache.dubbo.rpc.cluster.configurator.parser.model.ConditionMatch;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.INTERFACES;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
|
||||
import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY;
|
||||
import static org.apache.dubbo.common.constants.RegistryConstants.COMPATIBLE_CONFIG_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.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
|
||||
*/
|
||||
public abstract class AbstractConfigurator implements Configurator {
|
||||
private static final Logger logger = LoggerFactory.getLogger(AbstractConfigurator.class);
|
||||
private static final String TILDE = "~";
|
||||
|
||||
private final URL configuratorUrl;
|
||||
|
||||
public AbstractConfigurator(URL url) {
|
||||
if (url == null) {
|
||||
throw new IllegalArgumentException("configurator url == null");
|
||||
}
|
||||
this.configuratorUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getUrl() {
|
||||
return configuratorUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL configure(URL url) {
|
||||
// If override url is not enabled or is invalid, just return.
|
||||
if (!configuratorUrl.getParameter(ENABLED_KEY, true)
|
||||
|| 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;
|
||||
}
|
||||
|
||||
String apiVersion = configuratorUrl.getParameter(CONFIG_VERSION_KEY);
|
||||
if (StringUtils.isNotEmpty(apiVersion)) { // v2.7 or above
|
||||
String currentSide = url.getSide();
|
||||
String configuratorSide = configuratorUrl.getSide();
|
||||
if (currentSide.equals(configuratorSide) && CONSUMER.equals(configuratorSide)) {
|
||||
url = configureIfMatch(NetUtils.getLocalHost(), url);
|
||||
} else if (currentSide.equals(configuratorSide) && PROVIDER.equals(configuratorSide)) {
|
||||
url = configureIfMatch(url.getHost(), url);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This else branch is deprecated and is left only to keep compatibility with versions before 2.7.0
|
||||
*/
|
||||
else {
|
||||
url = configureDeprecated(url);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
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
|
||||
// override url, it may take effect on the specific provider instance or on consumers holding this provider
|
||||
// instance.
|
||||
if (configuratorUrl.getPort() != 0) {
|
||||
if (url.getPort() == configuratorUrl.getPort()) {
|
||||
return configureIfMatch(url.getHost(), url);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* override url don't have a port, means the ip override url specify is a consumer address or 0.0.0.0.
|
||||
* 1.If it is a consumer ip address, the intention is to control a specific consumer instance, it must takes effect at the consumer side, any provider received this override url should ignore.
|
||||
* 2.If the ip is 0.0.0.0, this override url can be used on consumer, and also can be used on provider.
|
||||
*/
|
||||
if (url.getSide(PROVIDER).equals(CONSUMER)) {
|
||||
// NetUtils.getLocalHost is the ip address consumer registered to registry.
|
||||
return configureIfMatch(NetUtils.getLocalHost(), url);
|
||||
} else if (url.getSide(CONSUMER).equals(PROVIDER)) {
|
||||
// take effect on all providers, so address must be 0.0.0.0, otherwise it won't flow to this if branch
|
||||
return configureIfMatch(ANYHOST_VALUE, url);
|
||||
}
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
private URL configureIfMatch(String host, URL url) {
|
||||
if (ANYHOST_VALUE.equals(configuratorUrl.getHost()) || host.equals(configuratorUrl.getHost())) {
|
||||
if (isV27ConditionMatchOrUnset(url)) {
|
||||
Set<String> conditionKeys = genConditionKeys();
|
||||
String apiVersion = configuratorUrl.getParameter(CONFIG_VERSION_KEY);
|
||||
if (apiVersion != null && apiVersion.startsWith(RULE_VERSION_V30)) {
|
||||
ConditionMatch matcher = (ConditionMatch) configuratorUrl.getAttribute(MATCH_CONDITION);
|
||||
if (matcher != null) {
|
||||
if (matcher.isMatch(host, url)) {
|
||||
return doConfigure(url, configuratorUrl.removeParameters(conditionKeys));
|
||||
} else {
|
||||
logger.debug("Cannot apply configurator rule, param mismatch, current params are " + url
|
||||
+ ", params in rule is " + matcher);
|
||||
}
|
||||
} else {
|
||||
return doConfigure(url, configuratorUrl.removeParameters(conditionKeys));
|
||||
}
|
||||
} else if (isDeprecatedConditionMatch(conditionKeys, url)) {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
return StringUtils.isNotEmpty(key) && key.startsWith(TILDE);
|
||||
}
|
||||
|
||||
protected abstract URL doConfigure(URL currentUrl, URL configUrl);
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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.absent;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.rpc.cluster.configurator.AbstractConfigurator;
|
||||
|
||||
/**
|
||||
* AbsentConfigurator
|
||||
*/
|
||||
public class AbsentConfigurator extends AbstractConfigurator {
|
||||
|
||||
public AbsentConfigurator(URL url) {
|
||||
super(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL doConfigure(URL currentUrl, URL configUrl) {
|
||||
return currentUrl.addParametersIfAbsent(configUrl.getParameters());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.rpc.cluster.configurator.absent;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.rpc.cluster.Configurator;
|
||||
import org.apache.dubbo.rpc.cluster.ConfiguratorFactory;
|
||||
|
||||
/**
|
||||
* AbsentConfiguratorFactory
|
||||
*
|
||||
*/
|
||||
public class AbsentConfiguratorFactory implements ConfiguratorFactory {
|
||||
|
||||
@Override
|
||||
public Configurator getConfigurator(URL url) {
|
||||
return new AbsentConfigurator(url);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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.override;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* OverrideConfigurator
|
||||
*/
|
||||
public class OverrideConfigurator extends AbstractConfigurator {
|
||||
public static final Logger logger = LoggerFactory.getLogger(OverrideConfigurator.class);
|
||||
|
||||
public OverrideConfigurator(URL url) {
|
||||
super(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL doConfigure(URL currentUrl, URL configUrl) {
|
||||
logger.info("Start overriding url " + currentUrl + " with override url " + configUrl);
|
||||
return currentUrl.addParameters(configUrl.getParameters());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.rpc.cluster.configurator.override;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.rpc.cluster.Configurator;
|
||||
import org.apache.dubbo.rpc.cluster.ConfiguratorFactory;
|
||||
|
||||
/**
|
||||
* OverrideConfiguratorFactory
|
||||
*
|
||||
*/
|
||||
public class OverrideConfiguratorFactory implements ConfiguratorFactory {
|
||||
|
||||
@Override
|
||||
public Configurator getConfigurator(URL url) {
|
||||
return new OverrideConfigurator(url);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,242 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||
import org.apache.dubbo.common.utils.JsonUtils;
|
||||
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.ConfiguratorConfig;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
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.PROVIDER;
|
||||
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.rpc.cluster.Constants.OVERRIDE_PROVIDERS_KEY;
|
||||
import static org.apache.dubbo.rpc.cluster.configurator.parser.model.ConfiguratorConfig.MATCH_CONDITION;
|
||||
|
||||
/**
|
||||
* Config parser
|
||||
*/
|
||||
public class ConfigParser {
|
||||
|
||||
public static List<URL> parseConfigurators(String rawConfig) {
|
||||
// compatible url JsonArray, such as [ "override://xxx", "override://xxx" ]
|
||||
List<URL> compatibleUrls = parseJsonArray(rawConfig);
|
||||
if (CollectionUtils.isNotEmpty(compatibleUrls)) {
|
||||
return compatibleUrls;
|
||||
}
|
||||
|
||||
List<URL> urls = new ArrayList<>();
|
||||
ConfiguratorConfig configuratorConfig = parseObject(rawConfig);
|
||||
|
||||
String scope = configuratorConfig.getScope();
|
||||
List<ConfigItem> items = configuratorConfig.getConfigs();
|
||||
|
||||
if (ConfiguratorConfig.SCOPE_APPLICATION.equals(scope)) {
|
||||
items.forEach(item -> urls.addAll(appItemToUrls(item, configuratorConfig)));
|
||||
} else {
|
||||
// service scope by default.
|
||||
items.forEach(item -> urls.addAll(serviceItemToUrls(item, configuratorConfig)));
|
||||
}
|
||||
|
||||
return urls;
|
||||
}
|
||||
|
||||
private static List<URL> parseJsonArray(String rawConfig) {
|
||||
List<URL> urls = new ArrayList<>();
|
||||
try {
|
||||
List<String> list = JsonUtils.toJavaList(rawConfig, String.class);
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
list.forEach(u -> urls.add(URL.valueOf(u)));
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
return null;
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
|
||||
private static ConfiguratorConfig parseObject(String rawConfig) {
|
||||
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
|
||||
Map<String, Object> map = yaml.load(rawConfig);
|
||||
return ConfiguratorConfig.parseFromMap(map);
|
||||
}
|
||||
|
||||
private static List<URL> serviceItemToUrls(ConfigItem item, ConfiguratorConfig config) {
|
||||
List<URL> urls = new ArrayList<>();
|
||||
List<String> addresses = parseAddresses(item);
|
||||
|
||||
addresses.forEach(addr -> {
|
||||
StringBuilder urlBuilder = new StringBuilder();
|
||||
urlBuilder.append("override://").append(addr).append('/');
|
||||
|
||||
urlBuilder.append(appendService(config.getKey()));
|
||||
urlBuilder.append(toParameterString(item));
|
||||
|
||||
parseEnabled(item, config, urlBuilder);
|
||||
|
||||
urlBuilder.append("&configVersion=").append(config.getConfigVersion());
|
||||
|
||||
List<String> apps = item.getApplications();
|
||||
if (CollectionUtils.isNotEmpty(apps)) {
|
||||
apps.forEach(app -> {
|
||||
StringBuilder tmpUrlBuilder = new StringBuilder(urlBuilder);
|
||||
urls.add(appendMatchCondition(
|
||||
URL.valueOf(tmpUrlBuilder
|
||||
.append("&application=")
|
||||
.append(app)
|
||||
.toString()),
|
||||
item));
|
||||
});
|
||||
} else {
|
||||
urls.add(appendMatchCondition(URL.valueOf(urlBuilder.toString()), item));
|
||||
}
|
||||
});
|
||||
|
||||
return urls;
|
||||
}
|
||||
|
||||
private static List<URL> appItemToUrls(ConfigItem item, ConfiguratorConfig config) {
|
||||
List<URL> urls = new ArrayList<>();
|
||||
List<String> addresses = parseAddresses(item);
|
||||
for (String addr : addresses) {
|
||||
StringBuilder urlBuilder = new StringBuilder();
|
||||
urlBuilder.append("override://").append(addr).append('/');
|
||||
List<String> services = item.getServices();
|
||||
if (services == null) {
|
||||
services = new ArrayList<>();
|
||||
}
|
||||
if (services.isEmpty()) {
|
||||
services.add("*");
|
||||
}
|
||||
for (String s : services) {
|
||||
StringBuilder tmpUrlBuilder = new StringBuilder(urlBuilder);
|
||||
tmpUrlBuilder.append(appendService(s));
|
||||
tmpUrlBuilder.append(toParameterString(item));
|
||||
|
||||
tmpUrlBuilder.append("&application=").append(config.getKey());
|
||||
|
||||
parseEnabled(item, config, tmpUrlBuilder);
|
||||
|
||||
tmpUrlBuilder.append("&category=").append(APP_DYNAMIC_CONFIGURATORS_CATEGORY);
|
||||
tmpUrlBuilder.append("&configVersion=").append(config.getConfigVersion());
|
||||
|
||||
urls.add(appendMatchCondition(URL.valueOf(tmpUrlBuilder.toString()), item));
|
||||
}
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
|
||||
private static String toParameterString(ConfigItem item) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("category=");
|
||||
sb.append(DYNAMIC_CONFIGURATORS_CATEGORY);
|
||||
if (item.getSide() != null) {
|
||||
sb.append("&side=");
|
||||
sb.append(item.getSide());
|
||||
}
|
||||
Map<String, String> parameters = item.getParameters();
|
||||
if (CollectionUtils.isEmptyMap(parameters)) {
|
||||
throw new IllegalStateException("Invalid configurator rule, please specify at least one parameter "
|
||||
+ "you want to change in the rule.");
|
||||
}
|
||||
|
||||
parameters.forEach((k, v) -> {
|
||||
sb.append('&');
|
||||
sb.append(k);
|
||||
sb.append('=');
|
||||
sb.append(v);
|
||||
});
|
||||
|
||||
if (CollectionUtils.isNotEmpty(item.getProviderAddresses())) {
|
||||
sb.append('&');
|
||||
sb.append(OVERRIDE_PROVIDERS_KEY);
|
||||
sb.append('=');
|
||||
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();
|
||||
}
|
||||
|
||||
private static String appendService(String serviceKey) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (StringUtils.isEmpty(serviceKey)) {
|
||||
throw new IllegalStateException("service field in configuration is null.");
|
||||
}
|
||||
|
||||
String interfaceName = serviceKey;
|
||||
int i = interfaceName.indexOf('/');
|
||||
if (i > 0) {
|
||||
sb.append("group=");
|
||||
sb.append(interfaceName, 0, i);
|
||||
sb.append('&');
|
||||
|
||||
interfaceName = interfaceName.substring(i + 1);
|
||||
}
|
||||
int j = interfaceName.indexOf(':');
|
||||
if (j > 0) {
|
||||
sb.append("version=");
|
||||
sb.append(interfaceName.substring(j + 1));
|
||||
sb.append('&');
|
||||
interfaceName = interfaceName.substring(0, j);
|
||||
}
|
||||
sb.insert(0, interfaceName + "?");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static void parseEnabled(ConfigItem item, ConfiguratorConfig config, StringBuilder urlBuilder) {
|
||||
urlBuilder.append("&enabled=");
|
||||
if (item.getType() == null || ConfigItem.GENERAL_TYPE.equals(item.getType())) {
|
||||
urlBuilder.append(config.getEnabled());
|
||||
} else {
|
||||
urlBuilder.append(item.getEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> parseAddresses(ConfigItem item) {
|
||||
List<String> addresses = item.getAddresses();
|
||||
if (addresses == null) {
|
||||
addresses = new ArrayList<>();
|
||||
}
|
||||
if (addresses.isEmpty()) {
|
||||
addresses.add(ANYHOST_VALUE);
|
||||
}
|
||||
return addresses;
|
||||
}
|
||||
|
||||
private static URL appendMatchCondition(URL url, ConfigItem item) {
|
||||
if (item.getMatch() != null) {
|
||||
url = url.putAttribute(MATCH_CONDITION, item.getMatch());
|
||||
}
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* 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 + '\'' + '}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* 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.logger.ErrorTypeAwareLogger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.common.utils.PojoUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.CLUSTER_FAILED_RECEIVE_RULE;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ConfigItem {
|
||||
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(ConfigItem.class);
|
||||
|
||||
public static final String GENERAL_TYPE = "general";
|
||||
public static final String WEIGHT_TYPE = "weight";
|
||||
public static final String BALANCING_TYPE = "balancing";
|
||||
public static final String DISABLED_TYPE = "disabled";
|
||||
public static final String CONFIG_ITEM_TYPE = "type";
|
||||
public static final String ENABLED_KEY = "enabled";
|
||||
public static final String ADDRESSES_KEY = "addresses";
|
||||
public static final String PROVIDER_ADDRESSES_KEY = "providerAddresses";
|
||||
public static final String SERVICES_KEY = "services";
|
||||
public static final String APPLICATIONS_KEY = "applications";
|
||||
public static final String PARAMETERS_KEY = "parameters";
|
||||
public static final String MATCH_KEY = "match";
|
||||
public static final String SIDE_KEY = "side";
|
||||
|
||||
private String type;
|
||||
private Boolean enabled;
|
||||
private List<String> addresses;
|
||||
private List<String> providerAddresses;
|
||||
private List<String> services;
|
||||
private List<String> applications;
|
||||
private Map<String, String> parameters;
|
||||
private ConditionMatch match;
|
||||
private String side;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static ConfigItem parseFromMap(Map<String, Object> map) {
|
||||
ConfigItem configItem = new ConfigItem();
|
||||
configItem.setType((String) map.get(CONFIG_ITEM_TYPE));
|
||||
|
||||
Object enabled = map.get(ENABLED_KEY);
|
||||
if (enabled != null) {
|
||||
configItem.setEnabled(Boolean.parseBoolean(enabled.toString()));
|
||||
}
|
||||
|
||||
Object addresses = map.get(ADDRESSES_KEY);
|
||||
if (addresses != null && List.class.isAssignableFrom(addresses.getClass())) {
|
||||
configItem.setAddresses(
|
||||
((List<Object>) addresses).stream().map(String::valueOf).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
Object providerAddresses = map.get(PROVIDER_ADDRESSES_KEY);
|
||||
if (providerAddresses != null && List.class.isAssignableFrom(providerAddresses.getClass())) {
|
||||
configItem.setProviderAddresses(((List<Object>) providerAddresses)
|
||||
.stream().map(String::valueOf).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
Object services = map.get(SERVICES_KEY);
|
||||
if (services != null && List.class.isAssignableFrom(services.getClass())) {
|
||||
configItem.setServices(
|
||||
((List<Object>) services).stream().map(String::valueOf).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
Object applications = map.get(APPLICATIONS_KEY);
|
||||
if (applications != null && List.class.isAssignableFrom(applications.getClass())) {
|
||||
configItem.setApplications(
|
||||
((List<Object>) applications).stream().map(String::valueOf).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
Object parameters = map.get(PARAMETERS_KEY);
|
||||
if (parameters != null && Map.class.isAssignableFrom(parameters.getClass())) {
|
||||
configItem.setParameters(((Map<String, Object>) parameters)
|
||||
.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue()
|
||||
.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));
|
||||
return configItem;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Boolean getEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public List<String> getAddresses() {
|
||||
return addresses;
|
||||
}
|
||||
|
||||
public void setAddresses(List<String> addresses) {
|
||||
this.addresses = addresses;
|
||||
}
|
||||
|
||||
public List<String> getServices() {
|
||||
return services;
|
||||
}
|
||||
|
||||
public void setServices(List<String> services) {
|
||||
this.services = services;
|
||||
}
|
||||
|
||||
public List<String> getApplications() {
|
||||
return applications;
|
||||
}
|
||||
|
||||
public void setApplications(List<String> applications) {
|
||||
this.applications = applications;
|
||||
}
|
||||
|
||||
public List<String> getProviderAddresses() {
|
||||
return providerAddresses;
|
||||
}
|
||||
|
||||
public void setProviderAddresses(List<String> providerAddresses) {
|
||||
this.providerAddresses = providerAddresses;
|
||||
}
|
||||
|
||||
public Map<String, String> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public void setParameters(Map<String, String> parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public String getSide() {
|
||||
return side;
|
||||
}
|
||||
|
||||
public void setSide(String side) {
|
||||
this.side = side;
|
||||
}
|
||||
|
||||
public ConditionMatch getMatch() {
|
||||
return match;
|
||||
}
|
||||
|
||||
public void setMatch(ConditionMatch match) {
|
||||
this.match = match;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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 java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ConfiguratorConfig {
|
||||
public static final String MATCH_CONDITION = "MATCH_CONDITION";
|
||||
public static final String SCOPE_SERVICE = "service";
|
||||
public static final String SCOPE_APPLICATION = "application";
|
||||
public static final String CONFIG_VERSION_KEY = "configVersion";
|
||||
public static final String SCOPE_KEY = "scope";
|
||||
public static final String CONFIG_KEY = "key";
|
||||
public static final String ENABLED_KEY = "enabled";
|
||||
public static final String CONFIGS_KEY = "configs";
|
||||
private String configVersion;
|
||||
private String scope;
|
||||
private String key;
|
||||
private Boolean enabled = true;
|
||||
private List<ConfigItem> configs;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static ConfiguratorConfig parseFromMap(Map<String, Object> map) {
|
||||
ConfiguratorConfig configuratorConfig = new ConfiguratorConfig();
|
||||
configuratorConfig.setConfigVersion((String) map.get(CONFIG_VERSION_KEY));
|
||||
configuratorConfig.setScope((String) map.get(SCOPE_KEY));
|
||||
configuratorConfig.setKey((String) map.get(CONFIG_KEY));
|
||||
|
||||
Object enabled = map.get(ENABLED_KEY);
|
||||
if (enabled != null) {
|
||||
configuratorConfig.setEnabled(Boolean.parseBoolean(enabled.toString()));
|
||||
}
|
||||
|
||||
Object configs = map.get(CONFIGS_KEY);
|
||||
if (configs != null && List.class.isAssignableFrom(configs.getClass())) {
|
||||
configuratorConfig.setConfigs(((List<Map<String, Object>>) configs)
|
||||
.stream().map(ConfigItem::parseFromMap).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
return configuratorConfig;
|
||||
}
|
||||
|
||||
public String getConfigVersion() {
|
||||
return configVersion;
|
||||
}
|
||||
|
||||
public void setConfigVersion(String configVersion) {
|
||||
this.configVersion = configVersion;
|
||||
}
|
||||
|
||||
public String getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public void setScope(String scope) {
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public Boolean getEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public List<ConfigItem> getConfigs() {
|
||||
return configs;
|
||||
}
|
||||
|
||||
public void setConfigs(List<ConfigItem> configs) {
|
||||
this.configs = configs;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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 + '\'' + '}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,623 @@
|
|||
/*
|
||||
* 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.directory;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.Version;
|
||||
import org.apache.dubbo.common.config.Configuration;
|
||||
import org.apache.dubbo.common.config.ConfigurationUtils;
|
||||
import org.apache.dubbo.common.constants.LoggerCodeConstants;
|
||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
|
||||
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.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.Invoker;
|
||||
import org.apache.dubbo.rpc.RpcContext;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
import org.apache.dubbo.rpc.cluster.Directory;
|
||||
import org.apache.dubbo.rpc.cluster.Router;
|
||||
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.support.ClusterUtils;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
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.DEFAULT_RECONNECT_TASK_PERIOD;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_RECONNECT_TASK_TRY_COUNT;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
|
||||
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_TRY_COUNT;
|
||||
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.rpc.cluster.Constants.CONSUMER_URL_KEY;
|
||||
import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
|
||||
|
||||
/**
|
||||
* Abstract implementation of Directory: Invoker list returned from this Directory's list method have been filtered by Routers
|
||||
*/
|
||||
public abstract class AbstractDirectory<T> implements Directory<T> {
|
||||
|
||||
// logger
|
||||
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(AbstractDirectory.class);
|
||||
|
||||
private final URL url;
|
||||
|
||||
private volatile boolean destroyed = false;
|
||||
|
||||
protected volatile URL consumerUrl;
|
||||
|
||||
protected RouterChain<T> routerChain;
|
||||
|
||||
protected final Map<String, String> queryMap;
|
||||
|
||||
/**
|
||||
* Invokers initialized flag.
|
||||
*/
|
||||
private volatile boolean invokersInitialized = false;
|
||||
|
||||
/**
|
||||
* All invokers from registry
|
||||
*/
|
||||
private volatile BitList<Invoker<T>> invokers = BitList.emptyList();
|
||||
|
||||
/**
|
||||
* Valid Invoker. All invokers from registry exclude unavailable and disabled invokers.
|
||||
*/
|
||||
private volatile BitList<Invoker<T>> validInvokers = BitList.emptyList();
|
||||
|
||||
/**
|
||||
* Waiting to reconnect invokers.
|
||||
*/
|
||||
protected volatile List<Invoker<T>> invokersToReconnect = new CopyOnWriteArrayList<>();
|
||||
|
||||
/**
|
||||
* Disabled Invokers. Will not be recovered in reconnect task, but be recovered if registry remove it.
|
||||
*/
|
||||
protected final Set<Invoker<T>> disabledInvokers = new ConcurrentHashSet<>();
|
||||
|
||||
private final Semaphore checkConnectivityPermit = new Semaphore(1);
|
||||
|
||||
private final ScheduledExecutorService connectivityExecutor;
|
||||
|
||||
private volatile ScheduledFuture<?> connectivityCheckFuture;
|
||||
|
||||
private final ReentrantLock invokerRefreshLock = new ReentrantLock();
|
||||
|
||||
/**
|
||||
* The max count of invokers for each reconnect task select to try to reconnect.
|
||||
*/
|
||||
private final int reconnectTaskTryCount;
|
||||
|
||||
/**
|
||||
* The period of reconnect task if needed. (in ms)
|
||||
*/
|
||||
private final int reconnectTaskPeriod;
|
||||
|
||||
private ApplicationModel applicationModel;
|
||||
|
||||
public AbstractDirectory(URL url) {
|
||||
this(url, null, false);
|
||||
}
|
||||
|
||||
public AbstractDirectory(URL url, boolean isUrlFromRegistry) {
|
||||
this(url, null, isUrlFromRegistry);
|
||||
}
|
||||
|
||||
public AbstractDirectory(URL url, RouterChain<T> routerChain, boolean isUrlFromRegistry) {
|
||||
if (url == null) {
|
||||
throw new IllegalArgumentException("url == null");
|
||||
}
|
||||
|
||||
this.url = url.removeAttribute(REFER_KEY).removeAttribute(MONITOR_KEY);
|
||||
|
||||
Map<String, String> queryMap;
|
||||
Object referParams = url.getAttribute(REFER_KEY);
|
||||
if (referParams instanceof Map) {
|
||||
queryMap = (Map<String, String>) referParams;
|
||||
this.consumerUrl = (URL) url.getAttribute(CONSUMER_URL_KEY);
|
||||
} else {
|
||||
queryMap = StringUtils.parseQueryString(url.getParameterAndDecoded(REFER_KEY));
|
||||
}
|
||||
|
||||
// remove some local only parameters
|
||||
applicationModel = url.getOrDefaultApplicationModel();
|
||||
this.queryMap =
|
||||
applicationModel.getBeanFactory().getBean(ClusterUtils.class).mergeLocalParams(queryMap);
|
||||
|
||||
if (consumerUrl == null) {
|
||||
String host =
|
||||
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 consumedProtocol = isNotEmpty(queryMap.get(PROTOCOL_KEY)) ? queryMap.get(PROTOCOL_KEY) : CONSUMER;
|
||||
|
||||
URL consumerUrlFrom = this.url
|
||||
.setHost(host)
|
||||
.setPort(0)
|
||||
.setProtocol(consumedProtocol)
|
||||
.setPath(path);
|
||||
if (isUrlFromRegistry) {
|
||||
// reserve parameters if url is already a consumer url
|
||||
consumerUrlFrom = consumerUrlFrom.clearParameters();
|
||||
}
|
||||
this.consumerUrl = consumerUrlFrom.addParameters(queryMap);
|
||||
}
|
||||
|
||||
this.connectivityExecutor = applicationModel
|
||||
.getFrameworkModel()
|
||||
.getBeanFactory()
|
||||
.getBean(FrameworkExecutorRepository.class)
|
||||
.getConnectivityScheduledExecutor();
|
||||
Configuration configuration = ConfigurationUtils.getGlobalConfiguration(url.getOrDefaultModuleModel());
|
||||
this.reconnectTaskTryCount = configuration.getInt(RECONNECT_TASK_TRY_COUNT, DEFAULT_RECONNECT_TASK_TRY_COUNT);
|
||||
this.reconnectTaskPeriod = configuration.getInt(RECONNECT_TASK_PERIOD, DEFAULT_RECONNECT_TASK_PERIOD);
|
||||
setRouterChain(routerChain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Invoker<T>> list(Invocation invocation) throws RpcException {
|
||||
if (destroyed) {
|
||||
throw new RpcException(
|
||||
"Directory of type " + this.getClass().getSimpleName() + " already destroyed for service "
|
||||
+ getConsumerUrl().getServiceKey() + " from registry " + getUrl());
|
||||
}
|
||||
|
||||
BitList<Invoker<T>> availableInvokers;
|
||||
SingleRouterChain<T> singleChain = null;
|
||||
try {
|
||||
try {
|
||||
if (routerChain != null) {
|
||||
routerChain.getLock().readLock().lock();
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public RouterChain<T> getRouterChain() {
|
||||
return routerChain;
|
||||
}
|
||||
|
||||
public void setRouterChain(RouterChain<T> routerChain) {
|
||||
this.routerChain = routerChain;
|
||||
}
|
||||
|
||||
protected void addRouters(List<Router> routers) {
|
||||
routers = routers == null ? Collections.emptyList() : routers;
|
||||
routerChain.addRouters(routers);
|
||||
}
|
||||
|
||||
public URL getConsumerUrl() {
|
||||
return consumerUrl;
|
||||
}
|
||||
|
||||
public void setConsumerUrl(URL consumerUrl) {
|
||||
this.consumerUrl = consumerUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDestroyed() {
|
||||
return destroyed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
destroyed = true;
|
||||
destroyInvokers();
|
||||
invokersToReconnect.clear();
|
||||
disabledInvokers.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void discordAddresses() {
|
||||
// do nothing by default
|
||||
}
|
||||
|
||||
@Override
|
||||
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
|
||||
if (removeValidInvoker(invoker)) {
|
||||
// 2. add this invoker to reconnect list
|
||||
invokersToReconnect.add(invoker);
|
||||
// 3. try start check connectivity task
|
||||
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() {
|
||||
// try to submit task, to ensure there is only one task at most for each directory
|
||||
if (checkConnectivityPermit.tryAcquire()) {
|
||||
this.connectivityCheckFuture = connectivityExecutor.schedule(
|
||||
() -> {
|
||||
try {
|
||||
if (isDestroyed()) {
|
||||
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
|
||||
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
|
||||
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
|
||||
if (!invokersToReconnect.isEmpty()) {
|
||||
checkConnectivity();
|
||||
}
|
||||
});
|
||||
MetricsEventBus.publish(RegistryEvent.refreshDirectoryEvent(
|
||||
applicationModel, getSummary(), getDirectoryMeta()));
|
||||
},
|
||||
reconnectTaskPeriod,
|
||||
TimeUnit.MILLISECONDS);
|
||||
}
|
||||
MetricsEventBus.publish(
|
||||
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh invokers from total invokers
|
||||
* 1. all the invokers in need to reconnect list should be removed in the valid invokers list
|
||||
* 2. all the invokers in disabled invokers list should be removed in the valid invokers list
|
||||
* 3. all the invokers disappeared from total invokers should be removed in the need to reconnect list
|
||||
* 4. all the invokers disappeared from total invokers should be removed in the disabled invokers list
|
||||
*/
|
||||
public void refreshInvoker() {
|
||||
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
|
||||
if (invokersInitialized) {
|
||||
refreshInvokerInternal();
|
||||
}
|
||||
});
|
||||
MetricsEventBus.publish(
|
||||
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
|
||||
}
|
||||
|
||||
protected Map<String, String> getDirectoryMeta() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
private void refreshInvokerInternal() {
|
||||
BitList<Invoker<T>> copiedInvokers = invokers.clone();
|
||||
refreshInvokers(copiedInvokers, invokersToReconnect);
|
||||
refreshInvokers(copiedInvokers, disabledInvokers);
|
||||
validInvokers = copiedInvokers;
|
||||
}
|
||||
|
||||
private void refreshInvokers(BitList<Invoker<T>> targetInvokers, Collection<Invoker<T>> invokersToRemove) {
|
||||
List<Invoker<T>> needToRemove = new LinkedList<>();
|
||||
for (Invoker<T> tInvoker : invokersToRemove) {
|
||||
if (targetInvokers.contains(tInvoker)) {
|
||||
targetInvokers.remove(tInvoker);
|
||||
} else {
|
||||
needToRemove.add(tInvoker);
|
||||
}
|
||||
}
|
||||
invokersToRemove.removeAll(needToRemove);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDisabledInvoker(Invoker<T> invoker) {
|
||||
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
|
||||
if (invokers.contains(invoker)) {
|
||||
disabledInvokers.add(invoker);
|
||||
removeValidInvoker(invoker);
|
||||
logger.info("Disable service address: " + invoker.getUrl() + ".");
|
||||
}
|
||||
});
|
||||
MetricsEventBus.publish(
|
||||
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recoverDisabledInvoker(Invoker<T> invoker) {
|
||||
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
|
||||
if (disabledInvokers.remove(invoker)) {
|
||||
try {
|
||||
addValidInvoker(invoker);
|
||||
logger.info("Recover service address: " + invoker.getUrl() + " from disabled list.");
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* for ut only
|
||||
*/
|
||||
@Deprecated
|
||||
public Semaphore getCheckConnectivityPermit() {
|
||||
return checkConnectivityPermit;
|
||||
}
|
||||
|
||||
/**
|
||||
* for ut only
|
||||
*/
|
||||
@Deprecated
|
||||
public ScheduledFuture<?> getConnectivityCheckFuture() {
|
||||
return connectivityCheckFuture;
|
||||
}
|
||||
|
||||
public BitList<Invoker<T>> getInvokers() {
|
||||
// return clone to avoid being modified.
|
||||
return invokers.clone();
|
||||
}
|
||||
|
||||
public BitList<Invoker<T>> getValidInvokers() {
|
||||
// return clone to avoid being modified.
|
||||
return validInvokers.clone();
|
||||
}
|
||||
|
||||
public List<Invoker<T>> getInvokersToReconnect() {
|
||||
return invokersToReconnect;
|
||||
}
|
||||
|
||||
public Set<Invoker<T>> getDisabledInvokers() {
|
||||
return disabledInvokers;
|
||||
}
|
||||
|
||||
protected void setInvokers(BitList<Invoker<T>> invokers) {
|
||||
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
|
||||
this.invokers = invokers;
|
||||
refreshInvokerInternal();
|
||||
this.invokersInitialized = true;
|
||||
});
|
||||
|
||||
MetricsEventBus.publish(
|
||||
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
|
||||
}
|
||||
|
||||
protected void destroyInvokers() {
|
||||
// set empty instead of clearing to support concurrent access.
|
||||
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
|
||||
this.invokers = BitList.emptyList();
|
||||
this.validInvokers = BitList.emptyList();
|
||||
this.invokersInitialized = false;
|
||||
});
|
||||
}
|
||||
|
||||
private boolean addValidInvoker(Invoker<T> invoker) {
|
||||
AtomicBoolean result = new AtomicBoolean(false);
|
||||
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
|
||||
result.set(this.validInvokers.add(invoker));
|
||||
});
|
||||
MetricsEventBus.publish(
|
||||
RegistryEvent.refreshDirectoryEvent(applicationModel, getSummary(), getDirectoryMeta()));
|
||||
return result.get();
|
||||
}
|
||||
|
||||
private boolean removeValidInvoker(Invoker<T> invoker) {
|
||||
AtomicBoolean result = new AtomicBoolean(false);
|
||||
LockUtils.safeLock(invokerRefreshLock, LockUtils.DEFAULT_TIMEOUT, () -> {
|
||||
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() {
|
||||
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(", "))
|
||||
+ "]" + ')';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* 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.directory;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
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.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
import org.apache.dubbo.rpc.cluster.RouterChain;
|
||||
import org.apache.dubbo.rpc.cluster.SingleRouterChain;
|
||||
import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
||||
|
||||
import java.util.HashMap;
|
||||
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
|
||||
*/
|
||||
public class StaticDirectory<T> extends AbstractDirectory<T> {
|
||||
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(StaticDirectory.class);
|
||||
private final Class<T> interfaceClass;
|
||||
|
||||
public StaticDirectory(List<Invoker<T>> invokers) {
|
||||
this(null, invokers, null);
|
||||
}
|
||||
|
||||
public StaticDirectory(List<Invoker<T>> invokers, RouterChain<T> routerChain) {
|
||||
this(null, invokers, routerChain);
|
||||
}
|
||||
|
||||
public StaticDirectory(URL url, List<Invoker<T>> invokers) {
|
||||
this(url, invokers, null);
|
||||
}
|
||||
|
||||
public StaticDirectory(URL url, List<Invoker<T>> invokers, RouterChain<T> routerChain) {
|
||||
super(
|
||||
url == null && CollectionUtils.isNotEmpty(invokers)
|
||||
? invokers.get(0).getUrl()
|
||||
: url,
|
||||
routerChain,
|
||||
false);
|
||||
if (CollectionUtils.isEmpty(invokers)) {
|
||||
throw new IllegalArgumentException("invokers == null");
|
||||
}
|
||||
this.setInvokers(new BitList<>(invokers));
|
||||
this.interfaceClass = invokers.get(0).getInterface();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getInterface() {
|
||||
return interfaceClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Invoker<T>> getAllInvokers() {
|
||||
return getInvokers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (isDestroyed()) {
|
||||
return false;
|
||||
}
|
||||
for (Invoker<T> invoker : getValidInvokers()) {
|
||||
if (invoker.isAvailable()) {
|
||||
return true;
|
||||
} else {
|
||||
addInvalidateInvoker(invoker);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
if (isDestroyed()) {
|
||||
return;
|
||||
}
|
||||
for (Invoker<T> invoker : getInvokers()) {
|
||||
invoker.destroy();
|
||||
}
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
public void buildRouterChain() {
|
||||
RouterChain<T> routerChain = RouterChain.buildChain(getInterface(), getUrl());
|
||||
routerChain.setInvokers(getInvokers(), () -> {});
|
||||
this.setRouterChain(routerChain);
|
||||
}
|
||||
|
||||
public void notify(List<Invoker<T>> invokers) {
|
||||
BitList<Invoker<T>> bitList = new BitList<>(invokers);
|
||||
if (routerChain != null) {
|
||||
refreshRouter(bitList.clone(), () -> this.setInvokers(bitList));
|
||||
} else {
|
||||
this.setInvokers(bitList);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Invoker<T>> doList(
|
||||
SingleRouterChain<T> singleRouterChain, BitList<Invoker<T>> invokers, Invocation invocation)
|
||||
throws RpcException {
|
||||
if (singleRouterChain != null) {
|
||||
try {
|
||||
List<Invoker<T>> finalInvokers = singleRouterChain.route(getConsumerUrl(), invokers, invocation);
|
||||
return finalInvokers == null ? BitList.emptyList() : finalInvokers;
|
||||
} catch (Throwable t) {
|
||||
logger.error(
|
||||
CLUSTER_FAILED_SITE_SELECTION,
|
||||
"Failed to execute router",
|
||||
"",
|
||||
"Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(),
|
||||
t);
|
||||
return BitList.emptyList();
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.apache.dubbo.common.extension.ExtensionScope;
|
||||
import org.apache.dubbo.common.extension.SPI;
|
||||
import org.apache.dubbo.rpc.BaseFilter;
|
||||
|
||||
@SPI(scope = ExtensionScope.MODULE)
|
||||
public interface ClusterFilter extends BaseFilter {}
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.extension.Activate;
|
||||
import org.apache.dubbo.common.extension.ExtensionDirector;
|
||||
import org.apache.dubbo.common.extension.support.ActivateComparator;
|
||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||
import org.apache.dubbo.rpc.Filter;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.cluster.ClusterInvoker;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.apache.dubbo.rpc.model.ModuleModel;
|
||||
import org.apache.dubbo.rpc.model.ScopeModel;
|
||||
import org.apache.dubbo.rpc.model.ScopeModelUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
@Activate
|
||||
public class DefaultFilterChainBuilder implements FilterChainBuilder {
|
||||
|
||||
/**
|
||||
* build consumer/provider filter chain
|
||||
*/
|
||||
@Override
|
||||
public <T> Invoker<T> buildInvokerChain(final Invoker<T> originalInvoker, String key, String group) {
|
||||
Invoker<T> last = originalInvoker;
|
||||
URL url = originalInvoker.getUrl();
|
||||
List<ModuleModel> moduleModels = getModuleModelsFromUrl(url);
|
||||
List<Filter> filters;
|
||||
if (moduleModels != null && moduleModels.size() == 1) {
|
||||
filters = ScopeModelUtil.getExtensionLoader(Filter.class, moduleModels.get(0))
|
||||
.getActivateExtension(url, key, group);
|
||||
} else if (moduleModels != null && moduleModels.size() > 1) {
|
||||
filters = new ArrayList<>();
|
||||
List<ExtensionDirector> directors = new ArrayList<>();
|
||||
for (ModuleModel moduleModel : moduleModels) {
|
||||
List<Filter> tempFilters = ScopeModelUtil.getExtensionLoader(Filter.class, moduleModel)
|
||||
.getActivateExtension(url, key, group);
|
||||
filters.addAll(tempFilters);
|
||||
directors.add(moduleModel.getExtensionDirector());
|
||||
}
|
||||
filters = sortingAndDeduplication(filters, directors);
|
||||
|
||||
} else {
|
||||
filters = ScopeModelUtil.getExtensionLoader(Filter.class, null).getActivateExtension(url, key, group);
|
||||
}
|
||||
|
||||
if (!CollectionUtils.isEmpty(filters)) {
|
||||
for (int i = filters.size() - 1; i >= 0; i--) {
|
||||
final Filter filter = filters.get(i);
|
||||
final Invoker<T> next = last;
|
||||
last = new CopyOfFilterChainNode<>(originalInvoker, next, filter);
|
||||
}
|
||||
return new CallbackRegistrationInvoker<>(last, filters);
|
||||
}
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
/**
|
||||
* build consumer cluster filter chain
|
||||
*/
|
||||
@Override
|
||||
public <T> ClusterInvoker<T> buildClusterInvokerChain(
|
||||
final ClusterInvoker<T> originalInvoker, String key, String group) {
|
||||
ClusterInvoker<T> last = originalInvoker;
|
||||
URL url = originalInvoker.getUrl();
|
||||
List<ModuleModel> moduleModels = getModuleModelsFromUrl(url);
|
||||
List<ClusterFilter> filters;
|
||||
if (moduleModels != null && moduleModels.size() == 1) {
|
||||
filters = ScopeModelUtil.getExtensionLoader(ClusterFilter.class, moduleModels.get(0))
|
||||
.getActivateExtension(url, key, group);
|
||||
} else if (moduleModels != null && moduleModels.size() > 1) {
|
||||
filters = new ArrayList<>();
|
||||
List<ExtensionDirector> directors = new ArrayList<>();
|
||||
for (ModuleModel moduleModel : moduleModels) {
|
||||
List<ClusterFilter> tempFilters = ScopeModelUtil.getExtensionLoader(ClusterFilter.class, moduleModel)
|
||||
.getActivateExtension(url, key, group);
|
||||
filters.addAll(tempFilters);
|
||||
directors.add(moduleModel.getExtensionDirector());
|
||||
}
|
||||
filters = sortingAndDeduplication(filters, directors);
|
||||
|
||||
} else {
|
||||
filters =
|
||||
ScopeModelUtil.getExtensionLoader(ClusterFilter.class, null).getActivateExtension(url, key, group);
|
||||
}
|
||||
|
||||
if (!CollectionUtils.isEmpty(filters)) {
|
||||
for (int i = filters.size() - 1; i >= 0; i--) {
|
||||
final ClusterFilter filter = filters.get(i);
|
||||
final Invoker<T> next = last;
|
||||
last = new CopyOfClusterFilterChainNode<>(originalInvoker, next, filter);
|
||||
}
|
||||
return new ClusterCallbackRegistrationInvoker<>(originalInvoker, last, filters);
|
||||
}
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
private <T> List<T> sortingAndDeduplication(List<T> filters, List<ExtensionDirector> directors) {
|
||||
Map<Class<?>, T> filtersSet = new TreeMap<>(new ActivateComparator(directors));
|
||||
for (T filter : filters) {
|
||||
filtersSet.putIfAbsent(filter.getClass(), filter);
|
||||
}
|
||||
return new ArrayList<>(filtersSet.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* When the application-level service registration and discovery strategy is adopted, the URL will be of type InstanceAddressURL,
|
||||
* and InstanceAddressURL belongs to the application layer and holds the ApplicationModel,
|
||||
* but the filter is at the module layer and holds the ModuleModel,
|
||||
* so it needs to be based on the url in the ScopeModel type to parse out all the moduleModels held by the url
|
||||
* to obtain the filter configuration.
|
||||
*
|
||||
* @param url URL
|
||||
* @return All ModuleModels in the url
|
||||
*/
|
||||
private List<ModuleModel> getModuleModelsFromUrl(URL url) {
|
||||
List<ModuleModel> moduleModels = null;
|
||||
ScopeModel scopeModel = url.getScopeModel();
|
||||
if (scopeModel instanceof ApplicationModel) {
|
||||
moduleModels = ((ApplicationModel) scopeModel).getPubModuleModels();
|
||||
} else if (scopeModel instanceof ModuleModel) {
|
||||
moduleModels = new ArrayList<>();
|
||||
moduleModels.add((ModuleModel) scopeModel);
|
||||
}
|
||||
return moduleModels;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,415 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.apache.dubbo.common.Experimental;
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.extension.SPI;
|
||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.rpc.AsyncRpcResult;
|
||||
import org.apache.dubbo.rpc.BaseFilter;
|
||||
import org.apache.dubbo.rpc.Filter;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.InvocationProfilerUtils;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.ListenableFilter;
|
||||
import org.apache.dubbo.rpc.Result;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
import org.apache.dubbo.rpc.cluster.ClusterInvoker;
|
||||
import org.apache.dubbo.rpc.cluster.Directory;
|
||||
|
||||
import java.util.List;
|
||||
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;
|
||||
|
||||
@SPI(value = "default", scope = APPLICATION)
|
||||
public interface FilterChainBuilder {
|
||||
/**
|
||||
* build consumer/provider filter chain
|
||||
*/
|
||||
<T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group);
|
||||
|
||||
/**
|
||||
* build consumer cluster filter chain
|
||||
*/
|
||||
<T> ClusterInvoker<T> buildClusterInvokerChain(final ClusterInvoker<T> invoker, String key, String group);
|
||||
|
||||
/**
|
||||
* Works on provider side
|
||||
*
|
||||
* @param <T>
|
||||
* @param <TYPE>
|
||||
*/
|
||||
class FilterChainNode<T, TYPE extends Invoker<T>, FILTER extends BaseFilter> implements Invoker<T> {
|
||||
TYPE originalInvoker;
|
||||
Invoker<T> nextNode;
|
||||
FILTER filter;
|
||||
|
||||
public FilterChainNode(TYPE originalInvoker, Invoker<T> nextNode, FILTER filter) {
|
||||
this.originalInvoker = originalInvoker;
|
||||
this.nextNode = nextNode;
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
public TYPE getOriginalInvoker() {
|
||||
return originalInvoker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getInterface() {
|
||||
return originalInvoker.getInterface();
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getUrl() {
|
||||
return originalInvoker.getUrl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return originalInvoker.isAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result invoke(Invocation invocation) throws RpcException {
|
||||
Result asyncResult;
|
||||
try {
|
||||
InvocationProfilerUtils.enterDetailProfiler(
|
||||
invocation, () -> "Filter " + filter.getClass().getName() + " invoke.");
|
||||
asyncResult = filter.invoke(nextNode, invocation);
|
||||
} catch (Exception e) {
|
||||
InvocationProfilerUtils.releaseDetailProfiler(invocation);
|
||||
if (filter instanceof ListenableFilter) {
|
||||
ListenableFilter listenableFilter = ((ListenableFilter) filter);
|
||||
try {
|
||||
Filter.Listener listener = listenableFilter.listener(invocation);
|
||||
if (listener != null) {
|
||||
listener.onError(e, originalInvoker, invocation);
|
||||
}
|
||||
} finally {
|
||||
listenableFilter.removeListener(invocation);
|
||||
}
|
||||
} else if (filter instanceof FILTER.Listener) {
|
||||
FILTER.Listener listener = (FILTER.Listener) filter;
|
||||
listener.onError(e, originalInvoker, invocation);
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
|
||||
}
|
||||
return asyncResult.whenCompleteWithContext((r, t) -> {
|
||||
InvocationProfilerUtils.releaseDetailProfiler(invocation);
|
||||
if (filter instanceof ListenableFilter) {
|
||||
ListenableFilter listenableFilter = ((ListenableFilter) filter);
|
||||
Filter.Listener listener = listenableFilter.listener(invocation);
|
||||
try {
|
||||
if (listener != null) {
|
||||
if (t == null) {
|
||||
listener.onResponse(r, originalInvoker, invocation);
|
||||
} else {
|
||||
listener.onError(t, originalInvoker, invocation);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
listenableFilter.removeListener(invocation);
|
||||
}
|
||||
} else if (filter instanceof FILTER.Listener) {
|
||||
FILTER.Listener listener = (FILTER.Listener) filter;
|
||||
if (t == null) {
|
||||
listener.onResponse(r, originalInvoker, invocation);
|
||||
} else {
|
||||
listener.onError(t, originalInvoker, invocation);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
originalInvoker.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return originalInvoker.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Works on consumer side
|
||||
*
|
||||
* @param <T>
|
||||
* @param <TYPE>
|
||||
*/
|
||||
class ClusterFilterChainNode<T, TYPE extends ClusterInvoker<T>, FILTER extends BaseFilter>
|
||||
extends FilterChainNode<T, TYPE, FILTER> implements ClusterInvoker<T> {
|
||||
public ClusterFilterChainNode(TYPE originalInvoker, Invoker<T> nextNode, FILTER filter) {
|
||||
super(originalInvoker, nextNode, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getRegistryUrl() {
|
||||
return getOriginalInvoker().getRegistryUrl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Directory<T> getDirectory() {
|
||||
return getOriginalInvoker().getDirectory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDestroyed() {
|
||||
return getOriginalInvoker().isDestroyed();
|
||||
}
|
||||
}
|
||||
|
||||
class CallbackRegistrationInvoker<T, FILTER extends BaseFilter> implements Invoker<T> {
|
||||
private static final ErrorTypeAwareLogger LOGGER =
|
||||
LoggerFactory.getErrorTypeAwareLogger(CallbackRegistrationInvoker.class);
|
||||
final Invoker<T> filterInvoker;
|
||||
final List<FILTER> filters;
|
||||
|
||||
public CallbackRegistrationInvoker(Invoker<T> filterInvoker, List<FILTER> filters) {
|
||||
this.filterInvoker = filterInvoker;
|
||||
this.filters = filters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result invoke(Invocation invocation) throws RpcException {
|
||||
Result asyncResult = filterInvoker.invoke(invocation);
|
||||
asyncResult.whenCompleteWithContext((r, t) -> {
|
||||
RuntimeException filterRuntimeException = null;
|
||||
for (int i = filters.size() - 1; i >= 0; i--) {
|
||||
FILTER filter = filters.get(i);
|
||||
try {
|
||||
InvocationProfilerUtils.releaseDetailProfiler(invocation);
|
||||
if (filter instanceof ListenableFilter) {
|
||||
ListenableFilter listenableFilter = ((ListenableFilter) filter);
|
||||
Filter.Listener listener = listenableFilter.listener(invocation);
|
||||
try {
|
||||
if (listener != null) {
|
||||
if (t == null) {
|
||||
listener.onResponse(r, filterInvoker, invocation);
|
||||
} else {
|
||||
listener.onError(t, filterInvoker, invocation);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
listenableFilter.removeListener(invocation);
|
||||
}
|
||||
} else if (filter instanceof FILTER.Listener) {
|
||||
FILTER.Listener listener = (FILTER.Listener) filter;
|
||||
if (t == null) {
|
||||
listener.onResponse(r, filterInvoker, invocation);
|
||||
} else {
|
||||
listener.onError(t, filterInvoker, invocation);
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException runtimeException) {
|
||||
LOGGER.error(
|
||||
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()) {
|
||||
LOGGER.debug(String.format(
|
||||
"Whole filter list is: %s",
|
||||
filters.stream()
|
||||
.map(tmpFilter ->
|
||||
tmpFilter.getClass().getSimpleName())
|
||||
.collect(Collectors.toList())));
|
||||
}
|
||||
filterRuntimeException = runtimeException;
|
||||
t = runtimeException;
|
||||
}
|
||||
}
|
||||
if (filterRuntimeException != null) {
|
||||
throw filterRuntimeException;
|
||||
}
|
||||
});
|
||||
|
||||
return asyncResult;
|
||||
}
|
||||
|
||||
public Invoker<T> getFilterInvoker() {
|
||||
return filterInvoker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getInterface() {
|
||||
return filterInvoker.getInterface();
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getUrl() {
|
||||
return filterInvoker.getUrl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return filterInvoker.isAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
filterInvoker.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
class ClusterCallbackRegistrationInvoker<T, FILTER extends BaseFilter>
|
||||
extends CallbackRegistrationInvoker<T, FILTER> implements ClusterInvoker<T> {
|
||||
private ClusterInvoker<T> originalInvoker;
|
||||
|
||||
public ClusterCallbackRegistrationInvoker(
|
||||
ClusterInvoker<T> originalInvoker, Invoker<T> filterInvoker, List<FILTER> filters) {
|
||||
super(filterInvoker, filters);
|
||||
this.originalInvoker = originalInvoker;
|
||||
}
|
||||
|
||||
public ClusterInvoker<T> getOriginalInvoker() {
|
||||
return originalInvoker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getRegistryUrl() {
|
||||
return getOriginalInvoker().getRegistryUrl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Directory<T> getDirectory() {
|
||||
return getOriginalInvoker().getDirectory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDestroyed() {
|
||||
return getOriginalInvoker().isDestroyed();
|
||||
}
|
||||
}
|
||||
|
||||
@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> {
|
||||
private static final ErrorTypeAwareLogger LOGGER =
|
||||
LoggerFactory.getErrorTypeAwareLogger(CopyOfFilterChainNode.class);
|
||||
TYPE originalInvoker;
|
||||
Invoker<T> nextNode;
|
||||
FILTER filter;
|
||||
|
||||
public CopyOfFilterChainNode(TYPE originalInvoker, Invoker<T> nextNode, FILTER filter) {
|
||||
this.originalInvoker = originalInvoker;
|
||||
this.nextNode = nextNode;
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
public TYPE getOriginalInvoker() {
|
||||
return originalInvoker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getInterface() {
|
||||
return originalInvoker.getInterface();
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getUrl() {
|
||||
return originalInvoker.getUrl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return originalInvoker.isAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result invoke(Invocation invocation) throws RpcException {
|
||||
Result asyncResult;
|
||||
try {
|
||||
InvocationProfilerUtils.enterDetailProfiler(
|
||||
invocation, () -> "Filter " + filter.getClass().getName() + " invoke.");
|
||||
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) {
|
||||
InvocationProfilerUtils.releaseDetailProfiler(invocation);
|
||||
if (filter instanceof ListenableFilter) {
|
||||
ListenableFilter listenableFilter = ((ListenableFilter) filter);
|
||||
try {
|
||||
Filter.Listener listener = listenableFilter.listener(invocation);
|
||||
if (listener != null) {
|
||||
listener.onError(e, originalInvoker, invocation);
|
||||
}
|
||||
} finally {
|
||||
listenableFilter.removeListener(invocation);
|
||||
}
|
||||
} else if (filter instanceof FILTER.Listener) {
|
||||
FILTER.Listener listener = (FILTER.Listener) filter;
|
||||
listener.onError(e, originalInvoker, invocation);
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
|
||||
}
|
||||
return asyncResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
originalInvoker.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return originalInvoker.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Experimental(
|
||||
"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>
|
||||
extends CopyOfFilterChainNode<T, TYPE, FILTER> implements ClusterInvoker<T> {
|
||||
public CopyOfClusterFilterChainNode(TYPE originalInvoker, Invoker<T> nextNode, FILTER filter) {
|
||||
super(originalInvoker, nextNode, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getRegistryUrl() {
|
||||
return getOriginalInvoker().getRegistryUrl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Directory<T> getDirectory() {
|
||||
return getOriginalInvoker().getDirectory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDestroyed() {
|
||||
return getOriginalInvoker().isDestroyed();
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue