Compare commits
181 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
58d1259cb9 | |
|
|
0aee810166 | |
|
|
3b2b20b34c | |
|
|
40f44fe0e6 | |
|
|
42c3a07db3 | |
|
|
41b0a22ea4 | |
|
|
6ea05b5a20 | |
|
|
e9d35554c7 | |
|
|
59da412eae | |
|
|
2e39f6d31b | |
|
|
f62ca3f71a | |
|
|
86b5e00ba2 | |
|
|
5e68e43912 | |
|
|
3f1e3f491d | |
|
|
fc1bdfa945 | |
|
|
c5ed7def80 | |
|
|
115cc7ff9d | |
|
|
077da34add | |
|
|
3a9172fcfa | |
|
|
9783ef060a | |
|
|
1d60fdf85a | |
|
|
6cea97fcad | |
|
|
37c3460bf7 | |
|
|
346c668386 | |
|
|
b100a6d22b | |
|
|
7165e382d8 | |
|
|
89e5fe0f27 | |
|
|
951d30644a | |
|
|
c66d95ab3e | |
|
|
b442d2bc8d | |
|
|
87a634db05 | |
|
|
34d1a3724d | |
|
|
64d8e36ff3 | |
|
|
e10b8dd6a9 | |
|
|
c894e06335 | |
|
|
d895bf15d0 | |
|
|
5e2c07c1dc | |
|
|
4a8abfd0ba | |
|
|
a9f0762f5e | |
|
|
59320a9eeb | |
|
|
280d54c07d | |
|
|
e778d5ad3a | |
|
|
585bb1193f | |
|
|
bada690763 | |
|
|
5a6a069986 | |
|
|
8c2141cd1c | |
|
|
98cfbd6535 | |
|
|
112990d063 | |
|
|
a8f6f99e43 | |
|
|
69cc9bded6 | |
|
|
07bcafb3ae | |
|
|
89b213f78d | |
|
|
77970748f2 | |
|
|
116c9c33eb | |
|
|
5d6baa5489 | |
|
|
36fc6c566f | |
|
|
5bdbc886cb | |
|
|
5c5ac0ab90 | |
|
|
8969b34b09 | |
|
|
281ab19ed4 | |
|
|
6f593a6fd2 | |
|
|
c8facc5ef6 | |
|
|
6702cbdb0e | |
|
|
0e886a966c | |
|
|
f932569938 | |
|
|
87a2f07542 | |
|
|
ef176f96f3 | |
|
|
ffce958ee0 | |
|
|
68042366c2 | |
|
|
10309b36d3 | |
|
|
4785a27fb4 | |
|
|
5672e52b12 | |
|
|
8683da7231 | |
|
|
00a8edcc26 | |
|
|
ef2cae1fc0 | |
|
|
d430ca9b17 | |
|
|
ba7f6f38c3 | |
|
|
2970f87373 | |
|
|
34b9ebfb2d | |
|
|
c528d56b6e | |
|
|
fec3363b74 | |
|
|
4a28ea1379 | |
|
|
badea862d3 | |
|
|
40b0ff28f3 | |
|
|
0f9cef935d | |
|
|
54e14e905c | |
|
|
342e814296 | |
|
|
19f30941f2 | |
|
|
43d8620cee | |
|
|
7fbfc37e58 | |
|
|
3375ec8278 | |
|
|
ac49a7d34a | |
|
|
483cd7c45f | |
|
|
0e50d65511 | |
|
|
1be26c9965 | |
|
|
38e0f15be3 | |
|
|
7b1985a1a6 | |
|
|
c290991cb5 | |
|
|
faa0abf7c2 | |
|
|
9cc4f933a2 | |
|
|
7629e73090 | |
|
|
86c473771a | |
|
|
a1b27ab18c | |
|
|
d6aae075b1 | |
|
|
ef4ecdf3a3 | |
|
|
5da01b1d27 | |
|
|
f2d73f7914 | |
|
|
0b0e8b5c0a | |
|
|
bcb1899f31 | |
|
|
4cd9619130 | |
|
|
2af5a6ddbb | |
|
|
c84d79f99f | |
|
|
c5a5b64a10 | |
|
|
bb9fd69233 | |
|
|
e0bf21aed5 | |
|
|
e4725cd687 | |
|
|
f58997f4aa | |
|
|
a531a5cb9a | |
|
|
dca95745c4 | |
|
|
2e826a65c7 | |
|
|
0b94b35992 | |
|
|
311d2b06bc | |
|
|
156ac39bb3 | |
|
|
5adb9bfb59 | |
|
|
c4eb4e8ceb | |
|
|
79ea2acba8 | |
|
|
f77c9fcc5e | |
|
|
28e10374a9 | |
|
|
0ac21f0697 | |
|
|
d7af5d917c | |
|
|
88037747a3 | |
|
|
f7baac7cd0 | |
|
|
3750059072 | |
|
|
57399a2cf0 | |
|
|
39ea8a8aa8 | |
|
|
5968f1a3f8 | |
|
|
2881738b7d | |
|
|
a0c1bef09f | |
|
|
d57a58c9a1 | |
|
|
acd7000224 | |
|
|
97d20a3622 | |
|
|
7ece161538 | |
|
|
52e9290d12 | |
|
|
8ae95c9542 | |
|
|
c7e7c14346 | |
|
|
ba51bab395 | |
|
|
6ce7b11f98 | |
|
|
b6b5415068 | |
|
|
d60e8240c3 | |
|
|
3963d8fd93 | |
|
|
375e2b9db6 | |
|
|
84f3215a4f | |
|
|
f33e5b37d4 | |
|
|
84b0afb300 | |
|
|
97124e91f4 | |
|
|
93d2eb674b | |
|
|
bfb95aff7e | |
|
|
bbfcb4124f | |
|
|
1ea098e1e1 | |
|
|
7884aec202 | |
|
|
22899a4b39 | |
|
|
44b9139b16 | |
|
|
69311abe3a | |
|
|
73d86a9d6e | |
|
|
79859aa20c | |
|
|
0278a0145f | |
|
|
5d8048bb1f | |
|
|
6429ac4e57 | |
|
|
e4aea68c97 | |
|
|
0882c83bb9 | |
|
|
d90540beea | |
|
|
a8be0eaadd | |
|
|
77757c3d23 | |
|
|
89017cedbc | |
|
|
ee21cea888 | |
|
|
47a4876a77 | |
|
|
0f36a0517d | |
|
|
cb6f7729fd | |
|
|
5e82a5eef6 | |
|
|
d1ca37db71 | |
|
|
00bad2e89b |
|
|
@ -0,0 +1,47 @@
|
|||
#
|
||||
# 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: Build and Test For Dubbo 2.6
|
||||
|
||||
on: [push, pull_request, workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
unit-test:
|
||||
name: "Unit Test On JDK: ${{ matrix.jdk }}"
|
||||
runs-on: ubuntu-18.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
jdk: [ 8, 11 ]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: "Set up JDK ${{ matrix.jdk }}"
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: ${{ matrix.jdk }}
|
||||
- uses: actions/cache@v2
|
||||
name: "Cache local Maven repository"
|
||||
with:
|
||||
path: ~/.m2/repository
|
||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-maven-
|
||||
- name: "Test with Maven"
|
||||
timeout-minutes: 30
|
||||
run: ./mvnw --batch-mode -U -e --no-transfer-progress clean test install -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -Dcheckstyle.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true
|
||||
- name: "Upload coverage to Codecov"
|
||||
uses: codecov/codecov-action@v1
|
||||
|
|
@ -1 +1 @@
|
|||
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip
|
||||
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.6.1/apache-maven-3.6.1-bin.zip
|
||||
|
|
|
|||
13
.travis.yml
13
.travis.yml
|
|
@ -1,13 +0,0 @@
|
|||
language: java
|
||||
sudo: false # faster builds
|
||||
|
||||
jdk:
|
||||
- oraclejdk9
|
||||
- oraclejdk8
|
||||
- openjdk7
|
||||
|
||||
script:
|
||||
- travis_wait 30 ./mvnw clean package
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
135
CHANGES.md
135
CHANGES.md
|
|
@ -1,15 +1,144 @@
|
|||
# Release Notes
|
||||
## 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
|
||||
* supoort 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 consuer 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/incubator-dubbo/issues/2235)
|
||||
- Introduce a new Spring ApplicationEvent for ServiceBean exporting [#2251](https://github.com/apache/incubator-dubbo/issues/2251)
|
||||
- [Enhancement] the algorithm of load issue on Windows. [#1641](https://github.com/apache/incubator-dubbo/issues/1641)
|
||||
- add javadoc to dubbo-all module good first issue. [#2600](https://github.com/apache/incubator-dubbo/issues/2600)
|
||||
- [Enhancement] Reactor the generation rule for @Service Bean name type/enhancement [#2235](https://github.com/apache/incubator-dubbo/issues/2235)
|
||||
- Optimize LeastActiveLoadBalance and add weight test case. [#2540](https://github.com/apache/incubator-dubbo/issues/2540)
|
||||
- Smooth Round Robin selection. [#2578](https://github.com/apache/incubator-dubbo/issues/2578) [#2647](https://github.com/apache/incubator-dubbo/pull/2647)
|
||||
- [Enhancement] Resolve the placeholders for sub-properties. [#2297](https://github.com/apache/incubator-dubbo/issues/2297)
|
||||
- Add ability to turn off SPI auto injection, special support for generic Object type injection. [#2681](https://github.com/apache/incubator-dubbo/pull/2681)
|
||||
|
||||
|
||||
Bugfixes:
|
||||
|
||||
- @Service(register=false) is not work. [#2063](https://github.com/apache/incubator-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/incubator-dubbo/issues/1903)
|
||||
- Consumer throws RpcException after RegistryDirectory notify in high QPS. [#2016](https://github.com/apache/incubator-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/incubator-dubbo/issues/2194)
|
||||
- `org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor#generateReferenceBeanCacheKey` has a bug. [#2522](https://github.com/apache/incubator-dubbo/issues/2522)
|
||||
- 2.6.x Spring Event & Bugfix. [#2256](https://github.com/apache/incubator-dubbo/issues/2256)
|
||||
- Fix incorrect descriptions for dubbo-serialization module. [#2665](https://github.com/apache/incubator-dubbo/issues/2665)
|
||||
- A empty directory dubbo-config/dubbo-config-spring/src/test/resources/work after package source tgz. [#2560](https://github.com/apache/incubator-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/incubator-dubbo/pull/2622)
|
||||
- Bean name of @service annotated class does not resolve placeholder. [#1755](https://github.com/apache/incubator-dubbo/issues/1755)
|
||||
|
||||
|
||||
|
||||
Issues and Pull Requests, check [milestone-2.6.5](https://github.com/apache/incubator-dubbo/milestone/21).
|
||||
|
||||
## 2.6.4
|
||||
|
||||
Enhancements / Features
|
||||
|
||||
- Support access Redis with password, [#2146](https://github.com/apache/incubator-dubbo/pull/2146)
|
||||
- Support char array for GenericService, [#2137](https://github.com/apache/incubator-dubbo/pull/2137)
|
||||
- Direct return when the server goes down abnormally, [#2451](https://github.com/apache/incubator-dubbo/pull/2451)
|
||||
- Add log for trouble-shooting when qos start failed, [#2455](https://github.com/apache/incubator-dubbo/pull/2455)
|
||||
- PojoUtil support subclasses of java.util.Date, [#2502](https://github.com/apache/incubator-dubbo/pull/2502)
|
||||
- Add ip and application name for MonitorService, [#2166](https://github.com/apache/incubator-dubbo/pull/2166)
|
||||
- New ASCII logo, [#2402](https://github.com/apache/incubator-dubbo/pull/2402)
|
||||
|
||||
Bugfixes
|
||||
|
||||
- Change consumer retries default value from 0 to 2, [#2303](https://github.com/apache/incubator-dubbo/pull/2303)
|
||||
- Fix the problem that attachment is lost when retry, [#2024](https://github.com/apache/incubator-dubbo/pull/2024)
|
||||
- Fix NPE when telnet get a null parameter, [#2453](https://github.com/apache/incubator-dubbo/pull/2453)
|
||||
|
||||
UT stability
|
||||
|
||||
- Improve the stability by changing different port, setting timeout to 3000ms, [#2501](https://github.com/apache/incubator-dubbo/pull/2501)
|
||||
|
||||
Issues and Pull Requests, check [milestone-2.6.4](https://github.com/apache/incubator-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
|
||||
|
||||
- Hessian deserialization optimization, #1705
|
||||
- Support Locale type, #1761
|
||||
|
||||
Compatibilities
|
||||
This release is compatible with other versions since 2.5.3, and you can upgrade smoothly.
|
||||
- The RPC protocol version has been upgraded from 2.0.1 to 2.0.2, to support attachments delivery in #889,
|
||||
generally, the protocol version is used internally, so it should have no side effects on users.
|
||||
|
||||
Issues and Pull Requests, check [milestone-2.6.3](https://github.com/apache/incubator-dubbo/milestone/17).
|
||||
|
||||
|
||||
## 2.6.2
|
||||
|
||||
1. Hessian-lite serialization: revert locale serialization for compatibility, #1413
|
||||
2. Asset transfer to ASF, includeing pom, license, DISCLAIMER and so on, #1491
|
||||
2. Asset transfer to ASF, including pom, license, DISCLAIMER and so on, #1491
|
||||
3. Introduce of new dispatcher policy: EagerThreadpool, #1568
|
||||
4. Separate monitor data with group and version, #1407
|
||||
5. Spring Boot Enhancenment, #1611
|
||||
6. Gaceful shutdown enhancement
|
||||
6. Graceful shutdown enhancement
|
||||
- Remove exporter destroy logic in AnnotationBean.
|
||||
- Waiting for registry notification on consumer side by checking channel state.
|
||||
7. Simplify consumer/provider side check in RpcContext, #1444.
|
||||
|
||||
Issues and Pull Requests, check [milestone-2.6.2](https://github.com/apache/incubator-dubbo/milestone/15).
|
||||
Issues and Pull Requests, check [milestone-2.6.2](https://github.com/apache/incubator-dubbo/milestone/15).
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ This Code of Conduct applies both within project spaces and in public spaces whe
|
|||
|
||||
## 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.
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at private@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.
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
Apache Dubbo is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessarily a reflection of the completeness or stability of the code, it does indicate that the project has yet to be fully endorsed by the ASF.
|
||||
48
LICENSE
48
LICENSE
|
|
@ -208,54 +208,6 @@ 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 hessian-lite submodule:
|
||||
|
||||
The Apache Software License, Version 1.1
|
||||
|
||||
Copyright (c) 2001-2004 Caucho Technology, 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:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. 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.
|
||||
|
||||
3. The end-user documentation included with the redistribution, if
|
||||
any, must include the following acknowlegement:
|
||||
"This product includes software developed by the
|
||||
Caucho Technology (http://www.caucho.com/)."
|
||||
Alternately, this acknowlegement may appear in the software itself,
|
||||
if and wherever such third-party acknowlegements normally appear.
|
||||
|
||||
4. The names "Hessian", "Resin", and "Caucho" must not be used to
|
||||
endorse or promote products derived from this software without prior
|
||||
written permission. For written permission, please contact
|
||||
info@caucho.com.
|
||||
|
||||
5. Products derived from this software may not be called "Resin"
|
||||
nor may "Resin" appear in their names without prior written
|
||||
permission of Caucho Technology.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 CAUCHO TECHNOLOGY OR ITS 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.
|
||||
|
||||
|
||||
For the com.alibaba.dubbo.common.concurrent package:
|
||||
|
||||
This product bundles and repackages the following code in Google Guava 16.0.1, which is available under a
|
||||
|
|
|
|||
15
NOTICE
15
NOTICE
|
|
@ -1,5 +1,14 @@
|
|||
Apache Dubbo (incubating)
|
||||
Copyright 2018 The Apache Software Foundation
|
||||
Apache Dubbo
|
||||
Copyright 2018-2021 The Apache Software Foundation
|
||||
|
||||
This product includes software developed at
|
||||
The Apache Software Foundation (http://www.apache.org/).
|
||||
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
|
||||
|
|
|
|||
16
README.md
16
README.md
|
|
@ -1,12 +1,12 @@
|
|||
# Apache Dubbo (incubating) Project
|
||||
# Apache Dubbo Project
|
||||
|
||||
[](https://travis-ci.org/apache/incubator-dubbo)
|
||||
[](https://codecov.io/gh/apache/incubator-dubbo)
|
||||
[](https://travis-ci.org/apache/dubbo)
|
||||
[](https://codecov.io/gh/apache/dubbo)
|
||||
[](https://gitter.im/alibaba/dubbo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||

|
||||

|
||||
|
||||
Apache Dubbo (incubating) is a high-performance, java based RPC framework open-sourced by Alibaba. Please visit [dubbo official site ](http://dubbo.incubator.apache.org) for quick start and documentations, as well as [Wiki](https://github.com/apache/incubator-dubbo/wiki) for news, FAQ, and release notes.
|
||||
Apache Dubbo is a high-performance, java based RPC framework open-sourced by Alibaba. Please visit [dubbo official site ](http://dubbo.incubator.apache.org) for quick start and documentations, as well as [Wiki](https://github.com/apache/incubator-dubbo/wiki) for news, FAQ, and release notes.
|
||||
|
||||
We are now collecting dubbo user info in order to help us to improve dubbo better, pls. kindly help us by providing yours on [issue#1012: Wanted: who's using dubbo](https://github.com/apache/incubator-dubbo/issues/1012), thanks :)
|
||||
|
||||
|
|
@ -15,10 +15,10 @@ We are now collecting dubbo user info in order to help us to improve dubbo bette
|
|||
* [Side projects](https://github.com/apache/incubator-dubbo)
|
||||
* [Dubbo Spring Boot](https://github.com/apache/incubator-dubbo-spring-boot-project) - Spring Boot Project for Dubbo.
|
||||
* [Dubbo ops](https://github.com/apache/incubator-dubbo-ops) - The reference implementation for dubbo ops(dubbo-admin,dubbo-monitor-simple,dubbo-registry-simple,etc.).
|
||||
* [Dubbo website](https://github.com/apache/incubator-dubbo-website) - Apache Dubbo (incubating) documents
|
||||
* [Dubbo rpc-jsonrpc](https://github.com/apache/incubator-dubbo-rpc-jsonrpc) - The Json rpc module of Apache Dubbo (incubating) project
|
||||
* [Dubbo feature-test](https://github.com/apache/incubator-dubbo-feature-test) - Apache Dubbo (incubating) feature test
|
||||
* [Dubbo docs](https://github.com/apache/incubator-dubbo-docs) - Apache Dubbo (incubating) documentation
|
||||
* [Dubbo website](https://github.com/apache/incubator-dubbo-website) - Apache Dubbo documents
|
||||
* [Dubbo rpc-jsonrpc](https://github.com/apache/incubator-dubbo-rpc-jsonrpc) - The Json rpc module of Apache Dubbo project
|
||||
* [Dubbo feature-test](https://github.com/apache/incubator-dubbo-feature-test) - Apache Dubbo feature test
|
||||
* [Dubbo docs](https://github.com/apache/incubator-dubbo-docs) - Apache Dubbo documentation
|
||||
* [Developer Mailing list](https://github.com/apache/incubator-dubbo/issues/1393) - Any questions or suggestions? [Subscribe](https://github.com/apache/incubator-dubbo/issues/1393) to (dev@dubbo.incubator.apache.org) to discuss with us.
|
||||
* [Gitter channel](https://gitter.im/alibaba/dubbo) - Online chat room with Dubbo developers.
|
||||
* [Dubbo user manual(English)](http://dubbo.apache.org/books/dubbo-user-book-en/) or [Dubbo用户手册(中文)](http://dubbo.apache.org/books/dubbo-user-book/) - Describe how to use Dubbo and all features of Dubbo concretely.
|
||||
|
|
|
|||
96
all/pom.xml
96
all/pom.xml
|
|
@ -19,16 +19,17 @@
|
|||
<parent>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-parent</artifactId>
|
||||
<version>2.6.3-SNAPSHOT</version>
|
||||
<version>2.6.13-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>dubbo</artifactId>
|
||||
<version>2.6.3-SNAPSHOT</version>
|
||||
<version>2.6.13-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
<name>dubbo-all</name>
|
||||
<description>The all in one project of dubbo</description>
|
||||
<properties>
|
||||
<skip_maven_deploy>false</skip_maven_deploy>
|
||||
<hessian_lite_version>3.2.4</hessian_lite_version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
|
@ -318,17 +319,9 @@
|
|||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-bootstrap</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>hessian-lite</artifactId>
|
||||
<version>3.2.3</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
|
@ -424,7 +417,6 @@
|
|||
<include>com.alibaba:dubbo-serialization-fst</include>
|
||||
<include>com.alibaba:dubbo-serialization-kryo</include>
|
||||
<include>com.alibaba:dubbo-serialization-jdk</include>
|
||||
<include>com.alibaba:dubbo-bootstrap</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
<transformers>
|
||||
|
|
@ -543,39 +535,61 @@
|
|||
</resource>
|
||||
</transformer>
|
||||
</transformers>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>com.alibaba:dubbo</artifact>
|
||||
<excludes>
|
||||
<!-- These two line is optional, it can remove some warn log -->
|
||||
<exclude>com/**</exclude>
|
||||
<exclude>org/**</exclude>
|
||||
<!-- This one is required -->
|
||||
<exclude>META-INF/dubbo/**</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>${maven_javadoc_version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadoc</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<doclint>none</doclint>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<includeDependencySources>true</includeDependencySources>
|
||||
<dependencySourceIncludes>
|
||||
<dependencySourceInclude>com.alibaba:dubbo-*</dependencySourceInclude>
|
||||
<dependencySourceExclude>com.alibaba:hessian-*</dependencySourceExclude>
|
||||
</dependencySourceIncludes>
|
||||
<show>public</show>
|
||||
<charset>UTF-8</charset>
|
||||
<encoding>UTF-8</encoding>
|
||||
<docencoding>UTF-8</docencoding>
|
||||
<links>
|
||||
<link>http://docs.oracle.com/javase/7/docs/api</link>
|
||||
</links>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>release</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>${maven_javadoc_version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadoc</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<doclint>none</doclint>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<includeDependencySources>true</includeDependencySources>
|
||||
<dependencySourceIncludes>
|
||||
<dependencySourceInclude>com.alibaba:dubbo-*</dependencySourceInclude>
|
||||
<dependencySourceExclude>com.alibaba:hessian-*</dependencySourceExclude>
|
||||
</dependencySourceIncludes>
|
||||
<show>public</show>
|
||||
<charset>UTF-8</charset>
|
||||
<encoding>UTF-8</encoding>
|
||||
<docencoding>UTF-8</docencoding>
|
||||
<links>
|
||||
<link>http://docs.oracle.com/javase/7/docs/api</link>
|
||||
</links>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
|
|
|
|||
30
bom/pom.xml
30
bom/pom.xml
|
|
@ -1,7 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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">
|
||||
|
||||
<!--
|
||||
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>
|
||||
<properties>
|
||||
<hessian_lite_version>3.2.4</hessian_lite_version>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
<groupId>org.sonatype.oss</groupId>
|
||||
|
|
@ -11,7 +32,7 @@
|
|||
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-bom</artifactId>
|
||||
<version>2.6.3-SNAPSHOT</version>
|
||||
<version>2.6.13-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>dubbo-bom</name>
|
||||
|
|
@ -278,11 +299,6 @@
|
|||
<artifactId>dubbo-serialization-kryo</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>hessian-lite</artifactId>
|
||||
<version>3.2.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,19 @@
|
|||
<?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>
|
||||
|
||||
|
|
@ -10,7 +25,7 @@
|
|||
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-dependencies-bom</artifactId>
|
||||
<version>2.6.3-SNAPSHOT</version>
|
||||
<version>2.6.13-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>dubbo-dependencies-bom</name>
|
||||
|
|
@ -29,8 +44,8 @@
|
|||
<url>https://github.com/apache/incubator-dubbo</url>
|
||||
<connection>scm:git:https://github.com/apache/incubator-dubbo.git</connection>
|
||||
<developerConnection>scm:git:https://github.com/apache/incubator-dubbo.git</developerConnection>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
<mailingLists>
|
||||
<mailingList>
|
||||
<name>Development List</name>
|
||||
|
|
@ -75,11 +90,11 @@
|
|||
<spring_version>4.3.16.RELEASE</spring_version>
|
||||
<javassist_version>3.20.0-GA</javassist_version>
|
||||
<netty_version>3.2.5.Final</netty_version>
|
||||
<netty4_version>4.0.35.Final</netty4_version>
|
||||
<netty4_version>4.1.25.Final</netty4_version>
|
||||
<mina_version>1.1.7</mina_version>
|
||||
<grizzly_version>2.1.4</grizzly_version>
|
||||
<httpclient_version>4.5.3</httpclient_version>
|
||||
<fastjson_version>1.2.46</fastjson_version>
|
||||
<fastjson_version>1.2.70</fastjson_version>
|
||||
<zookeeper_version>3.4.9</zookeeper_version>
|
||||
<zkclient_version>0.2</zkclient_version>
|
||||
<curator_version>2.12.0</curator_version>
|
||||
|
|
@ -87,7 +102,7 @@
|
|||
<xmemcached_version>1.3.6</xmemcached_version>
|
||||
<cxf_version>3.1.15</cxf_version>
|
||||
<thrift_version>0.8.0</thrift_version>
|
||||
<hessian_version>4.0.38</hessian_version>
|
||||
<hessian_version>4.0.51</hessian_version>
|
||||
<servlet_version>3.1.0</servlet_version>
|
||||
<jetty_version>6.1.26</jetty_version>
|
||||
<validation_version>1.1.0.Final</validation_version>
|
||||
|
|
@ -101,6 +116,7 @@
|
|||
<rs_api_version>2.0</rs_api_version>
|
||||
<resteasy_version>3.0.19.Final</resteasy_version>
|
||||
<tomcat_embed_version>8.5.31</tomcat_embed_version>
|
||||
|
||||
<!-- Log libs -->
|
||||
<slf4j_version>1.7.25</slf4j_version>
|
||||
<jcl_version>1.2</jcl_version>
|
||||
|
|
@ -111,6 +127,9 @@
|
|||
|
||||
<jaxb_version>2.2.7</jaxb_version>
|
||||
<activation_version>1.2.0</activation_version>
|
||||
<hessian_lite_version>3.2.12</hessian_lite_version>
|
||||
<alibaba_spring_context_support_version>1.0.2</alibaba_spring_context_support_version>
|
||||
<yaml_version>1.17</yaml_version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
|
|
@ -299,6 +318,7 @@
|
|||
<artifactId>tomcat-embed-logging-juli</artifactId>
|
||||
<version>${tomcat_embed_version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Log libs -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
|
|
@ -352,6 +372,20 @@
|
|||
<artifactId>javax.activation</artifactId>
|
||||
<version>${activation_version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>hessian-lite</artifactId>
|
||||
<version>${hessian_lite_version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Alibaba extensions -->
|
||||
|
||||
<!-- YAML -->
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>${yaml_version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Test lib -->
|
||||
<dependency>
|
||||
|
|
@ -366,6 +400,7 @@
|
|||
<version>${embedded_redis_version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
|
@ -391,4 +426,4 @@
|
|||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
<parent>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-parent</artifactId>
|
||||
<version>2.6.3-SNAPSHOT</version>
|
||||
<version>2.6.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>dubbo-distribution</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
|
@ -243,7 +243,6 @@
|
|||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>hessian-lite</artifactId>
|
||||
<version>3.2.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
|
@ -251,7 +250,7 @@
|
|||
<profile>
|
||||
<id>release</id>
|
||||
<build>
|
||||
<finalName>dubbo-incubating-${project.version}</finalName>
|
||||
<finalName>apache-dubbo-${project.version}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
|
|
|
|||
|
|
@ -46,6 +46,10 @@
|
|||
<exclude>**/*.log</exclude>
|
||||
<exclude>release.properties</exclude>
|
||||
<exclude>**/*.xml.*</exclude>
|
||||
<exclude>**/.mvn/**</exclude>
|
||||
<exclude>**/*.jar</exclude>
|
||||
<exclude>**/mvnw*</exclude>
|
||||
<exclude>**/invalid_data.ser</exclude>
|
||||
</excludes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<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">
|
||||
<parent>
|
||||
<artifactId>dubbo-parent</artifactId>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<version>2.6.3-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>dubbo-bootstrap</artifactId>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-config-api</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-common</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-registry-api</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.bootstrap;
|
||||
|
||||
import com.alibaba.dubbo.config.DubboShutdownHook;
|
||||
import com.alibaba.dubbo.config.ServiceConfig;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A bootstrap class to easily start and stop Dubbo via programmatic API.
|
||||
* The bootstrap class will be responsible to cleanup the resources during stop.
|
||||
*/
|
||||
public class DubboBootstrap {
|
||||
|
||||
/**
|
||||
* The list of ServiceConfig
|
||||
*/
|
||||
private List<ServiceConfig> serviceConfigList;
|
||||
|
||||
/**
|
||||
* Whether register the shutdown hook during start?
|
||||
*/
|
||||
private final boolean registerShutdownHookOnStart;
|
||||
|
||||
/**
|
||||
* The shutdown hook used when Dubbo is running under embedded environment
|
||||
*/
|
||||
private DubboShutdownHook shutdownHook;
|
||||
|
||||
public DubboBootstrap() {
|
||||
this(true, DubboShutdownHook.getDubboShutdownHook());
|
||||
}
|
||||
|
||||
public DubboBootstrap(boolean registerShutdownHookOnStart) {
|
||||
this(registerShutdownHookOnStart, DubboShutdownHook.getDubboShutdownHook());
|
||||
}
|
||||
|
||||
public DubboBootstrap(boolean registerShutdownHookOnStart, DubboShutdownHook shutdownHook) {
|
||||
this.serviceConfigList = new ArrayList<ServiceConfig>();
|
||||
this.shutdownHook = shutdownHook;
|
||||
this.registerShutdownHookOnStart = registerShutdownHookOnStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register service config to bootstrap, which will be called during {@link DubboBootstrap#stop()}
|
||||
* @param serviceConfig the service
|
||||
* @return the bootstrap instance
|
||||
*/
|
||||
public DubboBootstrap registerServiceConfig(ServiceConfig serviceConfig) {
|
||||
serviceConfigList.add(serviceConfig);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if (registerShutdownHookOnStart) {
|
||||
registerShutdownHook();
|
||||
} else {
|
||||
// DubboShutdown hook has been registered in AbstractConfig,
|
||||
// we need to remove it explicitly
|
||||
removeShutdownHook();
|
||||
}
|
||||
for (ServiceConfig serviceConfig: serviceConfigList) {
|
||||
serviceConfig.export();
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
for (ServiceConfig serviceConfig: serviceConfigList) {
|
||||
serviceConfig.unexport();
|
||||
}
|
||||
shutdownHook.destroyAll();
|
||||
if (registerShutdownHookOnStart) {
|
||||
removeShutdownHook();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the shutdown hook
|
||||
*/
|
||||
public void registerShutdownHook() {
|
||||
Runtime.getRuntime().addShutdownHook(shutdownHook);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove this shutdown hook
|
||||
*/
|
||||
public void removeShutdownHook() {
|
||||
try {
|
||||
Runtime.getRuntime().removeShutdownHook(shutdownHook);
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
// ignore - VM is already shutting down
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
<parent>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-parent</artifactId>
|
||||
<version>2.6.3-SNAPSHOT</version>
|
||||
<version>2.6.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>dubbo-cluster</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import java.util.List;
|
|||
* @see com.alibaba.dubbo.rpc.cluster.Cluster#join(Directory)
|
||||
* @see com.alibaba.dubbo.rpc.cluster.Directory#list(Invocation)
|
||||
*/
|
||||
public interface Router extends Comparable<Router> {
|
||||
public interface Router extends Comparable<Router>{
|
||||
|
||||
/**
|
||||
* get the router url.
|
||||
|
|
@ -51,4 +51,11 @@ public interface Router extends Comparable<Router> {
|
|||
*/
|
||||
<T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException;
|
||||
|
||||
/**
|
||||
* Router's priority, used to sort routers.
|
||||
*
|
||||
* @return router's priority
|
||||
*/
|
||||
int getPriority();
|
||||
|
||||
}
|
||||
|
|
@ -19,15 +19,14 @@ package com.alibaba.dubbo.rpc.cluster;
|
|||
import com.alibaba.dubbo.common.URL;
|
||||
import com.alibaba.dubbo.common.extension.Adaptive;
|
||||
import com.alibaba.dubbo.common.extension.SPI;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
|
||||
/**
|
||||
* RouterFactory. (SPI, Singleton, ThreadSafe)
|
||||
* <p>
|
||||
* <a href="http://en.wikipedia.org/wiki/Routing">Routing</a>
|
||||
*
|
||||
* @see com.alibaba.dubbo.rpc.cluster.Cluster#join(Directory)
|
||||
* @see com.alibaba.dubbo.rpc.cluster.Directory#list(Invocation)
|
||||
* @see Cluster#join(Directory)
|
||||
* @see Directory#list(com.alibaba.dubbo.rpc.Invocation)
|
||||
*/
|
||||
@SPI
|
||||
public interface RouterFactory {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import com.alibaba.dubbo.rpc.cluster.Directory;
|
|||
import com.alibaba.dubbo.rpc.cluster.Router;
|
||||
import com.alibaba.dubbo.rpc.cluster.RouterFactory;
|
||||
import com.alibaba.dubbo.rpc.cluster.router.MockInvokersSelector;
|
||||
import com.alibaba.dubbo.rpc.cluster.router.tag.TagRouter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
|
@ -107,6 +108,7 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
|
|||
}
|
||||
// append mock invoker selector
|
||||
routers.add(new MockInvokersSelector());
|
||||
routers.add(new TagRouter());
|
||||
Collections.sort(routers);
|
||||
this.routers = routers;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
package com.alibaba.dubbo.rpc.cluster.loadbalance;
|
||||
|
||||
import com.alibaba.dubbo.common.Constants;
|
||||
import com.alibaba.dubbo.common.URL;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
|
|
@ -41,26 +40,26 @@ public class LeastActiveLoadBalance extends AbstractLoadBalance {
|
|||
int leastActive = -1; // The least active value of all invokers
|
||||
int leastCount = 0; // The number of invokers having the same least active value (leastActive)
|
||||
int[] leastIndexs = new int[length]; // The index of invokers having the same least active value (leastActive)
|
||||
int totalWeight = 0; // The sum of weights
|
||||
int totalWeight = 0; // The sum of with warmup weights
|
||||
int firstWeight = 0; // Initial value, used for comparision
|
||||
boolean sameWeight = true; // Every invoker has the same weight value?
|
||||
for (int i = 0; i < length; i++) {
|
||||
Invoker<T> invoker = invokers.get(i);
|
||||
int active = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName()).getActive(); // Active number
|
||||
int weight = invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT); // Weight
|
||||
int afterWarmup = getWeight(invoker, invocation); // Weight
|
||||
if (leastActive == -1 || active < leastActive) { // Restart, when find a invoker having smaller least active value.
|
||||
leastActive = active; // Record the current least active value
|
||||
leastCount = 1; // Reset leastCount, count again based on current leastCount
|
||||
leastIndexs[0] = i; // Reset
|
||||
totalWeight = weight; // Reset
|
||||
firstWeight = weight; // Record the weight the first invoker
|
||||
totalWeight = afterWarmup; // Reset
|
||||
firstWeight = afterWarmup; // Record the weight the first invoker
|
||||
sameWeight = true; // Reset, every invoker has the same weight value?
|
||||
} else if (active == leastActive) { // If current invoker's active value equals with leaseActive, then accumulating.
|
||||
leastIndexs[leastCount++] = i; // Record index number of this invoker
|
||||
totalWeight += weight; // Add this invoker's weight to totalWeight.
|
||||
totalWeight += afterWarmup; // Add this invoker's weight to totalWeight.
|
||||
// If every invoker has the same weight?
|
||||
if (sameWeight && i > 0
|
||||
&& weight != firstWeight) {
|
||||
&& afterWarmup != firstWeight) {
|
||||
sameWeight = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -72,7 +71,7 @@ public class LeastActiveLoadBalance extends AbstractLoadBalance {
|
|||
}
|
||||
if (!sameWeight && totalWeight > 0) {
|
||||
// If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeight.
|
||||
int offsetWeight = random.nextInt(totalWeight);
|
||||
int offsetWeight = random.nextInt(totalWeight) + 1;
|
||||
// Return a invoker based on the random value.
|
||||
for (int i = 0; i < leastCount; i++) {
|
||||
int leastIndex = leastIndexs[i];
|
||||
|
|
|
|||
|
|
@ -17,87 +17,139 @@
|
|||
package com.alibaba.dubbo.rpc.cluster.loadbalance;
|
||||
|
||||
import com.alibaba.dubbo.common.URL;
|
||||
import com.alibaba.dubbo.common.utils.AtomicPositiveInteger;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* Round robin load balance.
|
||||
*
|
||||
*
|
||||
* Smoothly round robin's implementation @since 2.6.5
|
||||
*/
|
||||
public class RoundRobinLoadBalance extends AbstractLoadBalance {
|
||||
|
||||
public static final String NAME = "roundrobin";
|
||||
|
||||
private static int RECYCLE_PERIOD = 60000;
|
||||
|
||||
protected static class WeightedRoundRobin {
|
||||
private int weight;
|
||||
private AtomicLong current = new AtomicLong(0);
|
||||
private long lastUpdate;
|
||||
public int getWeight() {
|
||||
return weight;
|
||||
}
|
||||
public void setWeight(int weight) {
|
||||
this.weight = weight;
|
||||
current.set(0);
|
||||
}
|
||||
public long increaseCurrent() {
|
||||
return current.addAndGet(weight);
|
||||
}
|
||||
public void sel(int total) {
|
||||
current.addAndGet(-1 * total);
|
||||
}
|
||||
public long getLastUpdate() {
|
||||
return lastUpdate;
|
||||
}
|
||||
public void setLastUpdate(long lastUpdate) {
|
||||
this.lastUpdate = lastUpdate;
|
||||
}
|
||||
}
|
||||
|
||||
private final ConcurrentMap<String, AtomicPositiveInteger> sequences = new ConcurrentHashMap<String, AtomicPositiveInteger>();
|
||||
|
||||
private ConcurrentMap<String, ConcurrentMap<String, WeightedRoundRobin>> methodWeightMap = new ConcurrentHashMap<String, ConcurrentMap<String, WeightedRoundRobin>>();
|
||||
private AtomicBoolean updateLock = new AtomicBoolean();
|
||||
|
||||
/**
|
||||
* get invoker addr list cached for specified invocation
|
||||
* <p>
|
||||
* <b>for unit test only</b>
|
||||
*
|
||||
* @param invokers
|
||||
* @param invocation
|
||||
* @return
|
||||
*/
|
||||
protected <T> Collection<String> getInvokerAddrList(List<Invoker<T>> invokers, Invocation invocation) {
|
||||
String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();
|
||||
Map<String, WeightedRoundRobin> map = methodWeightMap.get(key);
|
||||
if (map != null) {
|
||||
return map.keySet();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
|
||||
String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();
|
||||
int length = invokers.size(); // Number of invokers
|
||||
int maxWeight = 0; // The maximum weight
|
||||
int minWeight = Integer.MAX_VALUE; // The minimum weight
|
||||
final LinkedHashMap<Invoker<T>, IntegerWrapper> invokerToWeightMap = new LinkedHashMap<Invoker<T>, IntegerWrapper>();
|
||||
int weightSum = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
int weight = getWeight(invokers.get(i), invocation);
|
||||
maxWeight = Math.max(maxWeight, weight); // Choose the maximum weight
|
||||
minWeight = Math.min(minWeight, weight); // Choose the minimum weight
|
||||
if (weight > 0) {
|
||||
invokerToWeightMap.put(invokers.get(i), new IntegerWrapper(weight));
|
||||
weightSum += weight;
|
||||
ConcurrentMap<String, WeightedRoundRobin> map = methodWeightMap.get(key);
|
||||
if (map == null) {
|
||||
methodWeightMap.putIfAbsent(key, new ConcurrentHashMap<String, WeightedRoundRobin>());
|
||||
map = methodWeightMap.get(key);
|
||||
}
|
||||
int totalWeight = 0;
|
||||
long maxCurrent = Long.MIN_VALUE;
|
||||
long now = System.currentTimeMillis();
|
||||
Invoker<T> selectedInvoker = null;
|
||||
WeightedRoundRobin selectedWRR = null;
|
||||
for (Invoker<T> invoker : invokers) {
|
||||
String identifyString = invoker.getUrl().toIdentityString();
|
||||
WeightedRoundRobin weightedRoundRobin = map.get(identifyString);
|
||||
int weight = getWeight(invoker, invocation);
|
||||
if (weight < 0) {
|
||||
weight = 0;
|
||||
}
|
||||
if (weightedRoundRobin == null) {
|
||||
weightedRoundRobin = new WeightedRoundRobin();
|
||||
weightedRoundRobin.setWeight(weight);
|
||||
map.putIfAbsent(identifyString, weightedRoundRobin);
|
||||
weightedRoundRobin = map.get(identifyString);
|
||||
}
|
||||
if (weight != weightedRoundRobin.getWeight()) {
|
||||
//weight changed
|
||||
weightedRoundRobin.setWeight(weight);
|
||||
}
|
||||
long cur = weightedRoundRobin.increaseCurrent();
|
||||
weightedRoundRobin.setLastUpdate(now);
|
||||
if (cur > maxCurrent) {
|
||||
maxCurrent = cur;
|
||||
selectedInvoker = invoker;
|
||||
selectedWRR = weightedRoundRobin;
|
||||
}
|
||||
totalWeight += weight;
|
||||
}
|
||||
AtomicPositiveInteger sequence = sequences.get(key);
|
||||
if (sequence == null) {
|
||||
sequences.putIfAbsent(key, new AtomicPositiveInteger());
|
||||
sequence = sequences.get(key);
|
||||
}
|
||||
int currentSequence = sequence.getAndIncrement();
|
||||
if (maxWeight > 0 && minWeight < maxWeight) {
|
||||
int mod = currentSequence % weightSum;
|
||||
for (int i = 0; i < maxWeight; i++) {
|
||||
for (Map.Entry<Invoker<T>, IntegerWrapper> each : invokerToWeightMap.entrySet()) {
|
||||
final Invoker<T> k = each.getKey();
|
||||
final IntegerWrapper v = each.getValue();
|
||||
if (mod == 0 && v.getValue() > 0) {
|
||||
return k;
|
||||
}
|
||||
if (v.getValue() > 0) {
|
||||
v.decrement();
|
||||
mod--;
|
||||
if (!updateLock.get() && invokers.size() != map.size()) {
|
||||
if (updateLock.compareAndSet(false, true)) {
|
||||
try {
|
||||
// copy -> modify -> update reference
|
||||
ConcurrentMap<String, WeightedRoundRobin> newMap = new ConcurrentHashMap<String, WeightedRoundRobin>();
|
||||
newMap.putAll(map);
|
||||
Iterator<Entry<String, WeightedRoundRobin>> it = newMap.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Entry<String, WeightedRoundRobin> item = it.next();
|
||||
if (now - item.getValue().getLastUpdate() > RECYCLE_PERIOD) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
methodWeightMap.put(key, newMap);
|
||||
} finally {
|
||||
updateLock.set(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Round robin
|
||||
return invokers.get(currentSequence % length);
|
||||
}
|
||||
|
||||
private static final class IntegerWrapper {
|
||||
private int value;
|
||||
|
||||
public IntegerWrapper(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public void decrement() {
|
||||
this.value--;
|
||||
if (selectedInvoker != null) {
|
||||
selectedWRR.sel(totalWeight);
|
||||
return selectedInvoker;
|
||||
}
|
||||
// should not happen here
|
||||
return invokers.get(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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 com.alibaba.dubbo.rpc.cluster.router;
|
||||
|
||||
import com.alibaba.dubbo.common.URL;
|
||||
import com.alibaba.dubbo.rpc.cluster.Router;
|
||||
|
||||
public abstract class AbstractRouter implements Router {
|
||||
|
||||
protected URL url;
|
||||
protected int priority;
|
||||
|
||||
@Override
|
||||
public URL getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Router o) {
|
||||
return (this.getPriority() < o.getPriority()) ? -1 : ((this.getPriority() == o.getPriority()) ? 0 : 1);
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,6 @@ 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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -29,9 +28,14 @@ import java.util.List;
|
|||
/**
|
||||
* A specific Router designed to realize mock feature.
|
||||
* If a request is configured to use mock, then this router guarantees that only the invokers with protocol MOCK appear in final the invoker list, all other invokers will be excluded.
|
||||
*
|
||||
*/
|
||||
public class MockInvokersSelector implements Router {
|
||||
public class MockInvokersSelector extends AbstractRouter {
|
||||
|
||||
private static final int DEFAULT_PRIORITY = Integer.MAX_VALUE;
|
||||
|
||||
public MockInvokersSelector() {
|
||||
this.priority = DEFAULT_PRIORITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<Invoker<T>> route(final List<Invoker<T>> invokers,
|
||||
|
|
@ -87,14 +91,4 @@ public class MockInvokersSelector implements Router {
|
|||
return hasMockProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getUrl() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Router o) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ 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.router.AbstractRouter;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -40,21 +41,19 @@ import java.util.regex.Pattern;
|
|||
|
||||
/**
|
||||
* ConditionRouter
|
||||
*
|
||||
*/
|
||||
public class ConditionRouter implements Router, Comparable<Router> {
|
||||
public class ConditionRouter extends AbstractRouter {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ConditionRouter.class);
|
||||
private static final int DEFAULT_PRIORITY = 2;
|
||||
private static Pattern ROUTE_PATTERN = Pattern.compile("([&!=,]*)\\s*([^&!=,\\s]+)");
|
||||
private final URL url;
|
||||
private final int priority;
|
||||
private final boolean force;
|
||||
private final Map<String, MatchPair> whenCondition;
|
||||
private final Map<String, MatchPair> thenCondition;
|
||||
|
||||
public ConditionRouter(URL url) {
|
||||
this.url = url;
|
||||
this.priority = url.getParameter(Constants.PRIORITY_KEY, 0);
|
||||
this.priority = url.getParameter(Constants.PRIORITY_KEY, DEFAULT_PRIORITY);
|
||||
this.force = url.getParameter(Constants.FORCE_KEY, false);
|
||||
try {
|
||||
String rule = url.getParameterAndDecoded(Constants.RULE_KEY);
|
||||
|
|
|
|||
|
|
@ -20,11 +20,12 @@ import com.alibaba.dubbo.common.Constants;
|
|||
import com.alibaba.dubbo.common.URL;
|
||||
import com.alibaba.dubbo.common.logger.Logger;
|
||||
import com.alibaba.dubbo.common.logger.LoggerFactory;
|
||||
import com.alibaba.dubbo.common.utils.StringUtils;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.RpcContext;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.cluster.Router;
|
||||
import com.alibaba.dubbo.rpc.cluster.router.AbstractRouter;
|
||||
|
||||
import javax.script.Bindings;
|
||||
import javax.script.Compilable;
|
||||
|
|
@ -32,6 +33,13 @@ import javax.script.CompiledScript;
|
|||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.CodeSource;
|
||||
import java.security.Permissions;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
|
@ -40,33 +48,64 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
|
||||
/**
|
||||
* ScriptRouter
|
||||
*
|
||||
*/
|
||||
public class ScriptRouter implements Router {
|
||||
public class ScriptRouter extends AbstractRouter {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ScriptRouter.class);
|
||||
|
||||
private static final int DEFAULT_PRIORITY = 1;
|
||||
|
||||
private static final Map<String, ScriptEngine> engines = new ConcurrentHashMap<String, ScriptEngine>();
|
||||
|
||||
private final ScriptEngine engine;
|
||||
|
||||
private final int priority;
|
||||
|
||||
private final String rule;
|
||||
|
||||
private final URL url;
|
||||
private CompiledScript function;
|
||||
|
||||
private AccessControlContext accessControlContext;
|
||||
|
||||
{
|
||||
//Just give permission of reflect to access member.
|
||||
Permissions perms = new Permissions();
|
||||
perms.add(new RuntimePermission("accessDeclaredMembers"));
|
||||
// Cast to Certificate[] required because of ambiguity:
|
||||
ProtectionDomain domain = new ProtectionDomain(new CodeSource(null, (Certificate[]) null), perms);
|
||||
accessControlContext = new AccessControlContext(new ProtectionDomain[]{domain});
|
||||
}
|
||||
|
||||
public ScriptRouter(URL url) {
|
||||
this.url = url;
|
||||
String type = url.getParameter(Constants.TYPE_KEY);
|
||||
this.priority = url.getParameter(Constants.PRIORITY_KEY, 0);
|
||||
String rule = url.getParameterAndDecoded(Constants.RULE_KEY);
|
||||
if (type == null || type.length() == 0) {
|
||||
type = Constants.DEFAULT_SCRIPT_TYPE_KEY;
|
||||
this.priority = url.getParameter(Constants.PRIORITY_KEY, DEFAULT_PRIORITY);
|
||||
|
||||
this.engine = getEngine(url);
|
||||
this.rule = getRule(url);
|
||||
|
||||
try {
|
||||
Compilable compilable = (Compilable) engine;
|
||||
function = compilable.compile(rule);
|
||||
} catch (ScriptException e) {
|
||||
logger.error("route error, rule has been ignored. rule: " + rule +
|
||||
", url: " + RpcContext.getContext().getUrl(), e);
|
||||
}
|
||||
if (rule == null || rule.length() == 0) {
|
||||
throw new IllegalStateException(new IllegalStateException("route rule can not be empty. rule:" + rule));
|
||||
}
|
||||
|
||||
/**
|
||||
* get rule from url parameters.
|
||||
*/
|
||||
private String getRule(URL url) {
|
||||
String vRule = url.getParameterAndDecoded(Constants.RULE_KEY);
|
||||
if (StringUtils.isEmpty(vRule)) {
|
||||
throw new IllegalStateException("route rule can not be empty.");
|
||||
}
|
||||
return vRule;
|
||||
}
|
||||
|
||||
/**
|
||||
* create ScriptEngine instance by type from url parameters, then cache it
|
||||
*/
|
||||
private ScriptEngine getEngine(URL url) {
|
||||
String type = url.getParameter(Constants.TYPE_KEY, Constants.DEFAULT_SCRIPT_TYPE_KEY);
|
||||
ScriptEngine engine = engines.get(type);
|
||||
if (engine == null) {
|
||||
engine = new ScriptEngineManager().getEngineByName(type);
|
||||
|
|
@ -75,52 +114,61 @@ public class ScriptRouter implements Router {
|
|||
}
|
||||
engines.put(type, engine);
|
||||
}
|
||||
this.engine = engine;
|
||||
this.rule = rule;
|
||||
|
||||
return engine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, 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 + ", method:" + invocation.getMethodName() + ", url: " + RpcContext.getContext().getUrl(), e);
|
||||
public <T> List<Invoker<T>> route(final List<Invoker<T>> invokers, URL url, final Invocation invocation) throws RpcException {
|
||||
if (engine == null || function == null) {
|
||||
return invokers;
|
||||
}
|
||||
final Bindings bindings = createBindings(invokers, invocation);
|
||||
return getRoutedInvokers(AccessController.doPrivileged(new PrivilegedAction() {
|
||||
@Override
|
||||
public Object run() {
|
||||
try {
|
||||
return function.eval(bindings);
|
||||
} catch (ScriptException e) {
|
||||
logger.error("route error, rule has been ignored. rule: " + rule + ", method:" +
|
||||
invocation.getMethodName() + ", url: " + RpcContext.getContext().getUrl(), e);
|
||||
return invokers;
|
||||
}
|
||||
}
|
||||
}, accessControlContext));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Router o) {
|
||||
if (o == null || o.getClass() != ScriptRouter.class) {
|
||||
return 1;
|
||||
/**
|
||||
* get routed invokers from result of script rule evaluation
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> List<Invoker<T>> getRoutedInvokers(Object obj) {
|
||||
if (obj instanceof Invoker[]) {
|
||||
return Arrays.asList((Invoker<T>[]) obj);
|
||||
} else if (obj instanceof Object[]) {
|
||||
Object[] objects = (Object[]) obj;
|
||||
List<Invoker<T>> invokers = new ArrayList<Invoker<T>>();
|
||||
for (Object object : objects) {
|
||||
invokers.add((Invoker<T>) object);
|
||||
}
|
||||
|
||||
return invokers;
|
||||
} else {
|
||||
return (List<Invoker<T>>) obj;
|
||||
}
|
||||
ScriptRouter c = (ScriptRouter) o;
|
||||
return this.priority == c.priority ? rule.compareTo(c.rule) : (this.priority > c.priority ? 1 : -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* create bindings for script engine
|
||||
*/
|
||||
private <T> Bindings createBindings(List<Invoker<T>> invokers, Invocation invocation) {
|
||||
Bindings bindings = engine.createBindings();
|
||||
// create a new List of invokers
|
||||
bindings.put("invokers", new ArrayList<Invoker<T>>(invokers));
|
||||
bindings.put("invocation", invocation);
|
||||
bindings.put("context", RpcContext.getContext());
|
||||
return bindings;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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 com.alibaba.dubbo.rpc.cluster.router.tag;
|
||||
|
||||
import com.alibaba.dubbo.common.Constants;
|
||||
import com.alibaba.dubbo.common.URL;
|
||||
import com.alibaba.dubbo.common.utils.StringUtils;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.RpcContext;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.cluster.router.AbstractRouter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* TagRouter
|
||||
*/
|
||||
public class TagRouter extends AbstractRouter {
|
||||
|
||||
private static final int DEFAULT_PRIORITY = 100;
|
||||
private static final URL ROUTER_URL = new URL("tag", Constants.ANYHOST_VALUE, 0, Constants.ANY_VALUE).addParameters(Constants.RUNTIME_KEY, "true");
|
||||
|
||||
public TagRouter() {
|
||||
this.url = ROUTER_URL;
|
||||
this.priority = url.getParameter(Constants.PRIORITY_KEY, DEFAULT_PRIORITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException {
|
||||
// filter
|
||||
List<Invoker<T>> result = new ArrayList<Invoker<T>>();
|
||||
// Dynamic param
|
||||
String tag = RpcContext.getContext().getAttachment(Constants.TAG_KEY);
|
||||
// Tag request
|
||||
if (!StringUtils.isEmpty(tag)) {
|
||||
// Select tag invokers first
|
||||
for (Invoker<T> invoker : invokers) {
|
||||
if (tag.equals(invoker.getUrl().getParameter(Constants.TAG_KEY))) {
|
||||
result.add(invoker);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If Constants.REQUEST_TAG_KEY unspecified or no invoker be selected, downgrade to normal invokers
|
||||
if (result.isEmpty()) {
|
||||
// Only forceTag = true force match, otherwise downgrade
|
||||
String forceTag = RpcContext.getContext().getAttachment(Constants.FORCE_USE_TAG);
|
||||
if (StringUtils.isEmpty(forceTag) || "false".equals(forceTag)) {
|
||||
for (Invoker<T> invoker : invokers) {
|
||||
if (StringUtils.isEmpty(invoker.getUrl().getParameter(Constants.TAG_KEY))) {
|
||||
result.add(invoker);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -25,6 +25,8 @@ 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.RpcContext;
|
||||
import com.alibaba.dubbo.rpc.RpcInvocation;
|
||||
import com.alibaba.dubbo.rpc.Result;
|
||||
import com.alibaba.dubbo.rpc.RpcException;
|
||||
import com.alibaba.dubbo.rpc.cluster.Directory;
|
||||
|
|
@ -33,6 +35,7 @@ import com.alibaba.dubbo.rpc.support.RpcUtils;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
|
|
@ -225,6 +228,13 @@ public abstract class AbstractClusterInvoker<T> implements Invoker<T> {
|
|||
public Result invoke(final Invocation invocation) throws RpcException {
|
||||
checkWhetherDestroyed();
|
||||
LoadBalance loadbalance = null;
|
||||
|
||||
// binding attachments into invocation.
|
||||
Map<String, String> contextAttachments = RpcContext.getContext().getAttachments();
|
||||
if (contextAttachments != null && contextAttachments.size() != 0) {
|
||||
((RpcInvocation) invocation).addAttachments(contextAttachments);
|
||||
}
|
||||
|
||||
List<Invoker<T>> invokers = list(invocation);
|
||||
if (invokers != null && !invokers.isEmpty()) {
|
||||
loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(invokers.get(0).getUrl()
|
||||
|
|
|
|||
|
|
@ -71,6 +71,14 @@ public class ClusterUtils {
|
|||
if (dubbo != null && dubbo.length() > 0) {
|
||||
map.put(Constants.DUBBO_VERSION_KEY, dubbo);
|
||||
}
|
||||
String defaultVersion = remoteMap.get(Constants.DEFAULT_KEY_PREFIX + Constants.VERSION_KEY);
|
||||
if (defaultVersion != null && defaultVersion.length() > 0) {
|
||||
map.put(Constants.DEFAULT_KEY_PREFIX + Constants.VERSION_KEY, defaultVersion);
|
||||
}
|
||||
String defaultGroup = remoteMap.get(Constants.DEFAULT_KEY_PREFIX + Constants.GROUP_KEY);
|
||||
if (defaultGroup != null && defaultGroup.length() > 0) {
|
||||
map.put(Constants.DEFAULT_KEY_PREFIX + Constants.GROUP_KEY, defaultGroup);
|
||||
}
|
||||
String version = remoteMap.get(Constants.VERSION_KEY);
|
||||
if (version != null && version.length() > 0) {
|
||||
map.put(Constants.VERSION_KEY, version);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ 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;
|
||||
import com.alibaba.dubbo.rpc.support.RpcUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
|
|
@ -54,7 +55,8 @@ public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
|
|||
public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
|
||||
List<Invoker<T>> copyinvokers = invokers;
|
||||
checkInvokers(copyinvokers, invocation);
|
||||
int len = getUrl().getMethodParameter(invocation.getMethodName(), Constants.RETRIES_KEY, Constants.DEFAULT_RETRIES) + 1;
|
||||
String methodName = RpcUtils.getMethodName(invocation);
|
||||
int len = getUrl().getMethodParameter(methodName, Constants.RETRIES_KEY, Constants.DEFAULT_RETRIES) + 1;
|
||||
if (len <= 0) {
|
||||
len = 1;
|
||||
}
|
||||
|
|
@ -77,7 +79,7 @@ public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
|
|||
try {
|
||||
Result result = invoker.invoke(invocation);
|
||||
if (le != null && logger.isWarnEnabled()) {
|
||||
logger.warn("Although retry the method " + invocation.getMethodName()
|
||||
logger.warn("Although retry the method " + methodName
|
||||
+ " in the service " + getInterface().getName()
|
||||
+ " was successful by the provider " + invoker.getUrl().getAddress()
|
||||
+ ", but there have been failed providers " + providers
|
||||
|
|
@ -100,7 +102,7 @@ public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
|
|||
}
|
||||
}
|
||||
throw new RpcException(le != null ? le.getCode() : 0, "Failed to invoke the method "
|
||||
+ invocation.getMethodName() + " in the service " + getInterface().getName()
|
||||
+ methodName + " in the service " + getInterface().getName()
|
||||
+ ". Tried " + len + " times of the providers " + providers
|
||||
+ " (" + providers.size() + "/" + copyinvokers.size()
|
||||
+ ") from the registry " + directory.getUrl().getAddress()
|
||||
|
|
|
|||
|
|
@ -57,50 +57,55 @@ public class ForkingClusterInvoker<T> extends AbstractClusterInvoker<T> {
|
|||
@Override
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public Result doInvoke(final Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
|
||||
checkInvokers(invokers, invocation);
|
||||
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++) {
|
||||
// TODO. Add some comment here, refer chinese version for more details.
|
||||
Invoker<T> invoker = select(loadbalance, invocation, invokers, selected);
|
||||
if (!selected.contains(invoker)) {//Avoid add the same invoker several times.
|
||||
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() {
|
||||
@Override
|
||||
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 {
|
||||
checkInvokers(invokers, invocation);
|
||||
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++) {
|
||||
// TODO. Add some comment here, refer chinese version for more details.
|
||||
Invoker<T> invoker = select(loadbalance, invocation, invokers, selected);
|
||||
if (!selected.contains(invoker)) {//Avoid add the same invoker several times.
|
||||
selected.add(invoker);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
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.getCause() != null ? e.getCause() : 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);
|
||||
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() {
|
||||
@Override
|
||||
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.getCause() != null ? e.getCause() : 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);
|
||||
}
|
||||
} finally {
|
||||
// clear attachments which is binding to current thread.
|
||||
RpcContext.getContext().clearAttachments();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,2 @@
|
|||
file=com.alibaba.dubbo.rpc.cluster.router.file.FileRouterFactory
|
||||
script=com.alibaba.dubbo.rpc.cluster.router.script.ScriptRouterFactory
|
||||
condition=com.alibaba.dubbo.rpc.cluster.router.condition.ConditionRouterFactory
|
||||
|
|
@ -114,12 +114,12 @@ public class StickyTest {
|
|||
|
||||
given(invoker1.invoke(invocation)).willReturn(result);
|
||||
given(invoker1.isAvailable()).willReturn(true);
|
||||
given(invoker1.getUrl()).willReturn(url);
|
||||
given(invoker1.getUrl()).willReturn(url.setPort(1));
|
||||
given(invoker1.getInterface()).willReturn(StickyTest.class);
|
||||
|
||||
given(invoker2.invoke(invocation)).willReturn(result);
|
||||
given(invoker2.isAvailable()).willReturn(true);
|
||||
given(invoker2.getUrl()).willReturn(url);
|
||||
given(invoker2.getUrl()).willReturn(url.setPort(2));
|
||||
given(invoker2.getInterface()).willReturn(StickyTest.class);
|
||||
|
||||
invocation.setMethodName(methodName);
|
||||
|
|
@ -158,4 +158,4 @@ public class StickyTest {
|
|||
return selectedInvoker;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,18 +21,24 @@ import com.alibaba.dubbo.common.URL;
|
|||
import com.alibaba.dubbo.common.extension.ExtensionLoader;
|
||||
import com.alibaba.dubbo.rpc.Invocation;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.RpcInvocation;
|
||||
import com.alibaba.dubbo.rpc.RpcStatus;
|
||||
import com.alibaba.dubbo.rpc.cluster.LoadBalance;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import static org.mockito.BDDMockito.given;
|
||||
|
|
@ -40,7 +46,6 @@ import static org.mockito.Mockito.mock;
|
|||
|
||||
/**
|
||||
* RoundRobinLoadBalanceTest
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class LoadBalanceTest {
|
||||
|
|
@ -52,6 +57,11 @@ public class LoadBalanceTest {
|
|||
Invoker<LoadBalanceTest> invoker4;
|
||||
Invoker<LoadBalanceTest> invoker5;
|
||||
|
||||
RpcStatus weightTestRpcStatus1;
|
||||
RpcStatus weightTestRpcStatus2;
|
||||
RpcStatus weightTestRpcStatus3;
|
||||
RpcInvocation weightTestInvocation;
|
||||
|
||||
/**
|
||||
* @throws java.lang.Exception
|
||||
*/
|
||||
|
|
@ -106,16 +116,183 @@ public class LoadBalanceTest {
|
|||
invokers.add(invoker4);
|
||||
invokers.add(invoker5);
|
||||
}
|
||||
|
||||
|
||||
private AbstractLoadBalance getLoadBalance(String loadbalanceName) {
|
||||
return (AbstractLoadBalance) ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(loadbalanceName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRoundRobinLoadBalance_select() {
|
||||
int runs = 10000;
|
||||
int runs = 1000;
|
||||
Map<Invoker, AtomicLong> counter = getInvokeCounter(runs, RoundRobinLoadBalance.NAME);
|
||||
for (Invoker minvoker : counter.keySet()) {
|
||||
Long count = counter.get(minvoker).get();
|
||||
Assert.assertTrue("abs diff shoud < 1", Math.abs(count - runs / (0f + invokers.size())) < 1f);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertStrictWRRResult(int runs, Map<Invoker, InvokeResult> resultMap) {
|
||||
for (InvokeResult invokeResult : resultMap.values()) {
|
||||
// Because it's a strictly round robin, so the abs delta should be < 10 too
|
||||
Assert.assertTrue("delta with expected count should < 10",
|
||||
Math.abs(invokeResult.getExpected(runs) - invokeResult.getCount().get()) < 10);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* a multi-threaded test on weighted round robin
|
||||
*/
|
||||
@Test
|
||||
public void testRoundRobinLoadBalanceWithWeight() {
|
||||
final Map<Invoker, InvokeResult> totalMap = new HashMap<Invoker, InvokeResult>();
|
||||
final AtomicBoolean shouldBegin = new AtomicBoolean(false);
|
||||
final int runs = 1000;
|
||||
List<Thread> threads = new ArrayList<Thread>();
|
||||
int threadNum = 10;
|
||||
for (int i = 0; i < threadNum; i ++) {
|
||||
threads.add(new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (!shouldBegin.get()) {
|
||||
try {
|
||||
sleep(5);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
Map<Invoker, InvokeResult> resultMap = getWeightedInvokeResult(runs, RoundRobinLoadBalance.NAME);
|
||||
synchronized (totalMap) {
|
||||
for (Entry<Invoker, InvokeResult> entry : resultMap.entrySet()) {
|
||||
if (!totalMap.containsKey(entry.getKey())) {
|
||||
totalMap.put(entry.getKey(), entry.getValue());
|
||||
} else {
|
||||
totalMap.get(entry.getKey()).getCount().addAndGet(entry.getValue().getCount().get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
for (Thread thread : threads) {
|
||||
thread.start();
|
||||
}
|
||||
// let's rock it!
|
||||
shouldBegin.set(true);
|
||||
for (Thread thread : threads) {
|
||||
try {
|
||||
thread.join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
assertStrictWRRResult(runs * threadNum, totalMap);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRoundRobinLoadBalanceWithWeightShouldNotRecycle() {
|
||||
int runs = 1000;
|
||||
//tmperately add a new invoker
|
||||
weightInvokers.add(weightInvokerTmp);
|
||||
try {
|
||||
Map<Invoker, InvokeResult> resultMap = getWeightedInvokeResult(runs, RoundRobinLoadBalance.NAME);
|
||||
assertStrictWRRResult(runs, resultMap);
|
||||
RoundRobinLoadBalance lb = (RoundRobinLoadBalance)getLoadBalance(RoundRobinLoadBalance.NAME);
|
||||
Assert.assertEquals(weightInvokers.size(), lb.getInvokerAddrList(weightInvokers, weightTestInvocation).size());
|
||||
|
||||
//remove the last invoker and retry
|
||||
weightInvokers.remove(weightInvokerTmp);
|
||||
resultMap = getWeightedInvokeResult(runs, RoundRobinLoadBalance.NAME);
|
||||
assertStrictWRRResult(runs, resultMap);
|
||||
Assert.assertNotEquals(weightInvokers.size(), lb.getInvokerAddrList(weightInvokers, weightTestInvocation).size());
|
||||
} finally {
|
||||
weightInvokers.remove(weightInvokerTmp);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRoundRobinLoadBalanceWithWeightShouldRecycle() {
|
||||
{
|
||||
Field recycleTimeField = null;
|
||||
try {
|
||||
//change recycle time to 1 ms
|
||||
recycleTimeField = RoundRobinLoadBalance.class.getDeclaredField("RECYCLE_PERIOD");
|
||||
recycleTimeField.setAccessible(true);
|
||||
recycleTimeField.setInt(RoundRobinLoadBalance.class, 10);
|
||||
} catch (NoSuchFieldException e) {
|
||||
Assert.assertTrue("getField failed", true);
|
||||
} catch (SecurityException e) {
|
||||
Assert.assertTrue("getField failed", true);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Assert.assertTrue("getField failed", true);
|
||||
} catch (IllegalAccessException e) {
|
||||
Assert.assertTrue("getField failed", true);
|
||||
}
|
||||
}
|
||||
int runs = 1000;
|
||||
//temporarily add a new invoker
|
||||
weightInvokers.add(weightInvokerTmp);
|
||||
try {
|
||||
Map<Invoker, InvokeResult> resultMap = getWeightedInvokeResult(runs, RoundRobinLoadBalance.NAME);
|
||||
assertStrictWRRResult(runs, resultMap);
|
||||
RoundRobinLoadBalance lb = (RoundRobinLoadBalance)getLoadBalance(RoundRobinLoadBalance.NAME);
|
||||
Assert.assertEquals(weightInvokers.size(), lb.getInvokerAddrList(weightInvokers, weightTestInvocation).size());
|
||||
|
||||
//remove the tmp invoker and retry, should recycle its cache
|
||||
weightInvokers.remove(weightInvokerTmp);
|
||||
resultMap = getWeightedInvokeResult(runs, RoundRobinLoadBalance.NAME);
|
||||
assertStrictWRRResult(runs, resultMap);
|
||||
Assert.assertEquals(weightInvokers.size(), lb.getInvokerAddrList(weightInvokers, weightTestInvocation).size());
|
||||
} finally {
|
||||
weightInvokers.remove(weightInvokerTmp);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectByWeightLeastActive() {
|
||||
int sumInvoker1 = 0;
|
||||
int sumInvoker2 = 0;
|
||||
int loop = 1000;
|
||||
LeastActiveLoadBalance lb = new LeastActiveLoadBalance();
|
||||
for (int i = 0; i < loop; i++) {
|
||||
Invoker selected = lb.select(weightInvokers, null, weightTestInvocation);
|
||||
if (selected.getUrl().getProtocol().equals("test1")) {
|
||||
sumInvoker1++;
|
||||
}
|
||||
if (selected.getUrl().getProtocol().equals("test2")) {
|
||||
sumInvoker2++;
|
||||
}
|
||||
// never select invoker3 because it's active is more than invoker1 and invoker2
|
||||
Assert.assertTrue("select is not the least active one", !selected.getUrl().getProtocol().equals("test3"));
|
||||
}
|
||||
// the sumInvoker1 : sumInvoker2 approximately equal to 1: 9
|
||||
System.out.println(sumInvoker1);
|
||||
System.out.println(sumInvoker2);
|
||||
Assert.assertEquals("select failed!", sumInvoker1 + sumInvoker2, loop);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectByWeightRandom() {
|
||||
int sumInvoker1 = 0;
|
||||
int sumInvoker2 = 0;
|
||||
int sumInvoker3 = 0;
|
||||
int loop = 1000;
|
||||
RandomLoadBalance lb = new RandomLoadBalance();
|
||||
for (int i = 0; i < loop; i++) {
|
||||
Invoker selected = lb.select(weightInvokers, null, weightTestInvocation);
|
||||
if (selected.getUrl().getProtocol().equals("test1")) {
|
||||
sumInvoker1++;
|
||||
}
|
||||
if (selected.getUrl().getProtocol().equals("test2")) {
|
||||
sumInvoker2++;
|
||||
}
|
||||
if (selected.getUrl().getProtocol().equals("test3")) {
|
||||
sumInvoker3++;
|
||||
}
|
||||
}
|
||||
// 1 : 9 : 6
|
||||
System.out.println(sumInvoker1);
|
||||
System.out.println(sumInvoker2);
|
||||
System.out.println(sumInvoker3);
|
||||
Assert.assertEquals("select failed!", sumInvoker1 + sumInvoker2 + sumInvoker3, loop);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRandomLoadBalance_select() {
|
||||
|
|
@ -125,7 +302,7 @@ public class LoadBalanceTest {
|
|||
Long count = counter.get(minvoker).get();
|
||||
// System.out.println(count);
|
||||
Assert.assertTrue("abs diff shoud < avg",
|
||||
Math.abs(count - runs / (0f + invokers.size())) < runs / (0f + invokers.size()));
|
||||
Math.abs(count - runs / (0f + invokers.size())) < runs / (0f + invokers.size()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
|
|
@ -146,24 +323,25 @@ public class LoadBalanceTest {
|
|||
|
||||
@Test
|
||||
public void testLeastActiveLoadBalance_select() {
|
||||
int runs = 10000;
|
||||
int runs = 1000;
|
||||
Map<Invoker, AtomicLong> counter = getInvokeCounter(runs, LeastActiveLoadBalance.NAME);
|
||||
for (Invoker minvoker : counter.keySet()) {
|
||||
Long count = counter.get(minvoker).get();
|
||||
// System.out.println(count);
|
||||
Assert.assertTrue("abs diff shoud < avg",
|
||||
Math.abs(count - runs / (0f + invokers.size())) < runs / (0f + invokers.size()));
|
||||
Math.abs(count - runs / (0f + invokers.size())) < runs / (0f + invokers.size()));
|
||||
}
|
||||
}
|
||||
|
||||
public Map<Invoker, AtomicLong> getInvokeCounter(int runs, String loadbalanceName) {
|
||||
|
||||
private Map<Invoker, AtomicLong> getInvokeCounter(int runs, String loadbalanceName) {
|
||||
Map<Invoker, AtomicLong> counter = new ConcurrentHashMap<Invoker, AtomicLong>();
|
||||
LoadBalance lb = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(loadbalanceName);
|
||||
LoadBalance lb = getLoadBalance(loadbalanceName);
|
||||
for (Invoker invoker : invokers) {
|
||||
counter.put(invoker, new AtomicLong(0));
|
||||
}
|
||||
URL url = invokers.get(0).getUrl();
|
||||
for (int i = 0; i < runs; i++) {
|
||||
Invoker sinvoker = lb.select(invokers, invokers.get(0).getUrl(), invocation);
|
||||
Invoker sinvoker = lb.select(invokers, url, invocation);
|
||||
counter.get(sinvoker).incrementAndGet();
|
||||
}
|
||||
return counter;
|
||||
|
|
@ -172,33 +350,143 @@ public class LoadBalanceTest {
|
|||
@Test
|
||||
public void testLoadBalanceWarmup() {
|
||||
Assert.assertEquals(1,
|
||||
AbstractLoadBalance.calculateWarmupWeight(0, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
AbstractLoadBalance.calculateWarmupWeight(0, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
Assert.assertEquals(1,
|
||||
AbstractLoadBalance.calculateWarmupWeight(13, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
AbstractLoadBalance.calculateWarmupWeight(13, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
Assert.assertEquals(1,
|
||||
AbstractLoadBalance.calculateWarmupWeight(6 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
AbstractLoadBalance.calculateWarmupWeight(6 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
Assert.assertEquals(2,
|
||||
AbstractLoadBalance.calculateWarmupWeight(12 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
AbstractLoadBalance.calculateWarmupWeight(12 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
Assert.assertEquals(10,
|
||||
AbstractLoadBalance.calculateWarmupWeight(60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
AbstractLoadBalance.calculateWarmupWeight(60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
Assert.assertEquals(50, AbstractLoadBalance
|
||||
.calculateWarmupWeight(5 * 60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
.calculateWarmupWeight(5 * 60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
Assert.assertEquals(50, AbstractLoadBalance
|
||||
.calculateWarmupWeight(5 * 60 * 1000 + 23, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
.calculateWarmupWeight(5 * 60 * 1000 + 23, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
Assert.assertEquals(50, AbstractLoadBalance
|
||||
.calculateWarmupWeight(5 * 60 * 1000 + 5999, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
.calculateWarmupWeight(5 * 60 * 1000 + 5999, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
Assert.assertEquals(51, AbstractLoadBalance
|
||||
.calculateWarmupWeight(5 * 60 * 1000 + 6000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
.calculateWarmupWeight(5 * 60 * 1000 + 6000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
Assert.assertEquals(90, AbstractLoadBalance
|
||||
.calculateWarmupWeight(9 * 60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
.calculateWarmupWeight(9 * 60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
Assert.assertEquals(98, AbstractLoadBalance
|
||||
.calculateWarmupWeight(10 * 60 * 1000 - 12 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
.calculateWarmupWeight(10 * 60 * 1000 - 12 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
Assert.assertEquals(99, AbstractLoadBalance
|
||||
.calculateWarmupWeight(10 * 60 * 1000 - 6 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
.calculateWarmupWeight(10 * 60 * 1000 - 6 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
Assert.assertEquals(100, AbstractLoadBalance
|
||||
.calculateWarmupWeight(10 * 60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
.calculateWarmupWeight(10 * 60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
Assert.assertEquals(100, AbstractLoadBalance
|
||||
.calculateWarmupWeight(20 * 60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
.calculateWarmupWeight(20 * 60 * 1000, Constants.DEFAULT_WARMUP, Constants.DEFAULT_WEIGHT));
|
||||
}
|
||||
|
||||
/*------------------------------------test invokers for weight---------------------------------------*/
|
||||
|
||||
protected List<Invoker<LoadBalanceTest>> weightInvokers = new ArrayList<Invoker<LoadBalanceTest>>();
|
||||
protected Invoker<LoadBalanceTest> weightInvoker1;
|
||||
protected Invoker<LoadBalanceTest> weightInvoker2;
|
||||
protected Invoker<LoadBalanceTest> weightInvoker3;
|
||||
protected Invoker<LoadBalanceTest> weightInvokerTmp;
|
||||
|
||||
@Before
|
||||
public void setUpWeightInvokers() throws Exception {
|
||||
weightInvoker1 = mock(Invoker.class);
|
||||
weightInvoker2 = mock(Invoker.class);
|
||||
weightInvoker3 = mock(Invoker.class);
|
||||
weightInvokerTmp = mock(Invoker.class);
|
||||
|
||||
weightTestInvocation = new RpcInvocation();
|
||||
weightTestInvocation.setMethodName("test");
|
||||
|
||||
URL url1 = URL.valueOf("test1://127.0.0.1:11/DemoService?weight=11&active=0");
|
||||
URL url2 = URL.valueOf("test2://127.0.0.1:12/DemoService?weight=97&active=0");
|
||||
URL url3 = URL.valueOf("test3://127.0.0.1:13/DemoService?weight=67&active=1");
|
||||
URL urlTmp = URL.valueOf("test4://127.0.0.1:9999/DemoService?weight=601&active=0");
|
||||
|
||||
given(weightInvoker1.isAvailable()).willReturn(true);
|
||||
given(weightInvoker1.getInterface()).willReturn(LoadBalanceTest.class);
|
||||
given(weightInvoker1.getUrl()).willReturn(url1);
|
||||
|
||||
given(weightInvoker2.isAvailable()).willReturn(true);
|
||||
given(weightInvoker2.getInterface()).willReturn(LoadBalanceTest.class);
|
||||
given(weightInvoker2.getUrl()).willReturn(url2);
|
||||
|
||||
given(weightInvoker3.isAvailable()).willReturn(true);
|
||||
given(weightInvoker3.getInterface()).willReturn(LoadBalanceTest.class);
|
||||
given(weightInvoker3.getUrl()).willReturn(url3);
|
||||
|
||||
given(weightInvokerTmp.isAvailable()).willReturn(true);
|
||||
given(weightInvokerTmp.getInterface()).willReturn(LoadBalanceTest.class);
|
||||
given(weightInvokerTmp.getUrl()).willReturn(urlTmp);
|
||||
|
||||
weightInvokers.add(weightInvoker1);
|
||||
weightInvokers.add(weightInvoker2);
|
||||
weightInvokers.add(weightInvoker3);
|
||||
|
||||
weightTestRpcStatus1 = RpcStatus.getStatus(weightInvoker1.getUrl(), weightTestInvocation.getMethodName());
|
||||
weightTestRpcStatus2 = RpcStatus.getStatus(weightInvoker2.getUrl(), weightTestInvocation.getMethodName());
|
||||
weightTestRpcStatus3 = RpcStatus.getStatus(weightInvoker3.getUrl(), weightTestInvocation.getMethodName());
|
||||
|
||||
// weightTestRpcStatus3 active is 1
|
||||
RpcStatus.beginCount(weightInvoker3.getUrl(), weightTestInvocation.getMethodName());
|
||||
}
|
||||
|
||||
private static class InvokeResult {
|
||||
private AtomicLong count = new AtomicLong();
|
||||
private int weight = 0;
|
||||
private int totalWeight = 0;
|
||||
|
||||
public InvokeResult(int weight) {
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
public AtomicLong getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public int getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
public int getTotalWeight() {
|
||||
return totalWeight;
|
||||
}
|
||||
|
||||
public void setTotalWeight(int totalWeight) {
|
||||
this.totalWeight = totalWeight;
|
||||
}
|
||||
|
||||
public int getExpected(int runCount) {
|
||||
return getWeight() * runCount / getTotalWeight();
|
||||
}
|
||||
|
||||
public float getDeltaPercentage(int runCount) {
|
||||
int expected = getExpected(runCount);
|
||||
return Math.abs((expected - getCount().get()) * 100.0f / expected);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JSON.toJSONString(this);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Invoker, InvokeResult> getWeightedInvokeResult(int runs, String loadbalanceName) {
|
||||
Map<Invoker, InvokeResult> counter = new ConcurrentHashMap<Invoker, InvokeResult>();
|
||||
AbstractLoadBalance lb = getLoadBalance(loadbalanceName);
|
||||
int totalWeight = 0;
|
||||
for (int i = 0; i < weightInvokers.size(); i ++) {
|
||||
InvokeResult invokeResult = new InvokeResult(lb.getWeight(weightInvokers.get(i), weightTestInvocation));
|
||||
counter.put(weightInvokers.get(i), invokeResult);
|
||||
totalWeight += invokeResult.getWeight();
|
||||
}
|
||||
for (InvokeResult invokeResult : counter.values()) {
|
||||
invokeResult.setTotalWeight(totalWeight);
|
||||
}
|
||||
for (int i = 0; i < runs; i++) {
|
||||
Invoker sinvoker = lb.select(weightInvokers, weightInvokers.get(0).getUrl(), weightTestInvocation);
|
||||
counter.get(sinvoker).getCount().incrementAndGet();
|
||||
}
|
||||
return counter;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -27,6 +27,7 @@ import com.alibaba.dubbo.rpc.cluster.router.MockInvoker;
|
|||
import junit.framework.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -49,6 +50,7 @@ public class ScriptRouterTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testRoute_ReturnAll() {
|
||||
Router router = new ScriptRouterFactory().getRouter(getRouteUrl("function route(op1,op2){return op1} route(invokers)"));
|
||||
List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
|
||||
|
|
@ -60,6 +62,7 @@ public class ScriptRouterTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testRoute_PickInvokers() {
|
||||
String rule = "var result = new java.util.ArrayList(invokers.size());" +
|
||||
"for (i=0;i<invokers.size(); i++){ " +
|
||||
|
|
|
|||
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* 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 com.alibaba.dubbo.rpc.cluster.router.tag;
|
||||
|
||||
import com.alibaba.dubbo.common.Constants;
|
||||
import com.alibaba.dubbo.common.URL;
|
||||
import com.alibaba.dubbo.common.utils.NetUtils;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.RpcContext;
|
||||
import com.alibaba.dubbo.rpc.RpcInvocation;
|
||||
import com.alibaba.dubbo.rpc.cluster.Router;
|
||||
import com.alibaba.dubbo.rpc.cluster.router.MockInvoker;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TagRouterTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() throws Exception {
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
RpcContext.getContext().clearAttachments();
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
RpcContext.getContext().clearAttachments();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRoute_matchTag() {
|
||||
RpcContext.getContext().setAttachment(Constants.TAG_KEY, "red");
|
||||
|
||||
List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
|
||||
Invoker<String> redInvoker = new MockInvoker<String>(URL.valueOf(
|
||||
"dubbo://10.20.3.1:20880/com.foo.BarService?dubbo.tag=red"));
|
||||
Invoker<String> yellowInvoker = new MockInvoker<String>(URL.valueOf(
|
||||
"dubbo://10.20.3.2:20880/com.foo.BarService?dubbo.tag=yellow"));
|
||||
Invoker<String> blueInvoker = new MockInvoker<String>(URL.valueOf(
|
||||
"dubbo://10.20.3.3:20880/com.foo.BarService?dubbo.tag=blue"));
|
||||
Invoker<String> defaultInvoker = new MockInvoker<String>(URL.valueOf(
|
||||
"dubbo://10.20.3.4:20880/com.foo.BarService"));
|
||||
|
||||
invokers.add(redInvoker);
|
||||
invokers.add(yellowInvoker);
|
||||
invokers.add(blueInvoker);
|
||||
invokers.add(defaultInvoker);
|
||||
|
||||
Router tagRouter = new TagRouter();
|
||||
List<Invoker<String>> filteredInvokers = tagRouter.route(invokers, URL.valueOf("consumer://" + NetUtils.getLocalHost() + "/com.foo.BarService"), new RpcInvocation());
|
||||
Assert.assertTrue(filteredInvokers.contains(redInvoker));
|
||||
Assert.assertFalse(filteredInvokers.contains(yellowInvoker));
|
||||
Assert.assertFalse(filteredInvokers.contains(blueInvoker));
|
||||
Assert.assertFalse(filteredInvokers.contains(defaultInvoker));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRoute_matchDefault() {
|
||||
|
||||
RpcContext.getContext().setAttachment(Constants.TAG_KEY, "");
|
||||
|
||||
List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
|
||||
Invoker<String> redInvoker = new MockInvoker<String>(URL.valueOf(
|
||||
"dubbo://10.20.3.1:20880/com.foo.BarService?dubbo.tag=red"));
|
||||
Invoker<String> yellowInvoker = new MockInvoker<String>(URL.valueOf(
|
||||
"dubbo://10.20.3.2:20880/com.foo.BarService?dubbo.tag=yellow"));
|
||||
Invoker<String> blueInvoker = new MockInvoker<String>(URL.valueOf(
|
||||
"dubbo://10.20.3.3:20880/com.foo.BarService?dubbo.tag=blue"));
|
||||
Invoker<String> defaultInvoker = new MockInvoker<String>(URL.valueOf(
|
||||
"dubbo://10.20.3.4:20880/com.foo.BarService"));
|
||||
|
||||
invokers.add(redInvoker);
|
||||
invokers.add(yellowInvoker);
|
||||
invokers.add(blueInvoker);
|
||||
invokers.add(defaultInvoker);
|
||||
|
||||
Router tagRouter = new TagRouter();
|
||||
List<Invoker<String>> filteredInvokers = tagRouter.route(invokers, URL.valueOf("consumer://" + NetUtils.getLocalHost() + "/com.foo.BarService"), new RpcInvocation());
|
||||
Assert.assertTrue(filteredInvokers.contains(defaultInvoker));
|
||||
Assert.assertFalse(filteredInvokers.contains(yellowInvoker));
|
||||
Assert.assertFalse(filteredInvokers.contains(blueInvoker));
|
||||
Assert.assertFalse(filteredInvokers.contains(redInvoker));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRoute_requestWithTag_shouldDowngrade() {
|
||||
|
||||
RpcContext.getContext().setAttachment(Constants.TAG_KEY, "black");
|
||||
|
||||
List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
|
||||
Invoker<String> redInvoker = new MockInvoker<String>(URL.valueOf(
|
||||
"dubbo://10.20.3.1:20880/com.foo.BarService?dubbo.tag=red"));
|
||||
Invoker<String> yellowInvoker = new MockInvoker<String>(URL.valueOf(
|
||||
"dubbo://10.20.3.2:20880/com.foo.BarService?dubbo.tag=yellow"));
|
||||
Invoker<String> blueInvoker = new MockInvoker<String>(URL.valueOf(
|
||||
"dubbo://10.20.3.3:20880/com.foo.BarService?dubbo.tag=blue"));
|
||||
Invoker<String> defaultInvoker = new MockInvoker<String>(URL.valueOf(
|
||||
"dubbo://10.20.3.4:20880/com.foo.BarService"));
|
||||
|
||||
invokers.add(redInvoker);
|
||||
invokers.add(yellowInvoker);
|
||||
invokers.add(blueInvoker);
|
||||
invokers.add(defaultInvoker);
|
||||
|
||||
Router tagRouter = new TagRouter();
|
||||
List<Invoker<String>> filteredInvokers = tagRouter.route(invokers, URL.valueOf("consumer://" + NetUtils.getLocalHost() + "/com.foo.BarService"), new RpcInvocation());
|
||||
Assert.assertTrue(filteredInvokers.contains(defaultInvoker));
|
||||
Assert.assertFalse(filteredInvokers.contains(yellowInvoker));
|
||||
Assert.assertFalse(filteredInvokers.contains(blueInvoker));
|
||||
Assert.assertFalse(filteredInvokers.contains(redInvoker));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRoute_requestWithoutTag_shouldNotDowngrade() {
|
||||
|
||||
RpcContext.getContext().setAttachment(Constants.TAG_KEY, "");
|
||||
|
||||
List<Invoker<String>> invokers = new ArrayList<Invoker<String>>();
|
||||
Invoker<String> redInvoker = new MockInvoker<String>(URL.valueOf(
|
||||
"dubbo://10.20.3.1:20880/com.foo.BarService?dubbo.tag=red"));
|
||||
Invoker<String> yellowInvoker = new MockInvoker<String>(URL.valueOf(
|
||||
"dubbo://10.20.3.2:20880/com.foo.BarService?dubbo.tag=yellow"));
|
||||
Invoker<String> blueInvoker = new MockInvoker<String>(URL.valueOf(
|
||||
"dubbo://10.20.3.3:20880/com.foo.BarService?dubbo.tag=blue"));
|
||||
|
||||
invokers.add(redInvoker);
|
||||
invokers.add(yellowInvoker);
|
||||
invokers.add(blueInvoker);
|
||||
|
||||
Router tagRouter = new TagRouter();
|
||||
List<Invoker<String>> filteredInvokers = tagRouter.route(invokers, URL.valueOf("consumer://" + NetUtils.getLocalHost() + "/com.foo.BarService"), new RpcInvocation());
|
||||
Assert.assertEquals(0, filteredInvokers.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@ 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.RpcInvocation;
|
||||
import com.alibaba.dubbo.rpc.cluster.Directory;
|
||||
|
|
@ -32,7 +33,6 @@ import com.alibaba.dubbo.rpc.cluster.filter.DemoService;
|
|||
import com.alibaba.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance;
|
||||
import com.alibaba.dubbo.rpc.cluster.loadbalance.RandomLoadBalance;
|
||||
import com.alibaba.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
|
|
@ -90,23 +90,23 @@ public class AbstractClusterInvokerTest {
|
|||
|
||||
given(invoker1.isAvailable()).willReturn(false);
|
||||
given(invoker1.getInterface()).willReturn(IHelloService.class);
|
||||
given(invoker1.getUrl()).willReturn(turl.addParameter("name", "invoker1"));
|
||||
given(invoker1.getUrl()).willReturn(turl.setPort(1).addParameter("name", "invoker1"));
|
||||
|
||||
given(invoker2.isAvailable()).willReturn(true);
|
||||
given(invoker2.getInterface()).willReturn(IHelloService.class);
|
||||
given(invoker2.getUrl()).willReturn(turl.addParameter("name", "invoker2"));
|
||||
given(invoker2.getUrl()).willReturn(turl.setPort(2).addParameter("name", "invoker2"));
|
||||
|
||||
given(invoker3.isAvailable()).willReturn(false);
|
||||
given(invoker3.getInterface()).willReturn(IHelloService.class);
|
||||
given(invoker3.getUrl()).willReturn(turl.addParameter("name", "invoker3"));
|
||||
given(invoker3.getUrl()).willReturn(turl.setPort(3).addParameter("name", "invoker3"));
|
||||
|
||||
given(invoker4.isAvailable()).willReturn(true);
|
||||
given(invoker4.getInterface()).willReturn(IHelloService.class);
|
||||
given(invoker4.getUrl()).willReturn(turl.addParameter("name", "invoker4"));
|
||||
given(invoker4.getUrl()).willReturn(turl.setPort(4).addParameter("name", "invoker4"));
|
||||
|
||||
given(invoker5.isAvailable()).willReturn(false);
|
||||
given(invoker5.getInterface()).willReturn(IHelloService.class);
|
||||
given(invoker5.getUrl()).willReturn(turl.addParameter("name", "invoker5"));
|
||||
given(invoker5.getUrl()).willReturn(turl.setPort(5).addParameter("name", "invoker5"));
|
||||
|
||||
given(mockedInvoker1.isAvailable()).willReturn(false);
|
||||
given(mockedInvoker1.getInterface()).willReturn(IHelloService.class);
|
||||
|
|
@ -132,6 +132,31 @@ public class AbstractClusterInvokerTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBindingAttachment() {
|
||||
final String attachKey = "attach";
|
||||
final String attachValue = "value";
|
||||
|
||||
// setup attachment
|
||||
RpcContext.getContext().setAttachment(attachKey, attachValue);
|
||||
Map<String, String> attachments = RpcContext.getContext().getAttachments();
|
||||
Assert.assertTrue("set attachment failed!", attachments != null && attachments.size() == 1);
|
||||
|
||||
cluster = new AbstractClusterInvoker(dic) {
|
||||
@Override
|
||||
protected Result doInvoke(Invocation invocation, List invokers, LoadBalance loadbalance)
|
||||
throws RpcException {
|
||||
// attachment will be bind to invocation
|
||||
String value = invocation.getAttachment(attachKey);
|
||||
Assert.assertTrue("binding attachment failed!", value != null && value.equals(attachValue));
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// invoke
|
||||
cluster.invoke(invocation);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelect_Invokersize0() throws Exception {
|
||||
{
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ public class FailoverClusterInvokerTest {
|
|||
* then we should reselect from the latest invokers before retry.
|
||||
*/
|
||||
@Test
|
||||
public void testInvokerDestoryAndReList() {
|
||||
public void testInvokerDestroyAndReList() {
|
||||
final URL url = URL.valueOf("test://localhost/" + Demo.class.getName() + "?loadbalance=roundrobin&retries=" + retries);
|
||||
RpcException exception = new RpcException(RpcException.TIMEOUT_EXCEPTION);
|
||||
MockInvoker<Demo> invoker1 = new MockInvoker<Demo>(Demo.class, url);
|
||||
|
|
|
|||
|
|
@ -19,25 +19,29 @@ package com.alibaba.dubbo.rpc.cluster.support;
|
|||
import com.alibaba.dubbo.common.URL;
|
||||
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.RpcInvocation;
|
||||
import com.alibaba.dubbo.rpc.RpcResult;
|
||||
import com.alibaba.dubbo.rpc.cluster.Directory;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* ForkingClusterInvokerTest
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ForkingClusterInvokerTest {
|
||||
|
|
@ -71,6 +75,7 @@ public class ForkingClusterInvokerTest {
|
|||
invokers.add(invoker3);
|
||||
|
||||
}
|
||||
|
||||
private void resetInvokerToException() {
|
||||
given(invoker1.invoke(invocation)).willThrow(new RuntimeException());
|
||||
given(invoker1.getUrl()).willReturn(url);
|
||||
|
|
@ -106,7 +111,7 @@ public class ForkingClusterInvokerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testInvokeExceptoin() {
|
||||
public void testInvokeException() {
|
||||
resetInvokerToException();
|
||||
ForkingClusterInvoker<ForkingClusterInvokerTest> invoker = new ForkingClusterInvoker<ForkingClusterInvokerTest>(
|
||||
dic);
|
||||
|
|
@ -115,20 +120,44 @@ public class ForkingClusterInvokerTest {
|
|||
invoker.invoke(invocation);
|
||||
Assert.fail();
|
||||
} catch (RpcException expected) {
|
||||
Assert.assertTrue(expected.getMessage().contains("Failed to forking invoke provider"));
|
||||
assertThat(expected.getMessage().contains("Failed to forking invoke provider"), is(true));
|
||||
assertFalse(expected.getCause() instanceof RpcException);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClearRpcContext() {
|
||||
resetInvokerToException();
|
||||
ForkingClusterInvoker<ForkingClusterInvokerTest> invoker = new ForkingClusterInvoker<ForkingClusterInvokerTest>(
|
||||
dic);
|
||||
|
||||
String attachKey = "attach";
|
||||
String attachValue = "value";
|
||||
|
||||
RpcContext.getContext().setAttachment(attachKey, attachValue);
|
||||
|
||||
Map<String, String> attachments = RpcContext.getContext().getAttachments();
|
||||
assertThat("set attachment failed!", attachments != null && attachments.size() == 1, is(true));
|
||||
try {
|
||||
invoker.invoke(invocation);
|
||||
Assert.fail();
|
||||
} catch (RpcException expected) {
|
||||
assertThat(expected.getMessage().contains("Failed to forking invoke provider"), is(true));
|
||||
assertFalse(expected.getCause() instanceof RpcException);
|
||||
}
|
||||
Map<String, String> afterInvoke = RpcContext.getContext().getAttachments();
|
||||
assertThat(afterInvoke != null && afterInvoke.size() == 0, is(true));
|
||||
}
|
||||
|
||||
@Test()
|
||||
public void testInvokeNoExceptoin() {
|
||||
public void testInvokeNoException() {
|
||||
|
||||
resetInvokerToNoException();
|
||||
|
||||
ForkingClusterInvoker<ForkingClusterInvokerTest> invoker = new ForkingClusterInvoker<ForkingClusterInvokerTest>(
|
||||
dic);
|
||||
Result ret = invoker.invoke(invocation);
|
||||
Assert.assertSame(result, ret);
|
||||
assertSame(result, ret);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
script=com.alibaba.dubbo.rpc.cluster.router.script.ScriptRouterFactory
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
<parent>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-parent</artifactId>
|
||||
<version>2.6.3-SNAPSHOT</version>
|
||||
<version>2.6.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>dubbo-common</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
|
@ -50,7 +50,6 @@
|
|||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>hessian-lite</artifactId>
|
||||
<version>3.2.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
|
|
|
|||
|
|
@ -599,6 +599,10 @@ public class Constants {
|
|||
|
||||
public static final String EXECUTOR_SERVICE_COMPONENT_KEY = ExecutorService.class.getName();
|
||||
|
||||
public static final String SHARE_EXECUTOR_KEY = "share.threadpool";
|
||||
|
||||
public static final String SHARED_CONSUMER_EXECUTOR_PORT = "consumer.executor.port";
|
||||
|
||||
public static final String GENERIC_SERIALIZATION_NATIVE_JAVA = "nativejava";
|
||||
|
||||
public static final String GENERIC_SERIALIZATION_DEFAULT = "true";
|
||||
|
|
@ -635,8 +639,38 @@ public class Constants {
|
|||
|
||||
public static final String MULTICAST = "multicast";
|
||||
|
||||
/*
|
||||
* private Constants(){ }
|
||||
*/
|
||||
public static final String SERVICE_IMPL_CLASS = "service.classimpl";
|
||||
|
||||
public static final String TAG_KEY = "dubbo.tag";
|
||||
|
||||
public static final String FORCE_USE_TAG = "dubbo.force.tag";
|
||||
|
||||
public static final String TELNET = "telnet";
|
||||
|
||||
public static final String BACKLOG_KEY = "backlog";
|
||||
|
||||
public static final int DEFAULT_BACKLOG = 1024;
|
||||
|
||||
public static final String DOT_REGEX = "\\.";
|
||||
|
||||
public static final String UNDERLINE_SEPARATOR = "_";
|
||||
|
||||
public static final String CLASS_DESERIALIZE_BLOCK_ALL = "dubbo.security.serialize.blockAllClassExceptAllow";
|
||||
|
||||
public static final String CLASS_DESERIALIZE_ALLOWED_LIST = "dubbo.security.serialize.allowedClassList";
|
||||
|
||||
public static final String CLASS_DESERIALIZE_BLOCKED_LIST = "dubbo.security.serialize.blockedClassList";
|
||||
|
||||
public static final String ENABLE_NATIVE_JAVA_GENERIC_SERIALIZE = "dubbo.security.serialize.generic.native-java-enable";
|
||||
|
||||
public static final String SERIALIZE_BLOCKED_LIST_FILE_PATH = "security/serialize.blockedlist";
|
||||
|
||||
public static final String DEFAULT_VERSION = "0.0.0";
|
||||
|
||||
public static final String SERIALIZATION_SECURITY_CHECK_KEY = "serialization.security.check";
|
||||
|
||||
public static final String SERIALIZATION_ID_KEY = "serialization_id";
|
||||
|
||||
public static final String INVOCATION_KEY = "invocation";
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -204,6 +204,13 @@ public final class URL implements Serializable {
|
|||
}
|
||||
url = url.substring(0, i);
|
||||
}
|
||||
|
||||
// ignore the url content following '#'
|
||||
int poundIndex = url.indexOf('#');
|
||||
if (poundIndex != -1) {
|
||||
url = url.substring(0, poundIndex);
|
||||
}
|
||||
|
||||
i = url.indexOf("://");
|
||||
if (i >= 0) {
|
||||
if (i == 0) throw new IllegalStateException("url missing protocol: \"" + url + "\"");
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ import java.util.Set;
|
|||
public final class Version {
|
||||
private static final Logger logger = LoggerFactory.getLogger(Version.class);
|
||||
|
||||
// Dubbo RPC protocol version
|
||||
// Dubbo RPC protocol version, for compatibility, it must not be between 2.0.10 ~ 2.6.2
|
||||
public static final String DEFAULT_DUBBO_PROTOCOL_VERSION = "2.0.2";
|
||||
// Dubbo implementation version, usually is jar version.
|
||||
private static final String VERSION = getVersion(Version.class, "");
|
||||
|
|
@ -43,7 +43,7 @@ public final class Version {
|
|||
* For protocol compatibility purpose.
|
||||
* Because {@link #isSupportResponseAttatchment} is checked for every call, int compare expect to has higher performance than string.
|
||||
*/
|
||||
private static final int LOWEST_VERSION_FOR_RESPONSE_ATTATCHMENT = 202; // 2.0.2
|
||||
private static final int LOWEST_VERSION_FOR_RESPONSE_ATTATCHMENT = 20002; // 2.0.2
|
||||
private static final Map<String, Integer> VERSION2INT = new HashMap<String, Integer>();
|
||||
|
||||
static {
|
||||
|
|
@ -66,7 +66,13 @@ public final class Version {
|
|||
if (version == null || version.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
return getIntVersion(version) >= LOWEST_VERSION_FOR_RESPONSE_ATTATCHMENT;
|
||||
// for previous dubbo version(2.0.10/020010~2.6.2/020602), this version is the jar's version, so they need to be ignore
|
||||
int iVersion = getIntVersion(version);
|
||||
if (iVersion >= 20010 && iVersion <= 20602) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return iVersion >= LOWEST_VERSION_FOR_RESPONSE_ATTATCHMENT;
|
||||
}
|
||||
|
||||
public static int getIntVersion(String version) {
|
||||
|
|
@ -82,12 +88,31 @@ public final class Version {
|
|||
int v = 0;
|
||||
String[] vArr = version.split("\\.");
|
||||
int len = vArr.length;
|
||||
for (int i = 1; i <= len; i++) {
|
||||
v += Integer.parseInt(vArr[len - i]) * Math.pow(10, i - 1);
|
||||
for (int i = 0; i < len; i++) {
|
||||
v += Integer.parseInt(getDigital(vArr[i])) * Math.pow(10, (len - i - 1) * 2);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
private static String getDigital(String v) {
|
||||
int index = 0;
|
||||
for (int i = 0; i < v.length(); i++) {
|
||||
char c = v.charAt(i);
|
||||
if (Character.isDigit(c)) {
|
||||
if (i == v.length() - 1) {
|
||||
index = i + 1;
|
||||
} else {
|
||||
index = i;
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return v.substring(0, index);
|
||||
}
|
||||
|
||||
private static boolean hasResource(String path) {
|
||||
try {
|
||||
return Version.class.getClassLoader().getResource(path) != null;
|
||||
|
|
@ -177,4 +202,4 @@ public final class Version {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import com.alibaba.dubbo.common.logger.Logger;
|
|||
import com.alibaba.dubbo.common.logger.LoggerFactory;
|
||||
import com.alibaba.dubbo.common.utils.LogHelper;
|
||||
import com.alibaba.dubbo.common.utils.ReflectUtils;
|
||||
import com.alibaba.dubbo.common.utils.SerializeClassChecker;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
|
|
@ -439,6 +440,7 @@ public final class JavaBeanSerializeUtil {
|
|||
if (isReferenceType(name)) {
|
||||
name = name.substring(1, name.length() - 1);
|
||||
}
|
||||
SerializeClassChecker.getInstance().validateClass(name);
|
||||
return Class.forName(name, false, loader);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
package com.alibaba.dubbo.common.concurrent;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
|
@ -66,7 +65,7 @@ import java.util.concurrent.RejectedExecutionException;
|
|||
* <ul>
|
||||
* <li>If they are returned from an {@code ExecutorService}, convert that
|
||||
* service to a {@link ListeningExecutorService}, usually by calling {@link
|
||||
* MoreExecutors#listeningDecorator(ExecutorService)
|
||||
* MoreExecutors#listeningDecorator(java.util.concurrent.ExecutorService)
|
||||
* MoreExecutors.listeningDecorator}. (Custom executors may find it more
|
||||
* convenient to use {@link ListenableFutureTask} directly.)
|
||||
* <li>If they are manually filled in by a call to {@link FutureTask#set} or a
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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 com.alibaba.dubbo.common.extension;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
public @interface DisableInject {
|
||||
}
|
||||
|
|
@ -190,10 +190,10 @@ public class ExtensionLoader<T> {
|
|||
String name = entry.getKey();
|
||||
Activate activate = entry.getValue();
|
||||
if (isMatchGroup(group, activate.group())) {
|
||||
T ext = getExtension(name);
|
||||
if (!names.contains(name)
|
||||
&& !names.contains(Constants.REMOVE_VALUE_PREFIX + name)
|
||||
&& isActive(activate, url)) {
|
||||
T ext = getExtension(name);
|
||||
exts.add(ext);
|
||||
}
|
||||
}
|
||||
|
|
@ -515,6 +515,12 @@ public class ExtensionLoader<T> {
|
|||
if (method.getName().startsWith("set")
|
||||
&& method.getParameterTypes().length == 1
|
||||
&& Modifier.isPublic(method.getModifiers())) {
|
||||
/**
|
||||
* Check {@link DisableInject} to see if we need auto injection for this property
|
||||
*/
|
||||
if (method.getAnnotation(DisableInject.class) != null) {
|
||||
continue;
|
||||
}
|
||||
Class<?> pt = method.getParameterTypes()[0];
|
||||
try {
|
||||
String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
|
||||
|
|
|
|||
|
|
@ -1,86 +1,94 @@
|
|||
/*
|
||||
* 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 com.alibaba.dubbo.common.extension.support;
|
||||
|
||||
import com.alibaba.dubbo.common.extension.Activate;
|
||||
import com.alibaba.dubbo.common.extension.ExtensionLoader;
|
||||
import com.alibaba.dubbo.common.extension.SPI;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* OrderComparetor
|
||||
*/
|
||||
public class ActivateComparator implements Comparator<Object> {
|
||||
|
||||
public static final Comparator<Object> COMPARATOR = new ActivateComparator();
|
||||
|
||||
@Override
|
||||
public int compare(Object o1, Object o2) {
|
||||
if (o1 == null && o2 == null) {
|
||||
return 0;
|
||||
}
|
||||
if (o1 == null) {
|
||||
return -1;
|
||||
}
|
||||
if (o2 == null) {
|
||||
return 1;
|
||||
}
|
||||
if (o1.equals(o2)) {
|
||||
return 0;
|
||||
}
|
||||
Activate a1 = o1.getClass().getAnnotation(Activate.class);
|
||||
Activate a2 = o2.getClass().getAnnotation(Activate.class);
|
||||
if ((a1.before().length > 0 || a1.after().length > 0
|
||||
|| a2.before().length > 0 || a2.after().length > 0)
|
||||
&& o1.getClass().getInterfaces().length > 0
|
||||
&& o1.getClass().getInterfaces()[0].isAnnotationPresent(SPI.class)) {
|
||||
ExtensionLoader<?> extensionLoader = ExtensionLoader.getExtensionLoader(o1.getClass().getInterfaces()[0]);
|
||||
if (a1.before().length > 0 || a1.after().length > 0) {
|
||||
String n2 = extensionLoader.getExtensionName(o2.getClass());
|
||||
for (String before : a1.before()) {
|
||||
if (before.equals(n2)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
for (String after : a1.after()) {
|
||||
if (after.equals(n2)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (a2.before().length > 0 || a2.after().length > 0) {
|
||||
String n1 = extensionLoader.getExtensionName(o1.getClass());
|
||||
for (String before : a2.before()) {
|
||||
if (before.equals(n1)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
for (String after : a2.after()) {
|
||||
if (after.equals(n1)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int n1 = a1 == null ? 0 : a1.order();
|
||||
int n2 = a2 == null ? 0 : a2.order();
|
||||
// never return 0 even if n1 equals n2, otherwise, o1 and o2 will override each other in collection like HashSet
|
||||
return n1 > n2 ? 1 : -1;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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 com.alibaba.dubbo.common.extension.support;
|
||||
|
||||
import com.alibaba.dubbo.common.extension.Activate;
|
||||
import com.alibaba.dubbo.common.extension.ExtensionLoader;
|
||||
import com.alibaba.dubbo.common.extension.SPI;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* OrderComparetor
|
||||
*/
|
||||
public class ActivateComparator implements Comparator<Object> {
|
||||
|
||||
public static final Comparator<Object> COMPARATOR = new ActivateComparator();
|
||||
|
||||
@Override
|
||||
public int compare(Object o1, Object o2) {
|
||||
if (o1 == null && o2 == null) {
|
||||
return 0;
|
||||
}
|
||||
if (o1 == null) {
|
||||
return -1;
|
||||
}
|
||||
if (o2 == null) {
|
||||
return 1;
|
||||
}
|
||||
if (o1.equals(o2)) {
|
||||
return 0;
|
||||
}
|
||||
Activate a1 = o1.getClass().getAnnotation(Activate.class);
|
||||
Activate a2 = o2.getClass().getAnnotation(Activate.class);
|
||||
Class<?> spiClass = null;
|
||||
if (o1.getClass().getInterfaces().length > 0) {
|
||||
for (Class<?> item : o1.getClass().getInterfaces()) {
|
||||
if (item.isAnnotationPresent(SPI.class)) {
|
||||
spiClass = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((a1.before().length > 0 || a1.after().length > 0
|
||||
|| a2.before().length > 0 || a2.after().length > 0)
|
||||
&& spiClass != null) {
|
||||
ExtensionLoader<?> extensionLoader = ExtensionLoader.getExtensionLoader(spiClass);
|
||||
if (a1.before().length > 0 || a1.after().length > 0) {
|
||||
String n2 = extensionLoader.getExtensionName(o2.getClass());
|
||||
for (String before : a1.before()) {
|
||||
if (before.equals(n2)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
for (String after : a1.after()) {
|
||||
if (after.equals(n2)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (a2.before().length > 0 || a2.after().length > 0) {
|
||||
String n1 = extensionLoader.getExtensionName(o1.getClass());
|
||||
for (String before : a2.before()) {
|
||||
if (before.equals(n1)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
for (String after : a2.after()) {
|
||||
if (after.equals(n1)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int n1 = a1 == null ? 0 : a1.order();
|
||||
int n2 = a2 == null ? 0 : a2.order();
|
||||
// never return 0 even if n1 equals n2, otherwise, o1 and o2 will override each other in collection like HashSet
|
||||
return n1 > n2 ? 1 : -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,11 @@ public class LoadStatusChecker implements StatusChecker {
|
|||
try {
|
||||
Method method = OperatingSystemMXBean.class.getMethod("getSystemLoadAverage", new Class<?>[0]);
|
||||
load = (Double) method.invoke(operatingSystemMXBean, new Object[0]);
|
||||
if (load == -1) {
|
||||
com.sun.management.OperatingSystemMXBean bean =
|
||||
(com.sun.management.OperatingSystemMXBean) operatingSystemMXBean;
|
||||
load = bean.getSystemCpuLoad();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
load = -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,12 +48,12 @@ public class SimpleDataStore implements DataStore {
|
|||
|
||||
@Override
|
||||
public void put(String componentName, String key, Object value) {
|
||||
Map<String, Object> componentData = data.get(componentName);
|
||||
ConcurrentMap<String, Object> componentData = data.get(componentName);
|
||||
if (null == componentData) {
|
||||
data.putIfAbsent(componentName, new ConcurrentHashMap<String, Object>());
|
||||
componentData = data.get(componentName);
|
||||
}
|
||||
componentData.put(key, value);
|
||||
componentData.putIfAbsent(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -79,9 +79,18 @@ public class CompatibleTypeUtils {
|
|||
return new Byte(string);
|
||||
} else if (type == Boolean.class || type == boolean.class) {
|
||||
return new Boolean(string);
|
||||
} else if (type == Date.class) {
|
||||
} else if (type == Date.class || type == java.sql.Date.class || type == java.sql.Timestamp.class || type == java.sql.Time.class) {
|
||||
try {
|
||||
return new SimpleDateFormat(DATE_FORMAT).parse((String) value);
|
||||
Date date = new SimpleDateFormat(DATE_FORMAT).parse((String) value);
|
||||
if (type == java.sql.Date.class) {
|
||||
return new java.sql.Date(date.getTime());
|
||||
} else if (type == java.sql.Timestamp.class) {
|
||||
return new java.sql.Timestamp(date.getTime());
|
||||
} else if (type == java.sql.Time.class) {
|
||||
return new java.sql.Time(date.getTime());
|
||||
} else {
|
||||
return date;
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
throw new IllegalStateException("Failed to parse date " + value + " by format " + DATE_FORMAT + ", cause: " + e.getMessage(), e);
|
||||
}
|
||||
|
|
@ -91,6 +100,19 @@ public class CompatibleTypeUtils {
|
|||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
} else if (char[].class.equals(type)) {
|
||||
// Process string to char array for generic invoke
|
||||
// See
|
||||
// - https://github.com/apache/incubator-dubbo/issues/2003
|
||||
if (string == null) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
int len = string.length();
|
||||
char[] chars = new char[len];
|
||||
string.getChars(0, len, chars, 0);
|
||||
return chars;
|
||||
}
|
||||
}
|
||||
} else if (value instanceof Number) {
|
||||
Number number = (Number) value;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import com.alibaba.dubbo.common.extension.ExtensionLoader;
|
|||
import com.alibaba.dubbo.common.logger.Logger;
|
||||
import com.alibaba.dubbo.common.logger.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.lang.management.ManagementFactory;
|
||||
|
|
@ -217,7 +218,7 @@ public class ConfigUtils {
|
|||
*/
|
||||
public static Properties loadProperties(String fileName, boolean allowMultiFile, boolean optional) {
|
||||
Properties properties = new Properties();
|
||||
if (fileName.startsWith("/")) {
|
||||
if (checkFileNameExist(fileName)) {
|
||||
try {
|
||||
FileInputStream input = new FileInputStream(fileName);
|
||||
try {
|
||||
|
|
@ -291,6 +292,16 @@ public class ConfigUtils {
|
|||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the fileName can be found in filesystem
|
||||
* @param fileName
|
||||
* @return
|
||||
*/
|
||||
private static boolean checkFileNameExist(String fileName) {
|
||||
File file = new File(fileName);
|
||||
return file != null && file.exists() ? true : false;
|
||||
}
|
||||
|
||||
public static int getPid() {
|
||||
if (PID < 0) {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* 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 com.alibaba.dubbo.common.utils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class LFUCache<K, V> {
|
||||
|
||||
private Map<K, CacheNode<K, V>> map;
|
||||
private CacheDeque<K, V>[] freqTable;
|
||||
|
||||
private final int capacity;
|
||||
private int evictionCount;
|
||||
private int curSize = 0;
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
private static final int DEFAULT_INITIAL_CAPACITY = 1000;
|
||||
|
||||
private static final float DEFAULT_EVICTION_FACTOR = 0.75f;
|
||||
|
||||
public LFUCache() {
|
||||
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_EVICTION_FACTOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and initializes cache with specified capacity and eviction
|
||||
* factor. Unacceptable parameter values followed with
|
||||
* {@link IllegalArgumentException}.
|
||||
*
|
||||
* @param maxCapacity cache max capacity
|
||||
* @param evictionFactor cache proceedEviction factor
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public LFUCache(final int maxCapacity, final float evictionFactor) {
|
||||
if (maxCapacity <= 0) {
|
||||
throw new IllegalArgumentException("Illegal initial capacity: " +
|
||||
maxCapacity);
|
||||
}
|
||||
boolean factorInRange = evictionFactor <= 1 && evictionFactor > 0;
|
||||
if (!factorInRange || Float.isNaN(evictionFactor)) {
|
||||
throw new IllegalArgumentException("Illegal eviction factor value:"
|
||||
+ evictionFactor);
|
||||
}
|
||||
this.capacity = maxCapacity;
|
||||
this.evictionCount = (int) (capacity * evictionFactor);
|
||||
this.map = new HashMap<K, CacheNode<K, V>>();
|
||||
this.freqTable = new CacheDeque[capacity + 1];
|
||||
for (int i = 0; i <= capacity; i++) {
|
||||
freqTable[i] = new CacheDeque<K, V>();
|
||||
}
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
freqTable[i].nextDeque = freqTable[i + 1];
|
||||
}
|
||||
freqTable[capacity].nextDeque = freqTable[capacity];
|
||||
}
|
||||
|
||||
public int getCapacity() {
|
||||
return capacity;
|
||||
}
|
||||
|
||||
public V put(final K key, final V value) {
|
||||
CacheNode<K, V> node;
|
||||
lock.lock();
|
||||
try {
|
||||
node = map.get(key);
|
||||
if (node != null) {
|
||||
CacheNode.withdrawNode(node);
|
||||
node.value = value;
|
||||
freqTable[0].addLastNode(node);
|
||||
map.put(key, node);
|
||||
} else {
|
||||
node = freqTable[0].addLast(key, value);
|
||||
map.put(key, node);
|
||||
curSize++;
|
||||
if (curSize > capacity) {
|
||||
proceedEviction();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
return node.value;
|
||||
}
|
||||
|
||||
public V remove(final K key) {
|
||||
CacheNode<K, V> node = null;
|
||||
lock.lock();
|
||||
try {
|
||||
if (map.containsKey(key)) {
|
||||
node = map.remove(key);
|
||||
if (node != null) {
|
||||
CacheNode.withdrawNode(node);
|
||||
}
|
||||
curSize--;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
return (node != null) ? node.value : null;
|
||||
}
|
||||
|
||||
public V get(final K key) {
|
||||
CacheNode<K, V> node = null;
|
||||
lock.lock();
|
||||
try {
|
||||
if (map.containsKey(key)) {
|
||||
node = map.get(key);
|
||||
CacheNode.withdrawNode(node);
|
||||
node.owner.nextDeque.addLastNode(node);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
return (node != null) ? node.value : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evicts less frequently used elements corresponding to eviction factor,
|
||||
* specified at instantiation step.
|
||||
*
|
||||
* @return number of evicted elements
|
||||
*/
|
||||
private int proceedEviction() {
|
||||
int targetSize = capacity - evictionCount;
|
||||
int evictedElements = 0;
|
||||
|
||||
FREQ_TABLE_ITER_LOOP:
|
||||
for (int i = 0; i <= capacity; i++) {
|
||||
CacheNode<K, V> node;
|
||||
while (!freqTable[i].isEmpty()) {
|
||||
node = freqTable[i].pollFirst();
|
||||
remove(node.key);
|
||||
if (targetSize >= curSize) {
|
||||
break FREQ_TABLE_ITER_LOOP;
|
||||
}
|
||||
evictedElements++;
|
||||
}
|
||||
}
|
||||
return evictedElements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns cache current size.
|
||||
*
|
||||
* @return cache size
|
||||
*/
|
||||
public int getSize() {
|
||||
return curSize;
|
||||
}
|
||||
|
||||
static class CacheNode<K, V> {
|
||||
|
||||
CacheNode<K, V> prev;
|
||||
CacheNode<K, V> next;
|
||||
K key;
|
||||
V value;
|
||||
CacheDeque<K, V> owner;
|
||||
|
||||
CacheNode() {
|
||||
}
|
||||
|
||||
CacheNode(final K key, final V value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method takes specified node and reattaches it neighbors nodes
|
||||
* links to each other, so specified node will no longer tied with them.
|
||||
* Returns united node, returns null if argument is null.
|
||||
*
|
||||
* @param node note to retrieve
|
||||
* @param <K> key
|
||||
* @param <V> value
|
||||
* @return retrieved node
|
||||
*/
|
||||
static <K, V> CacheNode<K, V> withdrawNode(
|
||||
final CacheNode<K, V> node) {
|
||||
if (node != null && node.prev != null) {
|
||||
node.prev.next = node.next;
|
||||
if (node.next != null) {
|
||||
node.next.prev = node.prev;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom deque implementation of LIFO type. Allows to place element at top
|
||||
* of deque and poll very last added elements. An arbitrary node from the
|
||||
* deque can be removed with {@link CacheNode#withdrawNode(CacheNode)}
|
||||
* method.
|
||||
*
|
||||
* @param <K> key
|
||||
* @param <V> value
|
||||
*/
|
||||
static class CacheDeque<K, V> {
|
||||
|
||||
CacheNode<K, V> last;
|
||||
CacheNode<K, V> first;
|
||||
CacheDeque<K, V> nextDeque;
|
||||
|
||||
/**
|
||||
* Constructs list and initializes last and first pointers.
|
||||
*/
|
||||
CacheDeque() {
|
||||
last = new CacheNode<K, V>();
|
||||
first = new CacheNode<K, V>();
|
||||
last.next = first;
|
||||
first.prev = last;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the node with specified key and value at the end of the deque
|
||||
* and returns node.
|
||||
*
|
||||
* @param key key
|
||||
* @param value value
|
||||
* @return added node
|
||||
*/
|
||||
CacheNode<K, V> addLast(final K key, final V value) {
|
||||
CacheNode<K, V> node = new CacheNode<K, V>(key, value);
|
||||
node.owner = this;
|
||||
node.next = last.next;
|
||||
node.prev = last;
|
||||
node.next.prev = node;
|
||||
last.next = node;
|
||||
return node;
|
||||
}
|
||||
|
||||
CacheNode<K, V> addLastNode(final CacheNode<K, V> node) {
|
||||
node.owner = this;
|
||||
node.next = last.next;
|
||||
node.prev = last;
|
||||
node.next.prev = node;
|
||||
last.next = node;
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves and removes the first node of this deque.
|
||||
*
|
||||
* @return removed node
|
||||
*/
|
||||
CacheNode<K, V> pollFirst() {
|
||||
CacheNode<K, V> node = null;
|
||||
if (first.prev != last) {
|
||||
node = first.prev;
|
||||
first.prev = node.prev;
|
||||
first.prev.next = first;
|
||||
node.prev = null;
|
||||
node.next = null;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if link to the last node points to link to the first node.
|
||||
*
|
||||
* @return is deque empty
|
||||
*/
|
||||
boolean isEmpty() {
|
||||
return last.next == first;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -21,8 +21,11 @@ import com.alibaba.dubbo.common.logger.Logger;
|
|||
import com.alibaba.dubbo.common.logger.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.UnknownHostException;
|
||||
|
|
@ -190,7 +193,7 @@ public class NetUtils {
|
|||
return localAddress;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
logger.warn("Failed to retrieving ip address, " + e.getMessage(), e);
|
||||
logger.warn(e);
|
||||
}
|
||||
try {
|
||||
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
|
||||
|
|
@ -207,19 +210,18 @@ public class NetUtils {
|
|||
return address;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
logger.warn("Failed to retrieving ip address, " + e.getMessage(), e);
|
||||
logger.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
logger.warn("Failed to retrieving ip address, " + e.getMessage(), e);
|
||||
logger.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
logger.warn("Failed to retrieving ip address, " + e.getMessage(), e);
|
||||
logger.warn(e);
|
||||
}
|
||||
logger.error("Could not get local host ip address, will use 127.0.0.1 instead.");
|
||||
return localAddress;
|
||||
}
|
||||
|
||||
|
|
@ -285,4 +287,34 @@ public class NetUtils {
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
public static void joinMulticastGroup(MulticastSocket multicastSocket, InetAddress multicastAddress) throws IOException {
|
||||
setInterface(multicastSocket, multicastAddress instanceof Inet6Address);
|
||||
multicastSocket.setLoopbackMode(false);
|
||||
multicastSocket.joinGroup(multicastAddress);
|
||||
}
|
||||
|
||||
public static void setInterface(MulticastSocket multicastSocket, boolean preferIpv6) throws IOException {
|
||||
boolean interfaceSet = false;
|
||||
Enumeration interfaces = NetworkInterface.getNetworkInterfaces();
|
||||
while (interfaces.hasMoreElements()) {
|
||||
NetworkInterface i = (NetworkInterface) interfaces.nextElement();
|
||||
Enumeration addresses = i.getInetAddresses();
|
||||
while (addresses.hasMoreElements()) {
|
||||
InetAddress address = (InetAddress) addresses.nextElement();
|
||||
if (preferIpv6 && address instanceof Inet6Address) {
|
||||
multicastSocket.setInterface(address);
|
||||
interfaceSet = true;
|
||||
break;
|
||||
} else if (!preferIpv6 && address instanceof Inet4Address) {
|
||||
multicastSocket.setInterface(address);
|
||||
interfaceSet = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (interfaceSet) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -371,6 +371,7 @@ public class PojoUtils {
|
|||
if (pojo instanceof Map<?, ?> && type != null) {
|
||||
Object className = ((Map<Object, Object>) pojo).get("class");
|
||||
if (className instanceof String) {
|
||||
SerializeClassChecker.getInstance().validateClass((String) className);
|
||||
try {
|
||||
type = ClassHelper.forName((String) className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
|
|
@ -381,8 +382,10 @@ public class PojoUtils {
|
|||
// special logic for enum
|
||||
if (type.isEnum()) {
|
||||
Object name = ((Map<Object, Object>) pojo).get("name");
|
||||
if (name != null) {
|
||||
return Enum.valueOf((Class<Enum>) type, name.toString());
|
||||
if (!(name instanceof String)) {
|
||||
throw new IllegalArgumentException("`name` filed should be string!");
|
||||
} else {
|
||||
return Enum.valueOf((Class<Enum>) type, (String) name);
|
||||
}
|
||||
}
|
||||
Map<Object, Object> map;
|
||||
|
|
@ -454,7 +457,7 @@ public class PojoUtils {
|
|||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("Failed to set pojo " + dest.getClass().getSimpleName() + " property " + name
|
||||
+ " value " + value + "(" + value.getClass() + "), cause: " + e.getMessage(), e);
|
||||
+ " value " + value.getClass() + ", cause: " + e.getMessage(), e);
|
||||
}
|
||||
} else if (field != null) {
|
||||
value = realize0(value, field.getType(), field.getGenericType(), history);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* 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 com.alibaba.dubbo.common.utils;
|
||||
|
||||
import com.alibaba.dubbo.common.Constants;
|
||||
import com.alibaba.dubbo.common.logger.Logger;
|
||||
import com.alibaba.dubbo.common.logger.LoggerFactory;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.InvalidClassException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectStreamClass;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class SerialDetector extends ObjectInputStream {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SerialDetector.class);
|
||||
|
||||
private static final BlacklistConfiguration configuration = new BlacklistConfiguration();
|
||||
|
||||
/**
|
||||
* Wrapper Constructor.
|
||||
*
|
||||
* @param inputStream The original InputStream, used by your service to receive serialized objects
|
||||
* @throws java.io.IOException File I/O exception
|
||||
* @throws IllegalStateException Invalid configuration exception
|
||||
*/
|
||||
public SerialDetector(final InputStream inputStream) throws IOException {
|
||||
super(inputStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> resolveClass(final ObjectStreamClass serialInput) throws IOException, ClassNotFoundException {
|
||||
if (isClassInBlacklist(serialInput)) {
|
||||
if (!configuration.shouldCheck()) {
|
||||
// Reporting mode
|
||||
logger.info(String.format("Blacklist match: '%s'", serialInput.getName()));
|
||||
} else {
|
||||
// Blocking mode
|
||||
logger.error(String.format("Blocked by blacklist'. Match found for '%s'", serialInput.getName()));
|
||||
throw new InvalidClassException(serialInput.getName(), "Class blocked from deserialization (blacklist)");
|
||||
}
|
||||
}
|
||||
|
||||
return super.resolveClass(serialInput);
|
||||
}
|
||||
|
||||
public static boolean isClassInBlacklist(final ObjectStreamClass serialInput) {
|
||||
// Enforce SerialDetector's blacklist
|
||||
Iterable<Pattern> blacklistIterable = configuration.blacklist();
|
||||
if (blacklistIterable == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean inBlacklist = false;
|
||||
for (Pattern blackPattern : blacklistIterable) {
|
||||
Matcher blackMatcher = blackPattern.matcher(serialInput.getName());
|
||||
if (blackMatcher.find()) {
|
||||
inBlacklist = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return inBlacklist;
|
||||
}
|
||||
|
||||
public static boolean shouldCheck() {
|
||||
return configuration.shouldCheck();
|
||||
}
|
||||
|
||||
static final class BlacklistConfiguration {
|
||||
private static final String DUBBO_SECURITY_SERIALIZATION_CHECK = "dubbo.security.serialization.check";
|
||||
private static final String DUBBO_SECURITY_SERIALIZATION_BLACKLIST = "dubbo.security.serialization.blacklist";
|
||||
private static final String DUBBO_SECURITY_SERIALIZATION_BLACKLIST_FILE = "dubbo.registry.serialization.blacklist.file";
|
||||
|
||||
private boolean check;
|
||||
private PatternList blacklistPattern;
|
||||
|
||||
BlacklistConfiguration() {
|
||||
try {
|
||||
check = Boolean.parseBoolean(getSecurityProperty(DUBBO_SECURITY_SERIALIZATION_CHECK, "false"));
|
||||
String blacklist = getSecurityProperty(DUBBO_SECURITY_SERIALIZATION_BLACKLIST, "");
|
||||
if (StringUtils.isEmpty(blacklist)) {
|
||||
String blacklistFile = getSecurityProperty(DUBBO_SECURITY_SERIALIZATION_BLACKLIST_FILE, "");
|
||||
if (StringUtils.isNotEmpty(blacklistFile)) {
|
||||
blacklist = loadBlacklistFile(blacklistFile);
|
||||
}
|
||||
}
|
||||
if (StringUtils.isNotEmpty(blacklist)) {
|
||||
blacklistPattern = new PatternList(Constants.COMMA_SPLIT_PATTERN.split(blacklist));
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
logger.warn("Failed to initialize the Serialization Security Checker component!", t);
|
||||
}
|
||||
}
|
||||
|
||||
Iterable<Pattern> blacklist() {
|
||||
return blacklistPattern;
|
||||
}
|
||||
|
||||
boolean shouldCheck() {
|
||||
return check;
|
||||
}
|
||||
|
||||
private String loadBlacklistFile(String fileName) {
|
||||
StringBuilder blacklist = new StringBuilder();
|
||||
InputStream is = null;
|
||||
|
||||
File file = new File(fileName);
|
||||
if (file.exists()) {
|
||||
try {
|
||||
is = new FileInputStream(fileName);
|
||||
} catch (Throwable e) {
|
||||
logger.warn("Failed to load " + fileName + " file " + e.getMessage(), e);
|
||||
}
|
||||
} else {
|
||||
is = this.getClass().getClassLoader().getResourceAsStream(fileName);
|
||||
}
|
||||
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
String line = null;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (!line.startsWith("#") && StringUtils.isNotEmpty(line)) {
|
||||
blacklist.append(line);
|
||||
blacklist.append(",");
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
logger.warn("Failed to read from file " + fileName + e.getMessage(), e);
|
||||
}
|
||||
return blacklist.toString();
|
||||
}
|
||||
|
||||
private String getSecurityProperty(String key, String defaultValue) {
|
||||
String value = ConfigUtils.getSystemProperty(key);
|
||||
if (StringUtils.isEmpty(value)) {
|
||||
value = ConfigUtils.getProperty(key);
|
||||
}
|
||||
return StringUtils.isEmpty(value) ? defaultValue : value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static final class PatternList implements Iterable<Pattern> {
|
||||
private final Pattern[] patterns;
|
||||
|
||||
PatternList(final String... regExps) {
|
||||
|
||||
for (int i = 0; i < regExps.length; i++) {
|
||||
if (regExps[i] == null) {
|
||||
throw new IllegalStateException("Deserialization blacklist reg expression cannot be null!");
|
||||
}
|
||||
}
|
||||
|
||||
this.patterns = new Pattern[regExps.length];
|
||||
for (int i = 0; i < regExps.length; i++) {
|
||||
patterns[i] = Pattern.compile(regExps[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Pattern> iterator() {
|
||||
return new Iterator<Pattern>() {
|
||||
int index = 0;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return index < patterns.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pattern next() {
|
||||
return patterns[index++];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("remove");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(patterns);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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 com.alibaba.dubbo.common.utils;
|
||||
|
||||
import com.alibaba.dubbo.common.beanutil.JavaBeanSerializeUtil;
|
||||
import com.alibaba.dubbo.common.Constants;
|
||||
import com.alibaba.dubbo.common.logger.Logger;
|
||||
import com.alibaba.dubbo.common.logger.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class SerializeClassChecker {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SerializeClassChecker.class);
|
||||
|
||||
private static volatile SerializeClassChecker INSTANCE = null;
|
||||
|
||||
private final boolean BLOCK_ALL_CLASS_EXCEPT_ALLOW;
|
||||
private final Set<String> CLASS_DESERIALIZE_ALLOWED_SET = new ConcurrentHashSet<String>();
|
||||
private final Set<String> CLASS_DESERIALIZE_BLOCKED_SET = new ConcurrentHashSet<String>();
|
||||
|
||||
private final Object CACHE = new Object();
|
||||
private final LFUCache<String, Object> CLASS_ALLOW_LFU_CACHE = new LFUCache<String, Object>();
|
||||
private final LFUCache<String, Object> CLASS_BLOCK_LFU_CACHE = new LFUCache<String, Object>();
|
||||
|
||||
private final AtomicLong counter = new AtomicLong(0);
|
||||
|
||||
private SerializeClassChecker() {
|
||||
String blockAllClassExceptAllow = System.getProperty(Constants.CLASS_DESERIALIZE_BLOCK_ALL, "false");
|
||||
BLOCK_ALL_CLASS_EXCEPT_ALLOW = Boolean.parseBoolean(blockAllClassExceptAllow);
|
||||
|
||||
String[] lines;
|
||||
try {
|
||||
ClassLoader classLoader = JavaBeanSerializeUtil.class.getClassLoader();
|
||||
if (classLoader != null) {
|
||||
lines = IOUtils.readLines(classLoader.getResourceAsStream(Constants.SERIALIZE_BLOCKED_LIST_FILE_PATH));
|
||||
} else {
|
||||
lines = IOUtils.readLines(ClassLoader.getSystemResourceAsStream(Constants.SERIALIZE_BLOCKED_LIST_FILE_PATH));
|
||||
}
|
||||
for (String line : lines) {
|
||||
line = line.trim();
|
||||
if (StringUtils.isEmpty(line) || line.startsWith("#")) {
|
||||
continue;
|
||||
}
|
||||
CLASS_DESERIALIZE_BLOCKED_SET.add(line);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to load blocked class list! Will ignore default blocked list.", e);
|
||||
}
|
||||
|
||||
String allowedClassList = System.getProperty(Constants.CLASS_DESERIALIZE_ALLOWED_LIST, "").trim().toLowerCase(Locale.ROOT);
|
||||
String blockedClassList = System.getProperty(Constants.CLASS_DESERIALIZE_BLOCKED_LIST, "").trim().toLowerCase(Locale.ROOT);
|
||||
|
||||
if (StringUtils.isNotEmpty(allowedClassList)) {
|
||||
String[] classStrings = allowedClassList.trim().split(",");
|
||||
CLASS_DESERIALIZE_ALLOWED_SET.addAll(Arrays.asList(classStrings));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(blockedClassList)) {
|
||||
String[] classStrings = blockedClassList.trim().split(",");
|
||||
CLASS_DESERIALIZE_BLOCKED_SET.addAll(Arrays.asList(classStrings));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static SerializeClassChecker getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (SerializeClassChecker.class) {
|
||||
if (INSTANCE == null) {
|
||||
INSTANCE = new SerializeClassChecker();
|
||||
}
|
||||
}
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* For ut only
|
||||
*/
|
||||
@Deprecated
|
||||
protected static void clearInstance() {
|
||||
INSTANCE = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a class is in block list, using prefix match
|
||||
*
|
||||
* @throws IllegalArgumentException if class is blocked
|
||||
* @param name class name ( all are convert to lower case )
|
||||
*/
|
||||
public void validateClass(String name) {
|
||||
name = name.toLowerCase(Locale.ROOT);
|
||||
if (CACHE == CLASS_ALLOW_LFU_CACHE.get(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (CACHE == CLASS_BLOCK_LFU_CACHE.get(name)) {
|
||||
error(name);
|
||||
}
|
||||
|
||||
for (String allowedPrefix : CLASS_DESERIALIZE_ALLOWED_SET) {
|
||||
if (name.startsWith(allowedPrefix)) {
|
||||
CLASS_ALLOW_LFU_CACHE.put(name, CACHE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (String blockedPrefix : CLASS_DESERIALIZE_BLOCKED_SET) {
|
||||
if (BLOCK_ALL_CLASS_EXCEPT_ALLOW || name.startsWith(blockedPrefix)) {
|
||||
CLASS_BLOCK_LFU_CACHE.put(name, CACHE);
|
||||
error(name);
|
||||
}
|
||||
}
|
||||
|
||||
CLASS_ALLOW_LFU_CACHE.put(name, CACHE);
|
||||
}
|
||||
|
||||
private void error(String name) {
|
||||
String notice = "Trigger the safety barrier! " +
|
||||
"Catch not allowed serialize class. " +
|
||||
"Class name: " + name + " . " +
|
||||
"This means currently maybe being attacking by others." +
|
||||
"If you are sure this is a mistake, " +
|
||||
"please add this class name to `" + Constants.CLASS_DESERIALIZE_ALLOWED_LIST +
|
||||
"` as a system environment property.";
|
||||
if (counter.incrementAndGet() % 1000 == 0 || counter.get() < 100) {
|
||||
logger.error(notice);
|
||||
}
|
||||
throw new IllegalArgumentException(notice);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -427,4 +427,12 @@ public final class StringUtils {
|
|||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public static String toOSStyleKey(String key) {
|
||||
key = key.toUpperCase().replaceAll(Constants.DOT_REGEX, Constants.UNDERLINE_SEPARATOR);
|
||||
if (!key.startsWith("DUBBO_")) {
|
||||
key = "DUBBO_" + key;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
#
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#
|
||||
aj.org.objectweb.asm.
|
||||
br.com.anteros.
|
||||
ch.qos.logback.
|
||||
clojure.core$constantly
|
||||
clojure.main$eval_opt
|
||||
com.alibaba.citrus.springext.support.parser.abstractnamedproxybeandefinitionparser$proxytargetfactory
|
||||
com.alibaba.citrus.springext.util.springextutil.abstractproxy
|
||||
com.alibaba.druid.pool.druiddatasource
|
||||
com.alibaba.druid.stat.jdbcdatasourcestat
|
||||
com.alibaba.fastjson.annotation
|
||||
com.alipay.custrelation.service.model.redress.pair
|
||||
com.caucho.
|
||||
com.ibatis.
|
||||
com.mchange
|
||||
com.mysql.cj.jdbc.admin.
|
||||
com.mysql.cj.jdbc.mysqlconnectionpooldatasource
|
||||
com.mysql.cj.jdbc.mysqldatasource
|
||||
com.mysql.cj.jdbc.mysqlxadatasource
|
||||
com.mysql.cj.log.
|
||||
com.p6spy.engine.
|
||||
com.rometools.rome.feed.impl.equalsbean
|
||||
com.rometools.rome.feed.impl.tostringbean
|
||||
com.sun.
|
||||
com.taobao.eagleeye.wrapper
|
||||
com.zaxxer.hikari.
|
||||
flex.messaging.util.concurrent.
|
||||
java.awt.i
|
||||
java.awt.p
|
||||
java.beans.expression
|
||||
java.io.closeable
|
||||
java.io.serializable
|
||||
java.lang.autocloseable
|
||||
java.lang.class
|
||||
java.lang.cloneable
|
||||
java.lang.iterable
|
||||
java.lang.object
|
||||
java.lang.readable
|
||||
java.lang.runnable
|
||||
java.lang.thread
|
||||
java.lang.unixprocess
|
||||
java.net.inetaddress
|
||||
java.net.socket
|
||||
java.net.url
|
||||
java.rmi
|
||||
java.security.signedobject
|
||||
java.util.collection
|
||||
java.util.eventlistener
|
||||
java.util.jar.
|
||||
java.util.logging.
|
||||
java.util.prefs.
|
||||
java.util.serviceloader$lazyiterator
|
||||
javassist.
|
||||
javax.activation.
|
||||
javax.imageio.imageio$containsfilter
|
||||
javax.imageio.spi.serviceregistry
|
||||
javax.management.
|
||||
javax.naming.
|
||||
javax.net.
|
||||
javax.print.
|
||||
javax.script.
|
||||
javax.sound.
|
||||
javax.swing.j
|
||||
javax.tools.
|
||||
javax.xml
|
||||
jdk.internal.
|
||||
jodd.db.connection.
|
||||
junit.
|
||||
net.bytebuddy.dynamic.loading.bytearrayclassloader
|
||||
net.sf.cglib.
|
||||
net.sf.ehcache.hibernate.
|
||||
net.sf.ehcache.transaction.manager.
|
||||
oracle.jdbc.
|
||||
oracle.jms.aq
|
||||
oracle.net
|
||||
org.aoju.bus.proxy.provider.
|
||||
org.apache.activemq.activemqconnectionfactory
|
||||
org.apache.activemq.activemqxaconnectionfactory
|
||||
org.apache.activemq.jms.pool.
|
||||
org.apache.activemq.pool.
|
||||
org.apache.activemq.spring.
|
||||
org.apache.aries.transaction.
|
||||
org.apache.axis2.jaxws.spi.handler.
|
||||
org.apache.axis2.transport.jms.
|
||||
org.apache.bcel
|
||||
org.apache.carbondata.core.scan.expression.expressionresult
|
||||
org.apache.catalina.
|
||||
org.apache.cocoon.
|
||||
org.apache.commons.beanutils
|
||||
org.apache.commons.collections.comparators.
|
||||
org.apache.commons.collections.functors
|
||||
org.apache.commons.collections.functors.
|
||||
org.apache.commons.collections.transformer
|
||||
org.apache.commons.collections4.comparators
|
||||
org.apache.commons.collections4.functors
|
||||
org.apache.commons.collections4.transformer
|
||||
org.apache.commons.configuration
|
||||
org.apache.commons.dbcp
|
||||
org.apache.commons.fileupload
|
||||
org.apache.commons.jelly.
|
||||
org.apache.commons.logging.
|
||||
org.apache.commons.proxy.
|
||||
org.apache.cxf.jaxrs.provider.
|
||||
org.apache.hadoop.shaded.com.zaxxer.hikari.
|
||||
org.apache.http.auth.
|
||||
org.apache.http.conn.
|
||||
org.apache.http.cookie.
|
||||
org.apache.http.impl.
|
||||
org.apache.ibatis.datasource
|
||||
org.apache.ibatis.executor.
|
||||
org.apache.ibatis.javassist.
|
||||
org.apache.ibatis.ognl.
|
||||
org.apache.ibatis.parsing.
|
||||
org.apache.ibatis.reflection.
|
||||
org.apache.ibatis.scripting.
|
||||
org.apache.ignite.cache.jta.
|
||||
org.apache.log4j.
|
||||
org.apache.logging.
|
||||
org.apache.myfaces.context.servlet
|
||||
org.apache.openjpa.ee.
|
||||
org.apache.shiro.jndi.
|
||||
org.apache.shiro.realm.
|
||||
org.apache.tomcat
|
||||
org.apache.wicket.util
|
||||
org.apache.xalan
|
||||
org.apache.xbean.
|
||||
org.apache.xpath.xpathcontext
|
||||
org.codehaus.groovy.runtime
|
||||
org.codehaus.jackson.
|
||||
org.eclipse.jetty.
|
||||
org.geotools.filter.constantexpression
|
||||
org.h2.jdbcx.
|
||||
org.h2.server.
|
||||
org.hibernate
|
||||
org.javasimon.
|
||||
org.jaxen.
|
||||
org.jboss
|
||||
org.jdom.
|
||||
org.jdom2.transform.
|
||||
org.logicalcobwebs.
|
||||
org.mortbay.jetty.
|
||||
org.mozilla.javascript
|
||||
org.objectweb.asm.
|
||||
org.osjava.sj.
|
||||
org.python.core
|
||||
org.quartz.
|
||||
org.slf4j.
|
||||
org.springframework.
|
||||
org.yaml.snakeyaml.tokens.directivetoken
|
||||
sun.rmi.server.unicastref
|
||||
|
|
@ -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.
|
||||
#
|
||||
bsh.XThis
|
||||
bsh.Interpreter
|
||||
com.mchange.v2.c3p0.PoolBackedDataSource
|
||||
com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase
|
||||
clojure.lang.PersistentArrayMap
|
||||
clojure.inspector.proxy$javax.swing.table.AbstractTableModel$ff19274a
|
||||
org.apache.commons.beanutils.BeanComparator
|
||||
org.apache.commons.collections.Transformer
|
||||
org.apache.commons.collections.functors.ChainedTransformer
|
||||
org.apache.commons.collections.functors.ConstantTransformer
|
||||
org.apache.commons.collections.functors.InstantiateTransformer
|
||||
org.apache.commons.collections.map.LazyMap
|
||||
org.apache.commons.collections.functors.InvokerTransformer
|
||||
org.apache.commons.collections.keyvalue.TiedMapEntry
|
||||
org.apache.commons.collections4.comparators.TransformingComparator
|
||||
org.apache.commons.collections4.functors.InvokerTransformer
|
||||
org.apache.commons.collections4.functors.ChainedTransformer
|
||||
org.apache.commons.collections4.functors.ConstantTransformer
|
||||
org.apache.commons.collections4.functors.InstantiateTransformer
|
||||
org.apache.commons.fileupload.disk.DiskFileItem
|
||||
org.apache.commons.io.output.DeferredFileOutputStream
|
||||
org.apache.commons.io.output.ThresholdingOutputStream
|
||||
org.apache.wicket.util.upload.DiskFileItem
|
||||
org.apache.wicket.util.io.DeferredFileOutputStream
|
||||
org.apache.wicket.util.io.ThresholdingOutputStream
|
||||
org.codehaus.groovy.runtime.ConvertedClosure
|
||||
org.codehaus.groovy.runtime.MethodClosure
|
||||
org.hibernate.engine.spi.TypedValue
|
||||
org.hibernate.tuple.component.AbstractComponentTuplizer
|
||||
org.hibernate.tuple.component.PojoComponentTuplizer
|
||||
org.hibernate.type.AbstractType
|
||||
org.hibernate.type.ComponentType
|
||||
org.hibernate.type.Type
|
||||
org.hibernate.EntityMode
|
||||
com.sun.rowset.JdbcRowSetImpl
|
||||
org.jboss.interceptor.builder.InterceptionModelBuilder
|
||||
org.jboss.interceptor.builder.MethodReference
|
||||
org.jboss.interceptor.proxy.DefaultInvocationContextFactory
|
||||
org.jboss.interceptor.proxy.InterceptorMethodHandler
|
||||
org.jboss.interceptor.reader.ClassMetadataInterceptorReference
|
||||
org.jboss.interceptor.reader.DefaultMethodMetadata
|
||||
org.jboss.interceptor.reader.ReflectiveClassMetadata
|
||||
org.jboss.interceptor.reader.SimpleInterceptorMetadata
|
||||
org.jboss.interceptor.spi.instance.InterceptorInstantiator
|
||||
org.jboss.interceptor.spi.metadata.InterceptorReference
|
||||
org.jboss.interceptor.spi.metadata.MethodMetadata
|
||||
org.jboss.interceptor.spi.model.InterceptionType
|
||||
org.jboss.interceptor.spi.model.InterceptionModel
|
||||
sun.rmi.server.UnicastRef
|
||||
sun.rmi.transport.LiveRef
|
||||
sun.rmi.transport.tcp.TCPEndpoint
|
||||
java.rmi.server.RemoteObject
|
||||
java.rmi.server.RemoteRef
|
||||
java.rmi.server.UnicastRemoteObject
|
||||
sun.rmi.server.ActivationGroupImpl
|
||||
sun.rmi.server.UnicastServerRef
|
||||
net.sf.json.JSONObject
|
||||
org.jboss.weld.interceptor.builder.InterceptionModelBuilder
|
||||
org.jboss.weld.interceptor.builder.MethodReference
|
||||
org.jboss.weld.interceptor.proxy.DefaultInvocationContextFactory
|
||||
org.jboss.weld.interceptor.proxy.InterceptorMethodHandler
|
||||
org.jboss.weld.interceptor.reader.ClassMetadataInterceptorReference
|
||||
org.jboss.weld.interceptor.reader.DefaultMethodMetadata
|
||||
org.jboss.weld.interceptor.reader.ReflectiveClassMetadata
|
||||
org.jboss.weld.interceptor.reader.SimpleInterceptorMetadata
|
||||
org.jboss.weld.interceptor.spi.instance.InterceptorInstantiator
|
||||
org.jboss.weld.interceptor.spi.metadata.InterceptorReference
|
||||
org.jboss.weld.interceptor.spi.metadata.MethodMetadata
|
||||
org.jboss.weld.interceptor.spi.model.InterceptionModel
|
||||
org.jboss.weld.interceptor.spi.model.InterceptionType
|
||||
org.python.core.PyObject
|
||||
org.python.core.PyBytecode
|
||||
org.python.core.PyFunction
|
||||
org.mozilla.javascript.**
|
||||
org.apache.myfaces.context.servlet.FacesContextImpl
|
||||
org.apache.myfaces.context.servlet.FacesContextImplBase
|
||||
org.apache.myfaces.el.CompositeELResolver
|
||||
org.apache.myfaces.el.unified.FacesELContext
|
||||
org.apache.myfaces.view.facelets.el.ValueExpressionMethodExpression
|
||||
com.sun.syndication.feed.impl.ObjectBean
|
||||
org.springframework.beans.factory.ObjectFactory
|
||||
org.springframework.aop.framework.AdvisedSupport
|
||||
org.springframework.aop.target.SingletonTargetSource
|
||||
com.vaadin.data.util.NestedMethodProperty
|
||||
com.vaadin.data.util.PropertysetItem;
|
||||
|
|
@ -46,6 +46,8 @@ import com.alibaba.dubbo.common.extensionloader.ext8_add.impl.AddExt3_ManualAdap
|
|||
import com.alibaba.dubbo.common.extensionloader.ext8_add.impl.AddExt4_ManualAdaptive;
|
||||
import com.alibaba.dubbo.common.extensionloader.ext9_empty.Ext9Empty;
|
||||
import com.alibaba.dubbo.common.extensionloader.ext9_empty.impl.Ext9EmptyImpl;
|
||||
import com.alibaba.dubbo.common.extensionloader.injection.InjectExt;
|
||||
import com.alibaba.dubbo.common.extensionloader.injection.impl.InjectExtImpl;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import org.junit.Test;
|
||||
|
|
@ -416,4 +418,14 @@ public class ExtensionLoaderTest {
|
|||
Assert.assertTrue(list.get(1).getClass() == OrderActivateExtImpl1.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInjectExtension() {
|
||||
// test default
|
||||
InjectExt injectExt = ExtensionLoader.getExtensionLoader(InjectExt.class).getExtension("injection");
|
||||
InjectExtImpl injectExtImpl = (InjectExtImpl) injectExt;
|
||||
org.junit.Assert.assertNotNull(injectExtImpl.getSimpleExt());
|
||||
org.junit.Assert.assertNull(injectExtImpl.getSimpleExt1());
|
||||
org.junit.Assert.assertNull(injectExtImpl.getGenericType());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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 com.alibaba.dubbo.common.extensionloader.injection;
|
||||
|
||||
import com.alibaba.dubbo.common.extension.SPI;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@SPI("injection")
|
||||
public interface InjectExt {
|
||||
String echo(String msg);
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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 com.alibaba.dubbo.common.extensionloader.injection.impl;
|
||||
|
||||
|
||||
import com.alibaba.dubbo.common.extension.DisableInject;
|
||||
import com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt;
|
||||
import com.alibaba.dubbo.common.extensionloader.injection.InjectExt;
|
||||
|
||||
public class InjectExtImpl implements InjectExt {
|
||||
|
||||
private SimpleExt simpleExt;
|
||||
|
||||
private SimpleExt simpleExt1;
|
||||
|
||||
private Object genericType;
|
||||
|
||||
public void setSimpleExt(SimpleExt simpleExt) {
|
||||
this.simpleExt = simpleExt;
|
||||
}
|
||||
|
||||
@DisableInject
|
||||
public void setSimpleExt1(SimpleExt simpleExt1) {
|
||||
this.simpleExt1 = simpleExt1;
|
||||
}
|
||||
|
||||
public void setGenericType(Object genericType) {
|
||||
this.genericType = genericType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String echo(String msg) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public SimpleExt getSimpleExt() {
|
||||
return simpleExt;
|
||||
}
|
||||
|
||||
public SimpleExt getSimpleExt1() {
|
||||
return simpleExt1;
|
||||
}
|
||||
|
||||
public Object getGenericType() {
|
||||
return genericType;
|
||||
}
|
||||
}
|
||||
|
|
@ -67,6 +67,26 @@ public class CompatibleTypeUtilsTest {
|
|||
|
||||
result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11 12:24:12", Date.class);
|
||||
assertEquals(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2011-12-11 12:24:12"), (Date) result);
|
||||
|
||||
result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11 12:24:12", java.sql.Date.class);
|
||||
assertEquals(new SimpleDateFormat("yyyy-MM-dd").format((java.sql.Date) result), "2011-12-11");
|
||||
|
||||
result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11 12:24:12", java.sql.Time.class);
|
||||
assertEquals(new SimpleDateFormat("HH:mm:ss").format((java.sql.Time) result), "12:24:12");
|
||||
|
||||
result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11 12:24:12", java.sql.Timestamp.class);
|
||||
assertEquals(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((java.sql.Timestamp) result), "2011-12-11 12:24:12");
|
||||
|
||||
result = CompatibleTypeUtils.compatibleTypeConvert("ab", char[].class);
|
||||
assertEquals(2, ((char[]) result).length);
|
||||
assertEquals('a', ((char[]) result)[0]);
|
||||
assertEquals('b', ((char[]) result)[1]);
|
||||
|
||||
result = CompatibleTypeUtils.compatibleTypeConvert("", char[].class);
|
||||
assertEquals(0, ((char[]) result).length);
|
||||
|
||||
result = CompatibleTypeUtils.compatibleTypeConvert(null, char[].class);
|
||||
assertEquals(null, result);
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,8 +29,10 @@ import org.junit.Test;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
|
|
@ -559,6 +561,34 @@ public class PojoUtilsTest {
|
|||
Assert.assertEquals(parent.getAge(), realizeParent.getAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDateTimeTimestamp() throws Exception {
|
||||
String dateStr = "2018-09-12";
|
||||
String timeStr = "10:12:33";
|
||||
String dateTimeStr = "2018-09-12 10:12:33";
|
||||
String[] dateFormat = new String[]{"yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd", "HH:mm:ss"};
|
||||
|
||||
//java.util.Date
|
||||
Object date = PojoUtils.realize(dateTimeStr, Date.class, (Type) Date.class);
|
||||
assertEquals(Date.class, date.getClass());
|
||||
assertEquals(dateTimeStr, new SimpleDateFormat(dateFormat[0]).format(date));
|
||||
|
||||
//java.sql.Time
|
||||
Object time = PojoUtils.realize(dateTimeStr, java.sql.Time.class, (Type) java.sql.Time.class);
|
||||
assertEquals(java.sql.Time.class, time.getClass());
|
||||
assertEquals(timeStr, new SimpleDateFormat(dateFormat[2]).format(time));
|
||||
|
||||
//java.sql.Date
|
||||
Object sqlDate = PojoUtils.realize(dateTimeStr, java.sql.Date.class, (Type) java.sql.Date.class);
|
||||
assertEquals(java.sql.Date.class, sqlDate.getClass());
|
||||
assertEquals(dateStr, new SimpleDateFormat(dateFormat[1]).format(sqlDate));
|
||||
|
||||
//java.sql.Timestamp
|
||||
Object timestamp = PojoUtils.realize(dateTimeStr, java.sql.Timestamp.class, (Type) java.sql.Timestamp.class);
|
||||
assertEquals(java.sql.Timestamp.class, timestamp.getClass());
|
||||
assertEquals(dateTimeStr, new SimpleDateFormat(dateFormat[0]).format(timestamp));
|
||||
}
|
||||
|
||||
public static class Parent {
|
||||
public String gender;
|
||||
public String email;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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 com.alibaba.dubbo.common.utils;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.InvalidClassException;
|
||||
import java.io.ObjectInputStream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class SerialDetectorTest {
|
||||
@Test
|
||||
public void testBlacklisted() throws Exception {
|
||||
try {
|
||||
ObjectInputStream stream = new SerialDetector(getClass().getResourceAsStream("/security/invalid_data.ser"));
|
||||
stream.readObject();
|
||||
fail();
|
||||
} catch (InvalidClassException expected) {
|
||||
assertTrue(expected.getMessage().contains("blocked"));
|
||||
assertTrue(expected.getMessage().contains("blacklist"));
|
||||
assertEquals(expected.classname, "org.hibernate.engine.spi.TypedValue");
|
||||
} catch (ClassNotFoundException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -90,9 +90,9 @@ public class UrlUtilsTest {
|
|||
|
||||
@Test
|
||||
public void testParseUrl2() {
|
||||
String address = "127.0.0.1";
|
||||
String backupAddress1 = "127.0.0.2";
|
||||
String backupAddress2 = "127.0.0.3";
|
||||
String address = "192.168.0.1";
|
||||
String backupAddress1 = "192.168.0.2";
|
||||
String backupAddress2 = "192.168.0.3";
|
||||
|
||||
Map<String, String> parameters = new HashMap<String, String>();
|
||||
parameters.put("username", "root");
|
||||
|
|
@ -100,25 +100,25 @@ public class UrlUtilsTest {
|
|||
parameters.put("port", "10000");
|
||||
parameters.put("protocol", "dubbo");
|
||||
URL url = UrlUtils.parseURL(address + "," + backupAddress1 + "," + backupAddress2, parameters);
|
||||
assertEquals(localAddress + ":10000", url.getAddress());
|
||||
assertEquals("192.168.0.1:10000", url.getAddress());
|
||||
assertEquals("root", url.getUsername());
|
||||
assertEquals("alibaba", url.getPassword());
|
||||
assertEquals(10000, url.getPort());
|
||||
assertEquals("dubbo", url.getProtocol());
|
||||
assertEquals("127.0.0.2" + "," + "127.0.0.3", url.getParameter("backup"));
|
||||
assertEquals("192.168.0.2" + "," + "192.168.0.3", url.getParameter("backup"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseUrls() {
|
||||
String addresses = "127.0.0.1|127.0.0.2|127.0.0.3";
|
||||
String addresses = "192.168.0.1|192.168.0.2|192.168.0.3";
|
||||
Map<String, String> parameters = new HashMap<String, String>();
|
||||
parameters.put("username", "root");
|
||||
parameters.put("password", "alibaba");
|
||||
parameters.put("port", "10000");
|
||||
parameters.put("protocol", "dubbo");
|
||||
List<URL> urls = UrlUtils.parseURLs(addresses, parameters);
|
||||
assertEquals(localAddress + ":10000", urls.get(0).getAddress());
|
||||
assertEquals("127.0.0.2" + ":10000", urls.get(1).getAddress());
|
||||
assertEquals("192.168.0.1" + ":10000", urls.get(0).getAddress());
|
||||
assertEquals("192.168.0.2" + ":10000", urls.get(1).getAddress());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -322,7 +322,7 @@ public class UrlUtilsTest {
|
|||
|
||||
@Test
|
||||
public void testIsServiceKeyMatch() throws Exception {
|
||||
URL url = URL.valueOf("test://127.0.0.0");
|
||||
URL url = URL.valueOf("test://127.0.0.1");
|
||||
URL pattern = url.addParameter(Constants.GROUP_KEY, "test")
|
||||
.addParameter(Constants.INTERFACE_KEY, "test")
|
||||
.addParameter(Constants.VERSION_KEY, "test");
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
injection=com.alibaba.dubbo.common.extensionloader.injection.impl.InjectExtImpl
|
||||
|
|
@ -15,4 +15,6 @@
|
|||
# limitations under the License.
|
||||
#
|
||||
|
||||
dubbo=properties
|
||||
dubbo=properties
|
||||
dubbo.security.serialization.blacklist=org.hibernate.engine.spi.TypedValue
|
||||
dubbo.security.serialization.check=true
|
||||
|
|
@ -1,19 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
- 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.
|
||||
-->
|
||||
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.
|
||||
-->
|
||||
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
|
||||
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
|
||||
<!-- ===================================================================== -->
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -19,7 +19,7 @@
|
|||
<parent>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-config</artifactId>
|
||||
<version>2.6.3-SNAPSHOT</version>
|
||||
<version>2.6.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>dubbo-config-api</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
|
@ -29,6 +29,11 @@
|
|||
<skip_maven_deploy>false</skip_maven_deploy>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-common</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-registry-api</artifactId>
|
||||
|
|
@ -85,7 +90,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-remoting-netty</artifactId>
|
||||
<artifactId>dubbo-remoting-netty4</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ public abstract class AbstractConfig implements Serializable {
|
|||
|
||||
private static final Pattern PATTERN_PATH = Pattern.compile("[/\\-$._0-9a-zA-Z]+");
|
||||
|
||||
private static final Pattern PATTERN_NAME_HAS_SYMBOL = Pattern.compile("[:*,/\\-._0-9a-zA-Z]+");
|
||||
private static final Pattern PATTERN_NAME_HAS_SYMBOL = Pattern.compile("[:*,\\s/\\-._0-9a-zA-Z]+");
|
||||
|
||||
private static final Pattern PATTERN_KEY = Pattern.compile("[*,\\-._0-9a-zA-Z]+");
|
||||
private static final Map<String, String> legacyProperties = new HashMap<String, String>();
|
||||
|
|
@ -423,7 +423,7 @@ public abstract class AbstractConfig implements Serializable {
|
|||
}
|
||||
String setter = "set" + property.substring(0, 1).toUpperCase() + property.substring(1);
|
||||
Object value = method.invoke(annotation);
|
||||
if (value != null && !value.equals(method.getDefaultValue())) {
|
||||
if (!isAnnotationArray(method.getReturnType()) && value != null && !value.equals(method.getDefaultValue())) {
|
||||
Class<?> parameterType = ReflectUtils.getBoxedClass(method.getReturnType());
|
||||
if ("filter".equals(property) || "listener".equals(property)) {
|
||||
parameterType = String.class;
|
||||
|
|
@ -446,6 +446,13 @@ public abstract class AbstractConfig implements Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
boolean isAnnotationArray(Class target) {
|
||||
if (target.isArray() && target.getComponentType().isAnnotation()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
try {
|
||||
|
|
@ -457,7 +464,8 @@ public abstract class AbstractConfig implements Serializable {
|
|||
try {
|
||||
String name = method.getName();
|
||||
if ((name.startsWith("get") || name.startsWith("is"))
|
||||
&& !"getClass".equals(name) && !"get".equals(name) && !"is".equals(name)
|
||||
&& !"get".equals(name) && !"is".equals(name)
|
||||
&& !"getClass".equals(name) && !"getObject".equals(name)
|
||||
&& Modifier.isPublic(method.getModifiers())
|
||||
&& method.getParameterTypes().length == 0
|
||||
&& isPrimitive(method.getReturnType())) {
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ import com.alibaba.dubbo.rpc.ProxyFactory;
|
|||
import com.alibaba.dubbo.rpc.cluster.Cluster;
|
||||
import com.alibaba.dubbo.rpc.support.MockInvoker;
|
||||
|
||||
import static com.alibaba.dubbo.common.utils.NetUtils.isInvalidLocalHost;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
|
@ -220,12 +222,22 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
|
|||
appendProperties(monitor);
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put(Constants.INTERFACE_KEY, MonitorService.class.getName());
|
||||
map.put(Constants.SIDE_KEY, Constants.CONSUMER_SIDE);
|
||||
map.put("dubbo", Version.getProtocolVersion());
|
||||
map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis()));
|
||||
if (ConfigUtils.getPid() > 0) {
|
||||
map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid()));
|
||||
}
|
||||
//set ip
|
||||
String hostToRegistry = ConfigUtils.getSystemProperty(Constants.DUBBO_IP_TO_REGISTRY);
|
||||
if (hostToRegistry == null || hostToRegistry.length() == 0) {
|
||||
hostToRegistry = NetUtils.getLocalHost();
|
||||
} else if (isInvalidLocalHost(hostToRegistry)) {
|
||||
throw new IllegalArgumentException("Specified invalid registry ip from property:" + Constants.DUBBO_IP_TO_REGISTRY + ", value:" + hostToRegistry);
|
||||
}
|
||||
map.put(Constants.REGISTER_IP_KEY, hostToRegistry);
|
||||
appendParameters(map, monitor);
|
||||
appendParameters(map, application);
|
||||
String address = monitor.getAddress();
|
||||
String sysaddress = System.getProperty("dubbo.monitor.address");
|
||||
if (sysaddress != null && sysaddress.length() > 0) {
|
||||
|
|
@ -277,7 +289,36 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
|
|||
}
|
||||
}
|
||||
|
||||
protected void checkStubAndMock(Class<?> interfaceClass) {
|
||||
void checkMock(Class<?> interfaceClass) {
|
||||
if (ConfigUtils.isEmpty(mock)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String normalizedMock = MockInvoker.normalizeMock(mock);
|
||||
if (normalizedMock.startsWith(Constants.RETURN_PREFIX)) {
|
||||
normalizedMock = normalizedMock.substring(Constants.RETURN_PREFIX.length()).trim();
|
||||
try {
|
||||
MockInvoker.parseMockValue(normalizedMock);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("Illegal mock return in <dubbo:service/reference ... " +
|
||||
"mock=\"" + mock + "\" />");
|
||||
}
|
||||
} else if (normalizedMock.startsWith(Constants.THROW_PREFIX)) {
|
||||
normalizedMock = normalizedMock.substring(Constants.THROW_PREFIX.length()).trim();
|
||||
if (ConfigUtils.isNotEmpty(normalizedMock)) {
|
||||
try {
|
||||
MockInvoker.getThrowable(normalizedMock);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("Illegal mock throw in <dubbo:service/reference ... " +
|
||||
"mock=\"" + mock + "\" />");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
MockInvoker.getMockObject(normalizedMock, interfaceClass);
|
||||
}
|
||||
}
|
||||
|
||||
void checkStub(Class<?> interfaceClass) {
|
||||
if (ConfigUtils.isNotEmpty(local)) {
|
||||
Class<?> localClass = ConfigUtils.isDefault(local) ? ReflectUtils.forName(interfaceClass.getName() + "Local") : ReflectUtils.forName(local);
|
||||
if (!interfaceClass.isAssignableFrom(localClass)) {
|
||||
|
|
@ -300,26 +341,6 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
|
|||
throw new IllegalStateException("No such constructor \"public " + localClass.getSimpleName() + "(" + interfaceClass.getName() + ")\" in local implementation class " + localClass.getName());
|
||||
}
|
||||
}
|
||||
if (ConfigUtils.isNotEmpty(mock)) {
|
||||
if (mock.startsWith(Constants.RETURN_PREFIX)) {
|
||||
String value = mock.substring(Constants.RETURN_PREFIX.length());
|
||||
try {
|
||||
MockInvoker.parseMockValue(value);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("Illegal mock json value in <dubbo:service ... mock=\"" + mock + "\" />");
|
||||
}
|
||||
} else {
|
||||
Class<?> mockClass = ConfigUtils.isDefault(mock) ? ReflectUtils.forName(interfaceClass.getName() + "Mock") : ReflectUtils.forName(mock);
|
||||
if (!interfaceClass.isAssignableFrom(mockClass)) {
|
||||
throw new IllegalStateException("The mock implementation class " + mockClass.getName() + " not implement interface " + interfaceClass.getName());
|
||||
}
|
||||
try {
|
||||
mockClass.getConstructor(new Class<?>[0]);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new IllegalStateException("No such empty constructor \"public " + mockClass.getSimpleName() + "()\" in mock implementation class " + mockClass.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -514,4 +535,4 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
|
|||
this.scope = scope;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,19 @@ public abstract class AbstractMethodConfig extends AbstractConfig {
|
|||
// customized parameters
|
||||
protected Map<String, String> parameters;
|
||||
|
||||
/**
|
||||
* forks for forking cluster
|
||||
*/
|
||||
protected Integer forks;
|
||||
|
||||
public Integer getForks() {
|
||||
return forks;
|
||||
}
|
||||
|
||||
public void setForks(Integer forks) {
|
||||
this.forks = forks;
|
||||
}
|
||||
|
||||
public Integer getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
|
@ -127,8 +140,14 @@ public abstract class AbstractMethodConfig extends AbstractConfig {
|
|||
}
|
||||
|
||||
public void setMock(String mock) {
|
||||
if (mock != null && mock.startsWith(Constants.RETURN_PREFIX)) {
|
||||
if (mock == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mock.startsWith(Constants.RETURN_PREFIX) || mock.startsWith(Constants.THROW_PREFIX + " ")) {
|
||||
checkLength("mock", mock);
|
||||
} else if (mock.startsWith(Constants.FAIL_PREFIX) || mock.startsWith(Constants.FORCE_PREFIX)) {
|
||||
checkNameHasSymbol("mock", mock);
|
||||
} else {
|
||||
checkName("mock", mock);
|
||||
}
|
||||
|
|
@ -168,4 +187,4 @@ public abstract class AbstractMethodConfig extends AbstractConfig {
|
|||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,243 +1,255 @@
|
|||
/*
|
||||
* 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 com.alibaba.dubbo.config;
|
||||
|
||||
import com.alibaba.dubbo.common.Constants;
|
||||
import com.alibaba.dubbo.config.support.Parameter;
|
||||
import com.alibaba.dubbo.rpc.ExporterListener;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* AbstractServiceConfig
|
||||
*
|
||||
* @export
|
||||
*/
|
||||
public abstract class AbstractServiceConfig extends AbstractInterfaceConfig {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// version
|
||||
protected String version;
|
||||
|
||||
// group
|
||||
protected String group;
|
||||
|
||||
// whether the service is deprecated
|
||||
protected Boolean deprecated;
|
||||
|
||||
// delay service exporting
|
||||
protected Integer delay;
|
||||
|
||||
// whether to export the service
|
||||
protected Boolean export;
|
||||
|
||||
// weight
|
||||
protected Integer weight;
|
||||
|
||||
// document center
|
||||
protected String document;
|
||||
|
||||
// whether to register as a dynamic service or not on register center
|
||||
protected Boolean dynamic;
|
||||
|
||||
// whether to use token
|
||||
protected String token;
|
||||
|
||||
// access log
|
||||
protected String accesslog;
|
||||
protected List<ProtocolConfig> protocols;
|
||||
// max allowed execute times
|
||||
private Integer executes;
|
||||
// whether to register
|
||||
private Boolean register;
|
||||
|
||||
// warm up period
|
||||
private Integer warmup;
|
||||
|
||||
// serialization
|
||||
private String serialization;
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
checkKey("version", version);
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public void setGroup(String group) {
|
||||
checkKey("group", group);
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
public Integer getDelay() {
|
||||
return delay;
|
||||
}
|
||||
|
||||
public void setDelay(Integer delay) {
|
||||
this.delay = delay;
|
||||
}
|
||||
|
||||
public Boolean getExport() {
|
||||
return export;
|
||||
}
|
||||
|
||||
public void setExport(Boolean export) {
|
||||
this.export = export;
|
||||
}
|
||||
|
||||
public Integer getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
public void setWeight(Integer weight) {
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
@Parameter(escaped = true)
|
||||
public String getDocument() {
|
||||
return document;
|
||||
}
|
||||
|
||||
public void setDocument(String document) {
|
||||
this.document = document;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
checkName("token", token);
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public void setToken(Boolean token) {
|
||||
if (token == null) {
|
||||
setToken((String) null);
|
||||
} else {
|
||||
setToken(String.valueOf(token));
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean isDeprecated() {
|
||||
return deprecated;
|
||||
}
|
||||
|
||||
public void setDeprecated(Boolean deprecated) {
|
||||
this.deprecated = deprecated;
|
||||
}
|
||||
|
||||
public Boolean isDynamic() {
|
||||
return dynamic;
|
||||
}
|
||||
|
||||
public void setDynamic(Boolean dynamic) {
|
||||
this.dynamic = dynamic;
|
||||
}
|
||||
|
||||
public List<ProtocolConfig> getProtocols() {
|
||||
return protocols;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public void setProtocols(List<? extends ProtocolConfig> protocols) {
|
||||
this.protocols = (List<ProtocolConfig>) protocols;
|
||||
}
|
||||
|
||||
public ProtocolConfig getProtocol() {
|
||||
return protocols == null || protocols.isEmpty() ? null : protocols.get(0);
|
||||
}
|
||||
|
||||
public void setProtocol(ProtocolConfig protocol) {
|
||||
this.protocols = Arrays.asList(protocol);
|
||||
}
|
||||
|
||||
public String getAccesslog() {
|
||||
return accesslog;
|
||||
}
|
||||
|
||||
public void setAccesslog(String accesslog) {
|
||||
this.accesslog = accesslog;
|
||||
}
|
||||
|
||||
public void setAccesslog(Boolean accesslog) {
|
||||
if (accesslog == null) {
|
||||
setAccesslog((String) null);
|
||||
} else {
|
||||
setAccesslog(String.valueOf(accesslog));
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getExecutes() {
|
||||
return executes;
|
||||
}
|
||||
|
||||
public void setExecutes(Integer executes) {
|
||||
this.executes = executes;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Parameter(key = Constants.SERVICE_FILTER_KEY, append = true)
|
||||
public String getFilter() {
|
||||
return super.getFilter();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Parameter(key = Constants.EXPORTER_LISTENER_KEY, append = true)
|
||||
public String getListener() {
|
||||
return listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListener(String listener) {
|
||||
checkMultiExtension(ExporterListener.class, "listener", listener);
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public Boolean isRegister() {
|
||||
return register;
|
||||
}
|
||||
|
||||
public void setRegister(Boolean register) {
|
||||
this.register = register;
|
||||
}
|
||||
|
||||
public Integer getWarmup() {
|
||||
return warmup;
|
||||
}
|
||||
|
||||
public void setWarmup(Integer warmup) {
|
||||
this.warmup = warmup;
|
||||
}
|
||||
|
||||
public String getSerialization() {
|
||||
return serialization;
|
||||
}
|
||||
|
||||
public void setSerialization(String serialization) {
|
||||
this.serialization = serialization;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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 com.alibaba.dubbo.config;
|
||||
|
||||
import com.alibaba.dubbo.common.Constants;
|
||||
import com.alibaba.dubbo.config.support.Parameter;
|
||||
import com.alibaba.dubbo.rpc.ExporterListener;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* AbstractServiceConfig
|
||||
*
|
||||
* @export
|
||||
*/
|
||||
public abstract class AbstractServiceConfig extends AbstractInterfaceConfig {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// version
|
||||
protected String version;
|
||||
|
||||
// group
|
||||
protected String group;
|
||||
|
||||
// whether the service is deprecated
|
||||
protected Boolean deprecated;
|
||||
|
||||
// delay service exporting
|
||||
protected Integer delay;
|
||||
|
||||
// whether to export the service
|
||||
protected Boolean export;
|
||||
|
||||
// weight
|
||||
protected Integer weight;
|
||||
|
||||
// document center
|
||||
protected String document;
|
||||
|
||||
// whether to register as a dynamic service or not on register center
|
||||
protected Boolean dynamic;
|
||||
|
||||
// whether to use token
|
||||
protected String token;
|
||||
|
||||
// access log
|
||||
protected String accesslog;
|
||||
protected List<ProtocolConfig> protocols;
|
||||
// max allowed execute times
|
||||
private Integer executes;
|
||||
// whether to register
|
||||
private Boolean register;
|
||||
|
||||
// warm up period
|
||||
private Integer warmup;
|
||||
|
||||
// serialization
|
||||
private String serialization;
|
||||
|
||||
// provider tag
|
||||
protected String tag;
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
checkKey("version", version);
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public void setGroup(String group) {
|
||||
checkKey("group", group);
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
public Integer getDelay() {
|
||||
return delay;
|
||||
}
|
||||
|
||||
public void setDelay(Integer delay) {
|
||||
this.delay = delay;
|
||||
}
|
||||
|
||||
public Boolean getExport() {
|
||||
return export;
|
||||
}
|
||||
|
||||
public void setExport(Boolean export) {
|
||||
this.export = export;
|
||||
}
|
||||
|
||||
public Integer getWeight() {
|
||||
return weight;
|
||||
}
|
||||
|
||||
public void setWeight(Integer weight) {
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
@Parameter(escaped = true)
|
||||
public String getDocument() {
|
||||
return document;
|
||||
}
|
||||
|
||||
public void setDocument(String document) {
|
||||
this.document = document;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
checkName("token", token);
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public void setToken(Boolean token) {
|
||||
if (token == null) {
|
||||
setToken((String) null);
|
||||
} else {
|
||||
setToken(String.valueOf(token));
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean isDeprecated() {
|
||||
return deprecated;
|
||||
}
|
||||
|
||||
public void setDeprecated(Boolean deprecated) {
|
||||
this.deprecated = deprecated;
|
||||
}
|
||||
|
||||
public Boolean isDynamic() {
|
||||
return dynamic;
|
||||
}
|
||||
|
||||
public void setDynamic(Boolean dynamic) {
|
||||
this.dynamic = dynamic;
|
||||
}
|
||||
|
||||
public List<ProtocolConfig> getProtocols() {
|
||||
return protocols;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public void setProtocols(List<? extends ProtocolConfig> protocols) {
|
||||
this.protocols = (List<ProtocolConfig>) protocols;
|
||||
}
|
||||
|
||||
public ProtocolConfig getProtocol() {
|
||||
return protocols == null || protocols.isEmpty() ? null : protocols.get(0);
|
||||
}
|
||||
|
||||
public void setProtocol(ProtocolConfig protocol) {
|
||||
this.protocols = Arrays.asList(protocol);
|
||||
}
|
||||
|
||||
public String getAccesslog() {
|
||||
return accesslog;
|
||||
}
|
||||
|
||||
public void setAccesslog(String accesslog) {
|
||||
this.accesslog = accesslog;
|
||||
}
|
||||
|
||||
public void setAccesslog(Boolean accesslog) {
|
||||
if (accesslog == null) {
|
||||
setAccesslog((String) null);
|
||||
} else {
|
||||
setAccesslog(String.valueOf(accesslog));
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getExecutes() {
|
||||
return executes;
|
||||
}
|
||||
|
||||
public void setExecutes(Integer executes) {
|
||||
this.executes = executes;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Parameter(key = Constants.SERVICE_FILTER_KEY, append = true)
|
||||
public String getFilter() {
|
||||
return super.getFilter();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Parameter(key = Constants.EXPORTER_LISTENER_KEY, append = true)
|
||||
public String getListener() {
|
||||
return listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListener(String listener) {
|
||||
checkMultiExtension(ExporterListener.class, "listener", listener);
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public Boolean isRegister() {
|
||||
return register;
|
||||
}
|
||||
|
||||
public void setRegister(Boolean register) {
|
||||
this.register = register;
|
||||
}
|
||||
|
||||
public Integer getWarmup() {
|
||||
return warmup;
|
||||
}
|
||||
|
||||
public void setWarmup(Integer warmup) {
|
||||
this.warmup = warmup;
|
||||
}
|
||||
|
||||
public String getSerialization() {
|
||||
return serialization;
|
||||
}
|
||||
|
||||
public void setSerialization(String serialization) {
|
||||
this.serialization = serialization;
|
||||
}
|
||||
|
||||
@Parameter(key = "dubbo.tag")
|
||||
public String getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void setTag(String tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,10 +71,13 @@ public class ApplicationConfig extends AbstractConfig {
|
|||
// directory for saving thread dump
|
||||
private String dumpDirectory;
|
||||
|
||||
// whether to enable qos or not
|
||||
private Boolean qosEnable;
|
||||
|
||||
// the qos port to listen
|
||||
private Integer qosPort;
|
||||
|
||||
// should we accept foreign ip or not?
|
||||
private Boolean qosAcceptForeignIp;
|
||||
|
||||
// customized parameters
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package com.alibaba.dubbo.config;
|
||||
|
||||
import com.alibaba.dubbo.config.annotation.Argument;
|
||||
import com.alibaba.dubbo.config.support.Parameter;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
|
@ -36,6 +37,15 @@ public class ArgumentConfig implements Serializable {
|
|||
//callback interface
|
||||
private Boolean callback;
|
||||
|
||||
public ArgumentConfig() {
|
||||
}
|
||||
|
||||
public ArgumentConfig(Argument argument) {
|
||||
this.index = argument.index();
|
||||
this.type = argument.type();
|
||||
this.callback = argument.callback();
|
||||
}
|
||||
|
||||
@Parameter(excluded = true)
|
||||
public Integer getIndex() {
|
||||
return index;
|
||||
|
|
@ -62,4 +72,4 @@ public class ArgumentConfig implements Serializable {
|
|||
return callback;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,18 @@ public class ConsumerConfig extends AbstractReferenceConfig {
|
|||
// networking framework client uses: netty, mina, etc.
|
||||
private String client;
|
||||
|
||||
// consumer thread pool type: cached, fixed, limit, eager
|
||||
private String threadpool;
|
||||
|
||||
// consumer threadpool core thread size
|
||||
private Integer corethreads;
|
||||
|
||||
// consumer threadpool thread size
|
||||
private Integer threads;
|
||||
|
||||
// consumer threadpool queue size
|
||||
private Integer queues;
|
||||
|
||||
@Override
|
||||
public void setTimeout(Integer timeout) {
|
||||
super.setTimeout(timeout);
|
||||
|
|
@ -56,4 +68,40 @@ public class ConsumerConfig extends AbstractReferenceConfig {
|
|||
public void setClient(String client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public String getThreadpool() {
|
||||
return threadpool;
|
||||
}
|
||||
|
||||
public void setThreadpool(String threadpool) {
|
||||
this.threadpool = threadpool;
|
||||
}
|
||||
|
||||
public Boolean getDefault() {
|
||||
return isDefault;
|
||||
}
|
||||
|
||||
public Integer getCorethreads() {
|
||||
return corethreads;
|
||||
}
|
||||
|
||||
public void setCorethreads(Integer corethreads) {
|
||||
this.corethreads = corethreads;
|
||||
}
|
||||
|
||||
public Integer getThreads() {
|
||||
return threads;
|
||||
}
|
||||
|
||||
public void setThreads(Integer threads) {
|
||||
this.threads = threads;
|
||||
}
|
||||
|
||||
public Integer getQueues() {
|
||||
return queues;
|
||||
}
|
||||
|
||||
public void setQueues(Integer queues) {
|
||||
this.queues = queues;
|
||||
}
|
||||
}
|
||||
|
|
@ -17,8 +17,12 @@
|
|||
package com.alibaba.dubbo.config;
|
||||
|
||||
import com.alibaba.dubbo.common.Constants;
|
||||
import com.alibaba.dubbo.common.utils.StringUtils;
|
||||
import com.alibaba.dubbo.config.annotation.Method;
|
||||
import com.alibaba.dubbo.config.support.Parameter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
|
@ -74,6 +78,45 @@ public class MethodConfig extends AbstractMethodConfig {
|
|||
|
||||
private List<ArgumentConfig> arguments;
|
||||
|
||||
public MethodConfig() {
|
||||
}
|
||||
|
||||
public MethodConfig(Method method) {
|
||||
appendAnnotation(Method.class, method);
|
||||
this.setReturn(method.isReturn());
|
||||
|
||||
if(StringUtils.isNotEmpty(method.oninvoke())){
|
||||
this.setOninvoke(method.oninvoke());
|
||||
}
|
||||
if(StringUtils.isNotEmpty(method.onreturn())){
|
||||
this.setOnreturn(method.onreturn());
|
||||
}
|
||||
if(StringUtils.isNotEmpty(method.onthrow())){
|
||||
this.setOnthrow(method.onthrow());
|
||||
}
|
||||
|
||||
if (method.arguments() != null && method.arguments().length != 0) {
|
||||
List<ArgumentConfig> argumentConfigs = new ArrayList<ArgumentConfig>(method.arguments().length);
|
||||
this.setArguments(argumentConfigs);
|
||||
for (int i = 0; i < method.arguments().length; i++) {
|
||||
ArgumentConfig argumentConfig = new ArgumentConfig(method.arguments()[i]);
|
||||
argumentConfigs.add(argumentConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<MethodConfig> constructMethodConfig(Method[] methods) {
|
||||
if (methods != null && methods.length != 0) {
|
||||
List<MethodConfig> methodConfigs = new ArrayList<MethodConfig>(methods.length);
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
MethodConfig methodConfig = new MethodConfig(methods[i]);
|
||||
methodConfigs.add(methodConfig);
|
||||
}
|
||||
return methodConfigs;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Parameter(excluded = true)
|
||||
public String getName() {
|
||||
return name;
|
||||
|
|
@ -211,4 +254,4 @@ public class MethodConfig extends AbstractMethodConfig {
|
|||
this.isReturn = isReturn;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -459,13 +459,4 @@ public class ProtocolConfig extends AbstractConfig {
|
|||
ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(name).destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Just for compatibility.
|
||||
* It should be deleted in the next major version, say 2.7.x.
|
||||
*/
|
||||
@Deprecated
|
||||
public static void destroyAll() {
|
||||
DubboShutdownHook.getDubboShutdownHook().destroyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ import com.alibaba.dubbo.config.annotation.Reference;
|
|||
import com.alibaba.dubbo.config.model.ApplicationModel;
|
||||
import com.alibaba.dubbo.config.model.ConsumerModel;
|
||||
import com.alibaba.dubbo.config.support.Parameter;
|
||||
import com.alibaba.dubbo.registry.support.ConsumerInvokerWrapper;
|
||||
import com.alibaba.dubbo.registry.support.ProviderConsumerRegTable;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.Protocol;
|
||||
import com.alibaba.dubbo.rpc.ProxyFactory;
|
||||
|
|
@ -47,11 +49,13 @@ import java.io.IOException;
|
|||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.alibaba.dubbo.common.utils.NetUtils.isInvalidLocalHost;
|
||||
|
||||
|
|
@ -112,6 +116,7 @@ public class ReferenceConfig<T> extends AbstractReferenceConfig {
|
|||
|
||||
public ReferenceConfig(Reference reference) {
|
||||
appendAnnotation(Reference.class, reference);
|
||||
setMethods(MethodConfig.constructMethodConfig(reference.methods()));
|
||||
}
|
||||
|
||||
private static void checkAndConvertImplicitConfig(MethodConfig method, Map<String, String> map, Map<Object, Object> attributes) {
|
||||
|
|
@ -276,7 +281,8 @@ public class ReferenceConfig<T> extends AbstractReferenceConfig {
|
|||
}
|
||||
}
|
||||
checkApplication();
|
||||
checkStubAndMock(interfaceClass);
|
||||
checkStub(interfaceClass);
|
||||
checkMock(interfaceClass);
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
Map<Object, Object> attributes = new HashMap<Object, Object>();
|
||||
map.put(Constants.SIDE_KEY, Constants.CONSUMER_SIDE);
|
||||
|
|
@ -403,7 +409,7 @@ public class ReferenceConfig<T> extends AbstractReferenceConfig {
|
|||
}
|
||||
if (registryURL != null) { // registry url is available
|
||||
// use AvailableCluster only when register's cluster is available
|
||||
URL u = registryURL.addParameter(Constants.CLUSTER_KEY, AvailableCluster.NAME);
|
||||
URL u = registryURL.addParameterIfAbsent(Constants.CLUSTER_KEY, AvailableCluster.NAME);
|
||||
invoker = cluster.join(new StaticDirectory(u, invokers));
|
||||
} else { // not a registry url
|
||||
invoker = cluster.join(new StaticDirectory(invokers));
|
||||
|
|
@ -419,7 +425,16 @@ public class ReferenceConfig<T> extends AbstractReferenceConfig {
|
|||
c = true; // default true
|
||||
}
|
||||
if (c && !invoker.isAvailable()) {
|
||||
throw new IllegalStateException("Failed to check the status of the service " + interfaceName + ". No provider available for the service " + (group == null ? "" : group + "/") + interfaceName + (version == null ? "" : ":" + version) + " from the url " + invoker.getUrl() + " to the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion());
|
||||
// make it possible for consumer to retry later if provider is temporarily unavailable
|
||||
initialized = false;
|
||||
final String serviceKey = (group == null ? "" : group + "/") + interfaceName + (version == null ? "" :
|
||||
":" + version);
|
||||
Set<ConsumerInvokerWrapper> consumerInvoker = ProviderConsumerRegTable.getConsumerInvoker(serviceKey);
|
||||
if (consumerInvoker != Collections.<ConsumerInvokerWrapper>emptySet()) {
|
||||
//since create proxy error , so we must be the first consumer. Simply clear ConcurrentHashSet
|
||||
consumerInvoker.clear();
|
||||
}
|
||||
throw new IllegalStateException("Failed to check the status of the service " + interfaceName + ". No provider available for the service " + serviceKey + " from the url " + invoker.getUrl() + " to the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion());
|
||||
}
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Refer dubbo service " + interfaceClass.getName() + " from url " + invoker.getUrl());
|
||||
|
|
@ -534,14 +549,25 @@ public class ReferenceConfig<T> extends AbstractReferenceConfig {
|
|||
@Parameter(excluded = true)
|
||||
public String getUniqueServiceName() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
String group = getGroup();
|
||||
if (group != null && group.length() > 0) {
|
||||
buf.append(group).append("/");
|
||||
}
|
||||
buf.append(interfaceName);
|
||||
String version = getVersion();
|
||||
if (version != null && version.length() > 0) {
|
||||
buf.append(":").append(version);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return StringUtils.isEmpty(this.version) ? (consumer != null ? consumer.getVersion() : this.version) : this.version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup() {
|
||||
return StringUtils.isEmpty(this.group) ? (consumer != null ? consumer.getGroup() : this.group) : this.group;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,11 +30,12 @@ import com.alibaba.dubbo.config.invoker.DelegateProviderMetaDataInvoker;
|
|||
import com.alibaba.dubbo.config.model.ApplicationModel;
|
||||
import com.alibaba.dubbo.config.model.ProviderModel;
|
||||
import com.alibaba.dubbo.config.support.Parameter;
|
||||
import com.alibaba.dubbo.remoting.transport.CodecSupport;
|
||||
import com.alibaba.dubbo.rpc.Exporter;
|
||||
import com.alibaba.dubbo.rpc.Invoker;
|
||||
import com.alibaba.dubbo.rpc.Protocol;
|
||||
import com.alibaba.dubbo.rpc.ProxyFactory;
|
||||
import com.alibaba.dubbo.rpc.ServiceClassHolder;
|
||||
import com.alibaba.dubbo.rpc.StaticContext;
|
||||
import com.alibaba.dubbo.rpc.cluster.ConfiguratorFactory;
|
||||
import com.alibaba.dubbo.rpc.service.GenericService;
|
||||
import com.alibaba.dubbo.rpc.support.ProtocolUtils;
|
||||
|
|
@ -101,6 +102,7 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
|
|||
|
||||
public ServiceConfig(Service service) {
|
||||
appendAnnotation(Service.class, service);
|
||||
setMethods(MethodConfig.constructMethodConfig(service.methods()));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
|
|
@ -310,11 +312,13 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
|
|||
checkRegistry();
|
||||
checkProtocol();
|
||||
appendProperties(this);
|
||||
checkStubAndMock(interfaceClass);
|
||||
checkStub(interfaceClass);
|
||||
checkMock(interfaceClass);
|
||||
if (path == null || path.length() == 0) {
|
||||
path = interfaceName;
|
||||
}
|
||||
doExportUrls();
|
||||
CodecSupport.addProviderSupportedSerialization(getUniqueServiceName(), getExportedUrls());
|
||||
ProviderModel providerModel = new ProviderModel(getUniqueServiceName(), this, ref);
|
||||
ApplicationModel.initProviderModel(getUniqueServiceName(), providerModel);
|
||||
}
|
||||
|
|
@ -532,7 +536,7 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
|
|||
.setProtocol(Constants.LOCAL_PROTOCOL)
|
||||
.setHost(LOCALHOST)
|
||||
.setPort(0);
|
||||
ServiceClassHolder.getInstance().pushServiceClass(getServiceClass(ref));
|
||||
StaticContext.getContext(Constants.SERVICE_IMPL_CLASS).put(url.getServiceKey(), getServiceClass(ref));
|
||||
Exporter<?> exporter = protocol.export(
|
||||
proxyFactory.getInvoker(ref, (Class) interfaceClass, local));
|
||||
exporters.add(exporter);
|
||||
|
|
@ -819,6 +823,16 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMock(Boolean mock) {
|
||||
throw new IllegalArgumentException("mock doesn't support on provider side");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMock(String mock) {
|
||||
throw new IllegalArgumentException("mock doesn't support on provider side");
|
||||
}
|
||||
|
||||
public List<URL> getExportedUrls() {
|
||||
return urls;
|
||||
}
|
||||
|
|
@ -842,13 +856,25 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
|
|||
@Parameter(excluded = true)
|
||||
public String getUniqueServiceName() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
String group = getGroup();
|
||||
if (group != null && group.length() > 0) {
|
||||
buf.append(group).append("/");
|
||||
}
|
||||
buf.append(interfaceName);
|
||||
String version = getVersion();
|
||||
if (version != null && version.length() > 0) {
|
||||
buf.append(":").append(version);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return StringUtils.isEmpty(this.version) ? (provider != null ? provider.getVersion() : this.version) : this.version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroup() {
|
||||
return StringUtils.isEmpty(this.group) ? (provider != null ? provider.getGroup() : this.group) : this.group;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,33 +14,31 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.dubbo.config.spring.convert.converter;
|
||||
package com.alibaba.dubbo.config.annotation;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* {@link StringArrayToStringConverter} Test
|
||||
* @since 2.6.5
|
||||
*
|
||||
* 2018/9/29
|
||||
*/
|
||||
public class StringArrayToStringConverterTest {
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.ANNOTATION_TYPE})
|
||||
@Inherited
|
||||
public @interface Argument {
|
||||
//argument: index -1 represents not set
|
||||
int index() default -1;
|
||||
|
||||
@Test
|
||||
public void testConvert() {
|
||||
|
||||
StringArrayToStringConverter converter = new StringArrayToStringConverter();
|
||||
|
||||
String value = converter.convert(new String[]{"Hello", "World"});
|
||||
|
||||
Assert.assertEquals("Hello,World", value);
|
||||
|
||||
value = converter.convert(new String[]{});
|
||||
|
||||
Assert.assertNull(value);
|
||||
|
||||
value = converter.convert(null);
|
||||
|
||||
Assert.assertNull(value);
|
||||
|
||||
}
|
||||
//argument type
|
||||
String type() default "";
|
||||
|
||||
//callback interface
|
||||
boolean callback() default false;
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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 com.alibaba.dubbo.config.annotation;
|
||||
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @since 2.6.5
|
||||
* *
|
||||
* * 2018/9/29
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.ANNOTATION_TYPE})
|
||||
@Inherited
|
||||
public @interface Method {
|
||||
String name();
|
||||
|
||||
int timeout() default -1;
|
||||
|
||||
int retries() default -1;
|
||||
|
||||
String loadbalance() default "";
|
||||
|
||||
boolean async() default false;
|
||||
|
||||
boolean sent() default true;
|
||||
|
||||
int actives() default 0;
|
||||
|
||||
int executes() default 0;
|
||||
|
||||
boolean deprecated() default false;
|
||||
|
||||
boolean sticky() default false;
|
||||
|
||||
boolean isReturn() default true;
|
||||
|
||||
String oninvoke() default "";
|
||||
|
||||
String onreturn() default "";
|
||||
|
||||
String onthrow() default "";
|
||||
|
||||
String cache() default "";
|
||||
|
||||
String validation() default "";
|
||||
|
||||
Argument[] arguments() default {};
|
||||
}
|
||||
|
|
@ -1,115 +1,125 @@
|
|||
/*
|
||||
* 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 com.alibaba.dubbo.config.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Reference
|
||||
*
|
||||
* @export
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||
public @interface Reference {
|
||||
|
||||
Class<?> interfaceClass() default void.class;
|
||||
|
||||
String interfaceName() default "";
|
||||
|
||||
String version() default "";
|
||||
|
||||
String group() default "";
|
||||
|
||||
String url() default "";
|
||||
|
||||
String client() default "";
|
||||
|
||||
boolean generic() default false;
|
||||
|
||||
boolean injvm() default false;
|
||||
|
||||
boolean check() default true;
|
||||
|
||||
boolean init() default false;
|
||||
|
||||
boolean lazy() default false;
|
||||
|
||||
boolean stubevent() default false;
|
||||
|
||||
String reconnect() default "";
|
||||
|
||||
boolean sticky() default false;
|
||||
|
||||
String proxy() default "";
|
||||
|
||||
String stub() default "";
|
||||
|
||||
String cluster() default "";
|
||||
|
||||
int connections() default 0;
|
||||
|
||||
int callbacks() default 0;
|
||||
|
||||
String onconnect() default "";
|
||||
|
||||
String ondisconnect() default "";
|
||||
|
||||
String owner() default "";
|
||||
|
||||
String layer() default "";
|
||||
|
||||
int retries() default 0;
|
||||
|
||||
String loadbalance() default "";
|
||||
|
||||
boolean async() default false;
|
||||
|
||||
int actives() default 0;
|
||||
|
||||
boolean sent() default false;
|
||||
|
||||
String mock() default "";
|
||||
|
||||
String validation() default "";
|
||||
|
||||
int timeout() default 0;
|
||||
|
||||
String cache() default "";
|
||||
|
||||
String[] filter() default {};
|
||||
|
||||
String[] listener() default {};
|
||||
|
||||
String[] parameters() default {};
|
||||
|
||||
String application() default "";
|
||||
|
||||
String module() default "";
|
||||
|
||||
String consumer() default "";
|
||||
|
||||
String monitor() default "";
|
||||
|
||||
String[] registry() default {};
|
||||
|
||||
}
|
||||
/*
|
||||
* 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 com.alibaba.dubbo.config.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Reference
|
||||
*
|
||||
* @export
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||
public @interface Reference {
|
||||
|
||||
Class<?> interfaceClass() default void.class;
|
||||
|
||||
String interfaceName() default "";
|
||||
|
||||
String version() default "";
|
||||
|
||||
String group() default "";
|
||||
|
||||
String url() default "";
|
||||
|
||||
String client() default "";
|
||||
|
||||
boolean generic() default false;
|
||||
|
||||
boolean injvm() default false;
|
||||
|
||||
boolean check() default true;
|
||||
|
||||
boolean init() default false;
|
||||
|
||||
boolean lazy() default false;
|
||||
|
||||
boolean stubevent() default false;
|
||||
|
||||
String reconnect() default "";
|
||||
|
||||
boolean sticky() default false;
|
||||
|
||||
String proxy() default "";
|
||||
|
||||
String stub() default "";
|
||||
|
||||
String cluster() default "";
|
||||
|
||||
int connections() default 0;
|
||||
|
||||
int callbacks() default 0;
|
||||
|
||||
String onconnect() default "";
|
||||
|
||||
String ondisconnect() default "";
|
||||
|
||||
String owner() default "";
|
||||
|
||||
String layer() default "";
|
||||
|
||||
int retries() default 2;
|
||||
|
||||
String loadbalance() default "";
|
||||
|
||||
boolean async() default false;
|
||||
|
||||
int actives() default 0;
|
||||
|
||||
boolean sent() default false;
|
||||
|
||||
String mock() default "";
|
||||
|
||||
String validation() default "";
|
||||
|
||||
int timeout() default 0;
|
||||
|
||||
String cache() default "";
|
||||
|
||||
String[] filter() default {};
|
||||
|
||||
String[] listener() default {};
|
||||
|
||||
String[] parameters() default {};
|
||||
|
||||
String application() default "";
|
||||
|
||||
String module() default "";
|
||||
|
||||
String consumer() default "";
|
||||
|
||||
String monitor() default "";
|
||||
|
||||
String[] registry() default {};
|
||||
|
||||
/**
|
||||
* The communication protocol of Dubbo Service
|
||||
*
|
||||
* @return the default value is ""
|
||||
* @since 2.6.6
|
||||
*/
|
||||
String protocol() default "";
|
||||
|
||||
Method[] methods() default {};
|
||||
|
||||
}
|
||||
|
|
@ -1,123 +1,127 @@
|
|||
/*
|
||||
* 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 com.alibaba.dubbo.config.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Service
|
||||
*
|
||||
* @export
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
@Inherited
|
||||
public @interface Service {
|
||||
|
||||
Class<?> interfaceClass() default void.class;
|
||||
|
||||
String interfaceName() default "";
|
||||
|
||||
String version() default "";
|
||||
|
||||
String group() default "";
|
||||
|
||||
String path() default "";
|
||||
|
||||
boolean export() default false;
|
||||
|
||||
String token() default "";
|
||||
|
||||
boolean deprecated() default false;
|
||||
|
||||
boolean dynamic() default false;
|
||||
|
||||
String accesslog() default "";
|
||||
|
||||
int executes() default 0;
|
||||
|
||||
boolean register() default false;
|
||||
|
||||
int weight() default 0;
|
||||
|
||||
String document() default "";
|
||||
|
||||
int delay() default 0;
|
||||
|
||||
String local() default "";
|
||||
|
||||
String stub() default "";
|
||||
|
||||
String cluster() default "";
|
||||
|
||||
String proxy() default "";
|
||||
|
||||
int connections() default 0;
|
||||
|
||||
int callbacks() default 0;
|
||||
|
||||
String onconnect() default "";
|
||||
|
||||
String ondisconnect() default "";
|
||||
|
||||
String owner() default "";
|
||||
|
||||
String layer() default "";
|
||||
|
||||
int retries() default 0;
|
||||
|
||||
String loadbalance() default "";
|
||||
|
||||
boolean async() default false;
|
||||
|
||||
int actives() default 0;
|
||||
|
||||
boolean sent() default false;
|
||||
|
||||
String mock() default "";
|
||||
|
||||
String validation() default "";
|
||||
|
||||
int timeout() default 0;
|
||||
|
||||
String cache() default "";
|
||||
|
||||
String[] filter() default {};
|
||||
|
||||
String[] listener() default {};
|
||||
|
||||
String[] parameters() default {};
|
||||
|
||||
String application() default "";
|
||||
|
||||
String module() default "";
|
||||
|
||||
String provider() default "";
|
||||
|
||||
String[] protocol() default {};
|
||||
|
||||
String monitor() default "";
|
||||
|
||||
String[] registry() default {};
|
||||
|
||||
}
|
||||
/*
|
||||
* 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 com.alibaba.dubbo.config.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Service
|
||||
*
|
||||
* @export
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
@Inherited
|
||||
public @interface Service {
|
||||
|
||||
Class<?> interfaceClass() default void.class;
|
||||
|
||||
String interfaceName() default "";
|
||||
|
||||
String version() default "";
|
||||
|
||||
String group() default "";
|
||||
|
||||
String path() default "";
|
||||
|
||||
boolean export() default false;
|
||||
|
||||
String token() default "";
|
||||
|
||||
boolean deprecated() default false;
|
||||
|
||||
boolean dynamic() default false;
|
||||
|
||||
String accesslog() default "";
|
||||
|
||||
int executes() default 0;
|
||||
|
||||
boolean register() default true;
|
||||
|
||||
int weight() default 0;
|
||||
|
||||
String document() default "";
|
||||
|
||||
int delay() default 0;
|
||||
|
||||
String local() default "";
|
||||
|
||||
String stub() default "";
|
||||
|
||||
String cluster() default "";
|
||||
|
||||
String proxy() default "";
|
||||
|
||||
int connections() default 0;
|
||||
|
||||
int callbacks() default 0;
|
||||
|
||||
String onconnect() default "";
|
||||
|
||||
String ondisconnect() default "";
|
||||
|
||||
String owner() default "";
|
||||
|
||||
String layer() default "";
|
||||
|
||||
int retries() default 0;
|
||||
|
||||
String loadbalance() default "";
|
||||
|
||||
boolean async() default false;
|
||||
|
||||
int actives() default 0;
|
||||
|
||||
boolean sent() default false;
|
||||
|
||||
String mock() default "";
|
||||
|
||||
String validation() default "";
|
||||
|
||||
int timeout() default 0;
|
||||
|
||||
String cache() default "";
|
||||
|
||||
String[] filter() default {};
|
||||
|
||||
String[] listener() default {};
|
||||
|
||||
String[] parameters() default {};
|
||||
|
||||
String application() default "";
|
||||
|
||||
String module() default "";
|
||||
|
||||
String provider() default "";
|
||||
|
||||
String[] protocol() default {};
|
||||
|
||||
String monitor() default "";
|
||||
|
||||
String[] registry() default {};
|
||||
|
||||
String tag() default "";
|
||||
|
||||
Method[] methods() default {};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import com.alibaba.dubbo.common.utils.ConfigUtils;
|
|||
import com.alibaba.dubbo.config.api.Greeting;
|
||||
import com.alibaba.dubbo.config.support.Parameter;
|
||||
import junit.framework.TestCase;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
|
|
@ -32,6 +33,8 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
public class AbstractConfigTest {
|
||||
|
||||
@Test
|
||||
|
|
@ -195,7 +198,8 @@ public class AbstractConfigTest {
|
|||
@Test
|
||||
public void checkNameHasSymbol() throws Exception {
|
||||
try {
|
||||
AbstractConfig.checkNameHasSymbol("hello", ":*,/-0123abcdABCD");
|
||||
AbstractConfig.checkNameHasSymbol("hello", ":*,/ -0123\tabcdABCD");
|
||||
AbstractConfig.checkNameHasSymbol("mock", "force:return world");
|
||||
} catch (Exception e) {
|
||||
TestCase.fail("the value should be legal.");
|
||||
}
|
||||
|
|
@ -267,8 +271,8 @@ public class AbstractConfigTest {
|
|||
TestCase.assertEquals(2, annotationConfig.getParameters().size());
|
||||
TestCase.assertEquals("v1", annotationConfig.getParameters().get("k1"));
|
||||
TestCase.assertEquals("v2", annotationConfig.getParameters().get("k2"));
|
||||
TestCase.assertEquals("<dubbo:annotation filter=\"f1, f2\" listener=\"l1, l2\" />",
|
||||
annotationConfig.toString());
|
||||
assertThat(annotationConfig.toString(), Matchers.containsString("filter=\"f1, f2\" "));
|
||||
assertThat(annotationConfig.toString(), Matchers.containsString("listener=\"l1, l2\" "));
|
||||
}
|
||||
|
||||
private static class PropertiesConfig extends AbstractConfig {
|
||||
|
|
@ -471,6 +475,16 @@ public class AbstractConfigTest {
|
|||
String[] listener() default {};
|
||||
|
||||
String[] parameters() default {};
|
||||
|
||||
ConfigField[] configFields() default {};
|
||||
|
||||
ConfigField configField() default @ConfigField;
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.ANNOTATION_TYPE})
|
||||
public @interface ConfigField {
|
||||
String value() default "";
|
||||
}
|
||||
|
||||
private static class AnnotationConfig extends AbstractConfig {
|
||||
|
|
@ -478,6 +492,7 @@ public class AbstractConfigTest {
|
|||
private String filter;
|
||||
private String listener;
|
||||
private Map<String, String> parameters;
|
||||
private String[] configFields;
|
||||
|
||||
public Class getInterface() {
|
||||
return interfaceClass;
|
||||
|
|
@ -510,5 +525,13 @@ public class AbstractConfigTest {
|
|||
public void setParameters(Map<String, String> parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public String[] getConfigFields() {
|
||||
return configFields;
|
||||
}
|
||||
|
||||
public void setConfigFields(String[] configFields) {
|
||||
this.configFields = configFields;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ public class AbstractInterfaceConfigTest {
|
|||
interfaceConfig.checkApplication();
|
||||
ApplicationConfig appConfig = interfaceConfig.getApplication();
|
||||
TestCase.assertEquals("demo", appConfig.getName());
|
||||
TestCase.assertEquals("100", System.getProperty(Constants.SHUTDOWN_WAIT_KEY));
|
||||
TestCase.assertEquals("100", ConfigUtils.getProperty(Constants.SHUTDOWN_WAIT_KEY));
|
||||
|
||||
System.clearProperty(Constants.SHUTDOWN_WAIT_KEY);
|
||||
ConfigUtils.setProperties(null);
|
||||
|
|
@ -178,63 +178,72 @@ public class AbstractInterfaceConfigTest {
|
|||
public void checkStubAndMock1() throws Exception {
|
||||
InterfaceConfig interfaceConfig = new InterfaceConfig();
|
||||
interfaceConfig.setLocal(GreetingLocal1.class.getName());
|
||||
interfaceConfig.checkStubAndMock(Greeting.class);
|
||||
interfaceConfig.checkStub(Greeting.class);
|
||||
interfaceConfig.checkMock(Greeting.class);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void checkStubAndMock2() throws Exception {
|
||||
InterfaceConfig interfaceConfig = new InterfaceConfig();
|
||||
interfaceConfig.setLocal(GreetingLocal2.class.getName());
|
||||
interfaceConfig.checkStubAndMock(Greeting.class);
|
||||
interfaceConfig.checkStub(Greeting.class);
|
||||
interfaceConfig.checkMock(Greeting.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkStubAndMock3() throws Exception {
|
||||
InterfaceConfig interfaceConfig = new InterfaceConfig();
|
||||
interfaceConfig.setLocal(GreetingLocal3.class.getName());
|
||||
interfaceConfig.checkStubAndMock(Greeting.class);
|
||||
interfaceConfig.checkStub(Greeting.class);
|
||||
interfaceConfig.checkMock(Greeting.class);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void checkStubAndMock4() throws Exception {
|
||||
InterfaceConfig interfaceConfig = new InterfaceConfig();
|
||||
interfaceConfig.setStub(GreetingLocal1.class.getName());
|
||||
interfaceConfig.checkStubAndMock(Greeting.class);
|
||||
interfaceConfig.checkStub(Greeting.class);
|
||||
interfaceConfig.checkMock(Greeting.class);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void checkStubAndMock5() throws Exception {
|
||||
InterfaceConfig interfaceConfig = new InterfaceConfig();
|
||||
interfaceConfig.setStub(GreetingLocal2.class.getName());
|
||||
interfaceConfig.checkStubAndMock(Greeting.class);
|
||||
interfaceConfig.checkStub(Greeting.class);
|
||||
interfaceConfig.checkMock(Greeting.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkStubAndMock6() throws Exception {
|
||||
InterfaceConfig interfaceConfig = new InterfaceConfig();
|
||||
interfaceConfig.setStub(GreetingLocal3.class.getName());
|
||||
interfaceConfig.checkStubAndMock(Greeting.class);
|
||||
interfaceConfig.checkStub(Greeting.class);
|
||||
interfaceConfig.checkMock(Greeting.class);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void checkStubAndMock7() throws Exception {
|
||||
InterfaceConfig interfaceConfig = new InterfaceConfig();
|
||||
interfaceConfig.setMock("return {a, b}");
|
||||
interfaceConfig.checkStubAndMock(Greeting.class);
|
||||
interfaceConfig.checkStub(Greeting.class);
|
||||
interfaceConfig.checkMock(Greeting.class);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void checkStubAndMock8() throws Exception {
|
||||
InterfaceConfig interfaceConfig = new InterfaceConfig();
|
||||
interfaceConfig.setMock(GreetingMock1.class.getName());
|
||||
interfaceConfig.checkStubAndMock(Greeting.class);
|
||||
interfaceConfig.checkStub(Greeting.class);
|
||||
interfaceConfig.checkMock(Greeting.class);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void checkStubAndMock9() throws Exception {
|
||||
InterfaceConfig interfaceConfig = new InterfaceConfig();
|
||||
interfaceConfig.setMock(GreetingMock2.class.getName());
|
||||
interfaceConfig.checkStubAndMock(Greeting.class);
|
||||
interfaceConfig.checkStub(Greeting.class);
|
||||
interfaceConfig.checkMock(Greeting.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -386,6 +395,7 @@ public class AbstractInterfaceConfigTest {
|
|||
Properties properties = new Properties();
|
||||
properties.put(key, value);
|
||||
properties.store(os, "");
|
||||
os.flush();
|
||||
os.close();
|
||||
} catch (IOException e) {
|
||||
if (os != null) {
|
||||
|
|
|
|||
|
|
@ -35,6 +35,13 @@ public class AbstractMethodConfigTest {
|
|||
assertThat(methodConfig.getTimeout(), equalTo(10));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForks() throws Exception {
|
||||
MethodConfig methodConfig = new MethodConfig();
|
||||
methodConfig.setForks(10);
|
||||
assertThat(methodConfig.getForks(), equalTo(10));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetries() throws Exception {
|
||||
MethodConfig methodConfig = new MethodConfig();
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package com.alibaba.dubbo.config;
|
||||
|
||||
import com.alibaba.dubbo.config.annotation.Argument;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
|
|
|||
|
|
@ -50,4 +50,32 @@ public class ConsumerConfigTest {
|
|||
consumer.setClient("client");
|
||||
assertThat(consumer.getClient(), equalTo("client"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThreadpool() throws Exception {
|
||||
ConsumerConfig consumer = new ConsumerConfig();
|
||||
consumer.setThreadpool("fixed");
|
||||
assertThat(consumer.getThreadpool(), equalTo("fixed"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorethreads() throws Exception {
|
||||
ConsumerConfig consumer = new ConsumerConfig();
|
||||
consumer.setCorethreads(10);
|
||||
assertThat(consumer.getCorethreads(), equalTo(10));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThreads() throws Exception {
|
||||
ConsumerConfig consumer = new ConsumerConfig();
|
||||
consumer.setThreads(20);
|
||||
assertThat(consumer.getThreads(), equalTo(20));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueues() throws Exception {
|
||||
ConsumerConfig consumer = new ConsumerConfig();
|
||||
consumer.setQueues(5);
|
||||
assertThat(consumer.getQueues(), equalTo(5));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import com.alibaba.dubbo.rpc.service.GenericException;
|
|||
import com.alibaba.dubbo.rpc.service.GenericService;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
|
@ -46,6 +47,11 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||
*/
|
||||
public class GenericServiceTest {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
System.setProperty(Constants.ENABLE_NATIVE_JAVA_GENERIC_SERIALIZE, "true");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenericServiceException() {
|
||||
ServiceConfig<GenericService> service = new ServiceConfig<GenericService>();
|
||||
|
|
@ -74,7 +80,7 @@ public class GenericServiceTest {
|
|||
ReferenceConfig<DemoService> reference = new ReferenceConfig<DemoService>();
|
||||
reference.setApplication(new ApplicationConfig("generic-consumer"));
|
||||
reference.setInterface(DemoService.class);
|
||||
reference.setUrl("dubbo://127.0.0.1:29581?generic=true");
|
||||
reference.setUrl("dubbo://127.0.0.1:29581?generic=true&timeout=3000");
|
||||
DemoService demoService = reference.get();
|
||||
try {
|
||||
// say name
|
||||
|
|
@ -113,7 +119,7 @@ public class GenericServiceTest {
|
|||
ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
|
||||
reference.setApplication(new ApplicationConfig("generic-consumer"));
|
||||
reference.setInterface(DemoService.class);
|
||||
reference.setUrl("dubbo://127.0.0.1:29581?scope=remote");
|
||||
reference.setUrl("dubbo://127.0.0.1:29581?scope=remote&timeout=3000");
|
||||
reference.setGeneric(true);
|
||||
GenericService genericService = reference.get();
|
||||
try {
|
||||
|
|
@ -147,7 +153,7 @@ public class GenericServiceTest {
|
|||
ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
|
||||
reference.setApplication(new ApplicationConfig("generic-consumer"));
|
||||
reference.setInterface(DemoService.class);
|
||||
reference.setUrl("dubbo://127.0.0.1:29581?scope=remote");
|
||||
reference.setUrl("dubbo://127.0.0.1:29581?scope=remote&timeout=3000");
|
||||
reference.setGeneric(Constants.GENERIC_SERIALIZATION_NATIVE_JAVA);
|
||||
GenericService genericService = reference.get();
|
||||
try {
|
||||
|
|
@ -216,7 +222,7 @@ public class GenericServiceTest {
|
|||
reference = new ReferenceConfig<GenericService>();
|
||||
reference.setApplication(new ApplicationConfig("bean-consumer"));
|
||||
reference.setInterface(DemoService.class);
|
||||
reference.setUrl("dubbo://127.0.0.1:29581?scope=remote");
|
||||
reference.setUrl("dubbo://127.0.0.1:29581?scope=remote&timeout=3000");
|
||||
reference.setGeneric(Constants.GENERIC_SERIALIZATION_BEAN);
|
||||
GenericService genericService = reference.get();
|
||||
User user = new User();
|
||||
|
|
@ -270,7 +276,7 @@ public class GenericServiceTest {
|
|||
ref = new ReferenceConfig<DemoService>();
|
||||
ref.setApplication(new ApplicationConfig("bean-consumer"));
|
||||
ref.setInterface(DemoService.class);
|
||||
ref.setUrl("dubbo://127.0.0.1:29581?scope=remote&generic=bean");
|
||||
ref.setUrl("dubbo://127.0.0.1:29581?scope=remote&generic=bean&timeout=3000");
|
||||
DemoService demoService = ref.get();
|
||||
User user = new User();
|
||||
user.setName("zhangsan");
|
||||
|
|
|
|||
|
|
@ -18,11 +18,16 @@
|
|||
package com.alibaba.dubbo.config;
|
||||
|
||||
import com.alibaba.dubbo.common.Constants;
|
||||
import com.alibaba.dubbo.config.annotation.Argument;
|
||||
import com.alibaba.dubbo.config.annotation.Method;
|
||||
import com.alibaba.dubbo.config.annotation.Reference;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
|
|
@ -34,6 +39,54 @@ import static org.hamcrest.Matchers.not;
|
|||
import static org.junit.Assert.assertThat;
|
||||
|
||||
public class MethodConfigTest {
|
||||
private static final String METHOD_NAME = "sayHello";
|
||||
private static final int TIMEOUT = 1300;
|
||||
private static final int RETRIES = 4;
|
||||
private static final String LOADBALANCE = "random";
|
||||
private static final boolean ASYNC = true;
|
||||
private static final int ACTIVES = 3;
|
||||
private static final int EXECUTES = 5;
|
||||
private static final boolean DEPERECATED = true;
|
||||
private static final boolean STICKY = true;
|
||||
private static final String ONINVOKE = "i";
|
||||
private static final String ONTHROW = "t";
|
||||
private static final String ONRETURN = "r";
|
||||
private static final String CACHE = "c";
|
||||
private static final String VALIDATION = "v";
|
||||
private static final int ARGUMENTS_INDEX = 24;
|
||||
private static final boolean ARGUMENTS_CALLBACK = true;
|
||||
private static final String ARGUMENTS_TYPE = "sss";
|
||||
|
||||
@Reference(methods = {@Method(name = METHOD_NAME, timeout = TIMEOUT, retries = RETRIES, loadbalance = LOADBALANCE, async = ASYNC,
|
||||
actives = ACTIVES, executes = EXECUTES, deprecated = DEPERECATED, sticky = STICKY, oninvoke = ONINVOKE, onthrow = ONTHROW, onreturn = ONRETURN, cache = CACHE, validation = VALIDATION,
|
||||
arguments = {@Argument(index = ARGUMENTS_INDEX, callback = ARGUMENTS_CALLBACK, type = ARGUMENTS_TYPE)})})
|
||||
private String testField;
|
||||
|
||||
@Test
|
||||
public void testStaticConstructor() throws NoSuchFieldException {
|
||||
Method[] methods = this.getClass().getDeclaredField("testField").getAnnotation(Reference.class).methods();
|
||||
List<MethodConfig> methodConfigs = MethodConfig.constructMethodConfig(methods);
|
||||
MethodConfig methodConfig = methodConfigs.get(0);
|
||||
|
||||
Assert.assertEquals(METHOD_NAME, methodConfig.getName());
|
||||
Assert.assertEquals(methodConfig.getTimeout().intValue(), TIMEOUT);
|
||||
Assert.assertEquals(RETRIES, methodConfig.getRetries().intValue());
|
||||
Assert.assertEquals(LOADBALANCE, methodConfig.getLoadbalance());
|
||||
Assert.assertEquals(ASYNC, methodConfig.isAsync());
|
||||
Assert.assertEquals(ACTIVES, methodConfig.getActives().intValue());
|
||||
Assert.assertEquals(EXECUTES, methodConfig.getExecutes().intValue());
|
||||
Assert.assertEquals(DEPERECATED, methodConfig.getDeprecated());
|
||||
Assert.assertEquals(STICKY, methodConfig.getSticky());
|
||||
Assert.assertEquals(ONINVOKE, methodConfig.getOninvoke());
|
||||
Assert.assertEquals(ONTHROW, methodConfig.getOnthrow());
|
||||
Assert.assertEquals(ONRETURN, methodConfig.getOnreturn());
|
||||
Assert.assertEquals(CACHE, methodConfig.getCache());
|
||||
Assert.assertEquals(VALIDATION, methodConfig.getValidation());
|
||||
Assert.assertEquals(ARGUMENTS_INDEX, methodConfig.getArguments().get(0).getIndex().intValue());
|
||||
Assert.assertEquals(ARGUMENTS_CALLBACK, methodConfig.getArguments().get(0).isCallback());
|
||||
Assert.assertEquals(ARGUMENTS_TYPE, methodConfig.getArguments().get(0).getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testName() throws Exception {
|
||||
MethodConfig method = new MethodConfig();
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@
|
|||
package com.alibaba.dubbo.config;
|
||||
|
||||
import com.alibaba.dubbo.common.Constants;
|
||||
import com.alibaba.dubbo.config.annotation.Argument;
|
||||
import com.alibaba.dubbo.config.annotation.Method;
|
||||
import com.alibaba.dubbo.config.annotation.Reference;
|
||||
import com.alibaba.dubbo.config.api.DemoService;
|
||||
import com.alibaba.dubbo.config.provider.impl.DemoServiceImpl;
|
||||
|
||||
|
|
@ -60,4 +63,73 @@ public class ReferenceConfigTest {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
@Test
|
||||
public void testConstructWithReferenceAnnotation() throws NoSuchFieldException {
|
||||
Reference reference = getClass().getDeclaredField("innerTest").getAnnotation(Reference.class);
|
||||
ReferenceConfig referenceConfig = new ReferenceConfig(reference);
|
||||
Assert.assertTrue(referenceConfig.getMethods().size() == 1);
|
||||
Assert.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getName(), "sayHello");
|
||||
Assert.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).getTimeout() == 1300);
|
||||
Assert.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).getRetries() == 4);
|
||||
Assert.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getLoadbalance(), "random");
|
||||
Assert.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).getActives() == 3);
|
||||
Assert.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).getExecutes() == 5);
|
||||
Assert.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).isAsync());
|
||||
Assert.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOninvoke(), "i");
|
||||
Assert.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOnreturn(), "r");
|
||||
Assert.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOnthrow(), "t");
|
||||
Assert.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getCache(), "c");
|
||||
}
|
||||
|
||||
|
||||
@Reference(methods = {@Method(name = "sayHello", timeout = 1300, retries = 4, loadbalance = "random", async = true,
|
||||
actives = 3, executes = 5, deprecated = true, sticky = true, oninvoke = "i", onthrow = "t", onreturn = "r", cache = "c", validation = "v",
|
||||
arguments = {@Argument(index = 24, callback = true, type = "sss")})})
|
||||
private InnerTest innerTest;
|
||||
|
||||
private class InnerTest {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* unit test for dubbo-1765
|
||||
*/
|
||||
@Test
|
||||
public void testReferenceRetry() {
|
||||
ApplicationConfig application = new ApplicationConfig();
|
||||
application.setName("test-reference-retry");
|
||||
RegistryConfig registry = new RegistryConfig();
|
||||
registry.setAddress("multicast://224.5.6.7:1234");
|
||||
ProtocolConfig protocol = new ProtocolConfig();
|
||||
protocol.setName("dubbo");
|
||||
ReferenceConfig<DemoService> rc = new ReferenceConfig<DemoService>();
|
||||
rc.setApplication(application);
|
||||
rc.setRegistry(registry);
|
||||
rc.setInterface(DemoService.class.getName());
|
||||
boolean success = false;
|
||||
DemoService demoService = null;
|
||||
try {
|
||||
demoService = rc.get();
|
||||
success = true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Assert.assertFalse(success);
|
||||
Assert.assertNull(demoService);
|
||||
ServiceConfig<DemoService> sc = new ServiceConfig<DemoService>();
|
||||
sc.setInterface(DemoService.class);
|
||||
sc.setRef(new DemoServiceImpl());
|
||||
sc.setApplication(application);
|
||||
sc.setRegistry(registry);
|
||||
sc.setProtocol(protocol);
|
||||
try {
|
||||
sc.export();
|
||||
demoService = rc.get();
|
||||
success = true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Assert.assertTrue(success);
|
||||
Assert.assertNotNull(demoService);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ public class RegistryConfigTest {
|
|||
registry.setWait(10);
|
||||
assertThat(registry.getWait(), is(10));
|
||||
assertThat(System.getProperty(Constants.SHUTDOWN_WAIT_KEY), equalTo("10"));
|
||||
System.clearProperty(Constants.SHUTDOWN_WAIT_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -194,6 +194,18 @@ public class ServiceConfigTest {
|
|||
service.setGeneric("illegal");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMock() throws Exception {
|
||||
ServiceConfig service = new ServiceConfig();
|
||||
service.setMock("true");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMock2() throws Exception {
|
||||
ServiceConfig service = new ServiceConfig();
|
||||
service.setMock(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUniqueServiceName() throws Exception {
|
||||
ServiceConfig<Greeting> service = new ServiceConfig<Greeting>();
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ public class CacheTest extends TestCase {
|
|||
ServiceConfig<CacheService> service = new ServiceConfig<CacheService>();
|
||||
service.setApplication(new ApplicationConfig("cache-provider"));
|
||||
service.setRegistry(new RegistryConfig("N/A"));
|
||||
service.setProtocol(new ProtocolConfig("dubbo", 29582));
|
||||
service.setProtocol(new ProtocolConfig("injvm"));
|
||||
service.setInterface(CacheService.class.getName());
|
||||
service.setRef(new CacheServiceImpl());
|
||||
service.export();
|
||||
|
|
@ -54,7 +54,7 @@ public class CacheTest extends TestCase {
|
|||
ReferenceConfig<CacheService> reference = new ReferenceConfig<CacheService>();
|
||||
reference.setApplication(new ApplicationConfig("cache-consumer"));
|
||||
reference.setInterface(CacheService.class);
|
||||
reference.setUrl("dubbo://127.0.0.1:29582?scope=remote&cache=true");
|
||||
reference.setUrl("injvm://127.0.0.1?scope=remote&cache=true");
|
||||
|
||||
MethodConfig method = new MethodConfig();
|
||||
method.setName("findCache");
|
||||
|
|
|
|||
|
|
@ -1,157 +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.
|
||||
-->
|
||||
<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-config</artifactId>
|
||||
<version>2.6.3-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>dubbo-config-spring</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>The spring config module of dubbo project</description>
|
||||
<properties>
|
||||
<skip_maven_deploy>false</skip_maven_deploy>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-config-api</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-bootstrap</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-registry-default</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-monitor-default</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-rpc-dubbo</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-rpc-rmi</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-rpc-injvm</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-remoting-netty</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-serialization-hessian2</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish</groupId>
|
||||
<artifactId>javax.el</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- upload xsd file command line
|
||||
mvn org.codehaus.mojo:wagon-maven-plugin:1.0-beta-3:upload-single -Dwagon.fromFile=src/main/resources/META-INF/dubbo.xsd -Dwagon.url=dav:http://code.alibabatech.com/schema/dubbo/ -Dwagon.serverId=opensesame.releases.account
|
||||
-->
|
||||
<!--
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>wagon-maven-plugin</artifactId>
|
||||
<version>1.0-beta-3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>upload-schema</id>
|
||||
<phase>deploy</phase>
|
||||
<goals>
|
||||
<goal>upload-single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<fromFile>${basedir}/src/main/resources/META-INF/dubbo.xsd</fromFile>
|
||||
<url>dav:http://code.alibabatech.com/schema/dubbo/</url>
|
||||
<serverId>opensesame.releases.account</serverId>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
-->
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
<!--
|
||||
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>com.alibaba</groupId>
|
||||
<artifactId>dubbo-config</artifactId>
|
||||
<version>2.6.13-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>dubbo-config-spring</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>The spring config module of dubbo project</description>
|
||||
<properties>
|
||||
<skip_maven_deploy>false</skip_maven_deploy>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-config-api</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Test -->
|
||||
<!-- Netty -->
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- REST support dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-client</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-netty4</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jackson-provider</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxb-provider</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-registry-default</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-registry-zookeeper</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-monitor-default</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-rpc-dubbo</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-rpc-rest</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-rpc-rmi</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-rpc-injvm</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-remoting-netty4</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo-serialization-hessian2</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish</groupId>
|
||||
<artifactId>javax.el</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Zookeeper -->
|
||||
<dependency>
|
||||
<groupId>org.apache.zookeeper</groupId>
|
||||
<artifactId>zookeeper</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.curator</groupId>
|
||||
<artifactId>curator-framework</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- upload xsd file command line
|
||||
mvn org.codehaus.mojo:wagon-maven-plugin:1.0-beta-3:upload-single -Dwagon.fromFile=src/main/resources/META-INF/dubbo.xsd -Dwagon.url=dav:http://code.alibabatech.com/schema/dubbo/ -Dwagon.serverId=opensesame.releases.account
|
||||
-->
|
||||
<!--
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>wagon-maven-plugin</artifactId>
|
||||
<version>1.0-beta-3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>upload-schema</id>
|
||||
<phase>deploy</phase>
|
||||
<goals>
|
||||
<goal>upload-single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<fromFile>${basedir}/src/main/resources/META-INF/dubbo.xsd</fromFile>
|
||||
<url>dav:http://code.alibabatech.com/schema/dubbo/</url>
|
||||
<serverId>opensesame.releases.account</serverId>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
-->
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue