可以通过check="false"关闭检查,比如,测试时,有些服务不关心,或者出现了循环依赖,必须有一方先启动。
关闭某个服务的启动时检查:(没有提供者时报错)
<
dubbo:reference
interface
=
"com.foo.BarService"
check
=
"false"
/>
|
关闭所有服务的启动时检查:(没有提供者时报错)
<
dubbo:consumer
check
=
"false"
/>
|
关闭注册中心启动时检查:(注册订阅失败时报错)
<
dubbo:registry
check
=
"false"
/>
|
也可以用dubbo.properties配置:
dubbo.reference.com.foo.BarService.check=false
dubbo.reference.check=false
dubbo.consumer.check=false
dubbo.registry.check=false
|
也可以用-D参数:
java -Ddubbo.reference.com.foo.BarService.check=false
java -Ddubbo.reference.check=false
java -Ddubbo.consumer.check=false
java -Ddubbo.registry.check=false
|
引用缺省是延迟初始化的,只有引用被注入到其它Bean,或被getBean()获取,才会初始化。
如果需要饥饿加载,即没有人引用也立即生成动态代理,可以配置:
<
dubbo:reference
interface
=
"com.foo.BarService"
init
=
"true"
/>
|
各节点关系:
可以自行扩展集群容错策略,参见:集群扩展
重试次数配置如:(failover集群模式生效)
<
dubbo:service
retries
=
"2"
/>
|
或:
<
dubbo:reference
retries
=
"2"
/>
|
或:
<
dubbo:reference
>
<
dubbo:method
name
=
"findFoo"
retries
=
"2"
/>
dubbo:reference
>
|
集群模式配置如:
<
dubbo:service
cluster
=
"failsafe"
/>
|
或:
<
dubbo:reference
cluster
=
"failsafe"
/>
|
(+) (#)
可以自行扩展负载均衡策略,参见:负载均衡扩展
配置如:
<
dubbo:service
interface
=
"..."
loadbalance
=
"roundrobin"
/>
|
或:
<
dubbo:reference
interface
=
"..."
loadbalance
=
"roundrobin"
/>
|
或:
<
dubbo:service
interface
=
"..."
>
<
dubbo:method
name
=
"..."
loadbalance
=
"roundrobin"
/>
dubbo:service
>
|
或:
<
dubbo:reference
interface
=
"..."
>
<
dubbo:method
name
=
"..."
loadbalance
=
"roundrobin"
/>
dubbo:reference
>
|
(+) (#)
配置如:
<
dubbo:protocol
name
=
"dubbo"
dispatcher
=
"all"
threadpool
=
"fixed"
threads
=
"100"
/>
|
(+) (#)
在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,
点对点直联方式,将以服务接口为单位,忽略注册中心的提供者列表,
A接口配置点对点,不影响B接口从注册中心获取列表。
(1) 如果是线上需求需要点对点,可在
|
(2) 在JVM启动参数中加入-D参数映射服务地址,如:
(key为服务名,value为服务提供者url,此配置优先级最高,1.0.15及以上版本支持)
java -Dcom.alibaba.xxx.XxxService=dubbo:
//localhost:20890
|
(3) 如果服务比较多,也可以用文件映射,如:
(用-Ddubbo.resolve.file指定映射文件路径,此配置优先级高于
(2.0以上版本自动加载${user.home}/dubbo-resolve.properties文件,不需要配置)
java -Ddubbo.resolve.file=xxx.properties
|
然后在映射文件xxx.properties中加入:
(key为服务名,value为服务提供者url)
com.alibaba.xxx.XxxService=dubbo:
//localhost:20890
|
(+) (#)
禁用注册配置:
<
dubbo:registry
address
=
"10.20.153.10:9090"
register
=
"false"
/>
|
或者:
<
dubbo:registry
address
=
"10.20.153.10:9090?register=false"
/>
|
(+) (#)
禁用订阅配置:
<
dubbo:registry
id
=
"hzRegistry"
address
=
"10.20.153.10:9090"
/>
<
dubbo:registry
id
=
"qdRegistry"
address
=
"10.20.141.150:9090"
subscribe
=
"false"
/>
|
或者:
<
dubbo:registry
id
=
"hzRegistry"
address
=
"10.20.153.10:9090"
/>
<
dubbo:registry
id
=
"qdRegistry"
address
=
"10.20.141.150:9090?subscribe=false"
/>
|
(+) (#)
<
dubbo:registry
address
=
"10.20.141.150:9090"
dynamic
=
"false"
/>
|
或者:
<
dubbo:registry
address
=
"10.20.141.150:9090?dynamic=false"
/>
|
服务提供者初次注册时为禁用状态,需人工启用,断线时,将不会被自动删除,需人工禁用。
如果是一个第三方独立提供者,比如memcached等,可以直接向注册中心写入提供者地址信息,消费者正常使用:
(通常由脚本监控中心页面等调用)
RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.
class
).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf(
"zookeeper://10.20.153.10:2181"
));
registry.register(URL.valueOf(
"memcached://10.20.153.11/com.foo.BarService?category=providers&dynamic=false&application=foo"
));
|
(+) (#)
可以自行扩展协议,参见:协议扩展
比如:不同服务在性能上适用不同协议进行传输,比如大数据用短连接协议,小数据大并发用长连接协议。
|
比如:需要与http客户端互操作
|
(+) (#)
可以自行扩展注册中心,参见:注册中心扩展
比如:中文站有些服务来不及在青岛部署,只在杭州部署,而青岛的其它应用需要引用此服务,就可以将服务同时注册到两个注册中心。
|
比如:CRM有些服务是专门为国际站设计的,有些服务是专门为中文站设计的。
|
比如:CRM需同时调用中文站和国际站的PC2服务,PC2在中文站和国际站均有部署,接口及版本号都一样,但连的数据库不一样。
|
如果只是测试环境临时需要连接两个不同注册中心,使用竖号分隔多个不同注册中心地址:
|
(+) (#)
<
dubbo:service
group
=
"feedback"
interface
=
"com.xxx.IndexService"
/>
<
dubbo:service
group
=
"member"
interface
=
"com.xxx.IndexService"
/>
|
<
dubbo:reference
id
=
"feedbackIndexService"
group
=
"feedback"
interface
=
"com.xxx.IndexService"
/>
<
dubbo:reference
id
=
"memberIndexService"
group
=
"member"
interface
=
"com.xxx.IndexService"
/>
|
任意组:(2.2.0以上版本支持,总是只调一个可用组的实现)
<
dubbo:reference
id
=
"barService"
interface
=
"com.foo.BarService"
group
=
"*"
/>
|
(+) (#)
<
dubbo:service
interface
=
"com.foo.BarService"
version
=
"1.0.0"
/>
|
<
dubbo:service
interface
=
"com.foo.BarService"
version
=
"2.0.0"
/>
|
<
dubbo:reference
id
=
"barService"
interface
=
"com.foo.BarService"
version
=
"1.0.0"
/>
|
<
dubbo:reference
id
=
"barService"
interface
=
"com.foo.BarService"
version
=
"2.0.0"
/>
|
不区分版本:(2.2.0以上版本支持)
<
dubbo:reference
id
=
"barService"
interface
=
"com.foo.BarService"
version
=
"*"
/>
|
(+) (#)
代码参见:https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/merge
配置如:(搜索所有分组)
<
dubbo:reference
interface
=
"com.xxx.MenuService"
group
=
"*"
merger
=
"true"
/>
|
或:(合并指定分组)
<
dubbo:reference
interface
=
"com.xxx.MenuService"
group
=
"aaa,bbb"
merger
=
"true"
/>
|
或:(指定方法合并结果,其它未指定的方法,将只调用一个Group)
<
dubbo:reference
interface
=
"com.xxx.MenuService"
group
=
"*"
>
<
dubbo:method
name
=
"getMenuItems"
merger
=
"true"
/>
dubbo:service
>
|
或:(某个方法不合并结果,其它都合并结果)
<
dubbo:reference
interface
=
"com.xxx.MenuService"
group
=
"*"
merger
=
"true"
>
<
dubbo:method
name
=
"getMenuItems"
merger
=
"false"
/>
dubbo:service
>
|
或:(指定合并策略,缺省根据返回值类型自动匹配,如果同一类型有两个合并器时,需指定合并器的名称)
参见:[合并结果扩展]
<
dubbo:reference
interface
=
"com.xxx.MenuService"
group
=
"*"
>
<
dubbo:method
name
=
"getMenuItems"
merger
=
"mymerge"
/>
dubbo:service
>
|
或:(指定合并方法,将调用返回结果的指定方法进行合并,合并方法的参数类型必须是返回结果类型本身)
<
dubbo:reference
interface
=
"com.xxx.MenuService"
group
=
"*"
>
<
dubbo:method
name
=
"getMenuItems"
merger
=
".addAll"
/>
dubbo:service
>
|
(+) (#)
完整示例代码参见:https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/validation
验证方式可扩展,参见:Validation扩展点
参数标注示例:
import
java.io.Serializable;
import
java.util.Date;
import
javax.validation.constraints.Future;
import
javax.validation.constraints.Max;
import
javax.validation.constraints.Min;
import
javax.validation.constraints.NotNull;
import
javax.validation.constraints.Past;
import
javax.validation.constraints.Pattern;
import
javax.validation.constraints.Size;
public
class
ValidationParameter
implements
Serializable {
private
static
final
long
serialVersionUID = 7158911668568000392L;
@NotNull
// 不允许为空
@Size
(min =
1
, max =
20
)
// 长度或大小范围
private
String name;
@NotNull
(groups = ValidationService.Save.
class
)
// 保存时不允许为空,更新时允许为空 ,表示不更新该字段
@Pattern
(regexp =
"^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$"
)
private
String email;
@Min
(
18
)
// 最小值
@Max
(
100
)
// 最大值
private
int
age;
@Past
// 必须为一个过去的时间
private
Date loginDate;
@Future
// 必须为一个未来的时间
private
Date expiryDate;
public
String getName() {
return
name;
}
public
void
setName(String name) {
this
.name = name;
}
public
String getEmail() {
return
email;
}
public
void
setEmail(String email) {
this
.email = email;
}
public
int
getAge() {
return
age;
}
public
void
setAge(
int
age) {
this
.age = age;
}
public
Date getLoginDate() {
return
loginDate;
}
public
void
setLoginDate(Date loginDate) {
this
.loginDate = loginDate;
}
public
Date getExpiryDate() {
return
expiryDate;
}
public
void
setExpiryDate(Date expiryDate) {
this
.expiryDate = expiryDate;
}
}
|
分组验证示例:
public
interface
ValidationService {
// 缺省可按服务接口区分验证场景,如:@NotNull(groups = ValidationService.class)
@interface
Save{}
// 与方法同名接口,首字母大写,用于区分验证场景,如:@NotNull(groups = ValidationService.Save.class),可选
void
save(ValidationParameter parameter);
void
update(ValidationParameter parameter);
}
|
关联验证示例:
import
javax.validation.GroupSequence;
public
interface
ValidationService {
@GroupSequence
(Update.
class
)
// 同时验证Update组规则
@interface
Save{}
void
save(ValidationParameter parameter);
@interface
Update{}
void
update(ValidationParameter parameter);
}
|
参数验证示例:
import
javax.validation.constraints.Min;
import
javax.validation.constraints.NotNull;
public
interface
ValidationService {
void
save(
@NotNull
ValidationParameter parameter);
// 验证参数不为空
void
delete(
@Min
(
1
)
int
id);
// 直接对基本类型参数验证
}
|
在客户端验证参数:
<
dubbo:reference
id
=
"validationService"
interface
=
"com.alibaba.dubbo.examples.validation.api.ValidationService"
validation
=
"true"
/>
|
在服务器端验证参数:
<
dubbo:service
interface
=
"com.alibaba.dubbo.examples.validation.api.ValidationService"
ref
=
"validationService"
validation
=
"true"
/>
|
验证异常信息:
import
javax.validation.ConstraintViolationException;
import
javax.validation.ConstraintViolationException;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
import
com.alibaba.dubbo.examples.validation.api.ValidationParameter;
import
com.alibaba.dubbo.examples.validation.api.ValidationService;
import
com.alibaba.dubbo.rpc.RpcException;
public
class
ValidationConsumer {
public
static
void
main(String[] args)
throws
Exception {
String config = ValidationConsumer.
class
.getPackage().getName().replace(
'.'
,
'/'
) +
"/validation-consumer.xml"
;
ClassPathXmlApplicationContext context =
new
ClassPathXmlApplicationContext(config);
context.start();
ValidationService validationService = (ValidationService)context.getBean(
"validationService"
);
// Error
try
{
parameter =
new
ValidationParameter();
validationService.save(parameter);
System.out.println(
"Validation ERROR"
);
}
catch
(RpcException e) {
// 抛出的是RpcException
ConstraintViolationException ve = (ConstraintViolationException) e.getCause();
// 里面嵌了一个ConstraintViolationException
Set
// 可以拿到一个验证错误详细信息的集合
System.out.println(violations);
}
}
}
|
需要加入依赖:
<
dependency
>
<
groupId
>javax.validation
groupId
>
<
artifactId
>validation-api
artifactId
>
<
version
>1.0.0.GA
version
>
dependency
>
<
dependency
>
<
groupId
>org.hibernate
groupId
>
<
artifactId
>hibernate-validator
artifactId
>
<
version
>4.2.0.Final
version
>
dependency
>
|
(+) (#)
示例代码:https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/cache
缓存类型可扩展,参见:CacheFactory扩展点
配置如:
<
dubbo:reference
interface
=
"com.foo.BarService"
cache
=
"lru"
/>
|
或:
<
dubbo:reference
interface
=
"com.foo.BarService"
>
<
dubbo:method
name
=
"findBar"
cache
=
"lru"
/>
dubbo:reference
>
|
(+) (#)
<
dubbo:reference
id
=
"barService"
interface
=
"com.foo.BarService"
generic
=
"true"
/>
|
GenericService barService = (GenericService) applicationContext.getBean(
"barService"
);
Object result = barService.$invoke(
"sayHello"
,
new
String[] {
"java.lang.String"
},
new
Object[] {
"World"
});
|
import
com.alibaba.dubbo.rpc.service.GenericService;
...
// 引用远程服务
ReferenceConfig
new
ReferenceConfig
// 该实例很重量,里面封装了所有与注册中心及服务提供方连接,请缓存
reference.setInterface(
"com.xxx.XxxService"
);
// 弱类型接口名
reference.setVersion(
"1.0.0"
|