XML配置
dubbo通过spring的xml文件进行配置,可以方便地与spring进行集成。
示例
下面是一个简单的provider端配置示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <dubbo:application name="hello-app"/> <dubbo:protocol name="dubbo" port="20880"/> <dubbo:registry address="zookeeper://localhost:2181"/> <dubbo:service interface="life.qzz.dubbodemo.api.DemoService" ref="demoService"/> <bean id="demoService" class="life.qzz.dubbodemo.api.impl.DemoServiceImpl"/> </beans>
|
consumer端配置示例:
1 2 3 4 5 6 7 8 9 10 11
| <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <dubbo:application name="hello-app"/> <dubbo:registry address="zookeeper://localhost:2181"/> <dubbo:reference id="demoService" interface="life.qzz.dubbodemo.api.DemoService"/> </beans>
|
在对dubbo进行扩展时,可以通过<dubbo:parameter>
标签来设置自定义参数,同时也支持spring的p
标签。如:
1 2 3
| <dubbo:protocol name="jms"> <dubbo:parameter key="queue" value="http://localhost/queue" /> </dubbo:protocol>
|
或:
1 2 3 4 5 6 7 8 9
| <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <dubbo:protocol name="jms" p:queue="http://localhost/queue" /> </beans>
|
配置关系图
配置优先级
- 上图中以timeout为值,显示了配置的查找顺序,其他retires,loadbalance,actives等类似。
- 方法级优先,接口级次之,全局配置再次之。
- 如果级别一样,则消费方优先,提供方再次之。
- 服务提供者的配置,通过URL由注册中心传递给服务消费者。
- 建议由服务提供者设置超时时间,因为一个方法要执行多久,提供方很清楚,如果一个服务消费者同时引用多个提供者,则无需关心超时时间。
- 理论上ReferenceConfig的非标识配置,在ConsumerConfig,ServiceConfig,ProviderConfig均可缺省配置(比如:只需要配置id和interface)。
上面的优先级查找顺序只针对提供者和消费者都是dubbo实现的,比如如果消费者是浏览器,提供者用的是rest协议,那么这种优先级关系应该不存在。
demo地址
属性配置
- 如果公共配置很简单,需要多个Spring容器共享配置,可以使用dubbo.properties作为缺省配置。
- Dubbo会自动加载classpath根目录下的dubbo.properties,可以通过JVM启动参数`-Ddubbo.properties.file=xxx.properties
改变缺省配置位置。
如果classpath根目录下存在多个dubbo.properties文件,比如多个jar包中有dubbo.properties,Dubbo会任意加载,这容易导致混乱,所以最好只用一个dubbo.properties文件。
映射规则
属性文件的key值与xml的配置存在一定的映射关系。
- 将XML配置的标签名,加上属性名,再用点
.
进行分隔,多个属性拆成多行书写。比如:
- dubbo.application.name=hello 等价于<dubbo:application name=”hello”/>
- dubbo.registry.address=zookeeper://localhost:2181 等价于<dubbo:registry address=”zookeeper://localhost:2181”/>
- 如果XML有多行同名标签配置,可以用id进行区分,如果没有id号将对所有同名标签生效。比如:
- dubbo.protocol.rmi.port=1099 等价于<dubbo:protocol id=”rmi” name=”rmi” port=”1099”/>(协议的id没配时,缺省使用协议名作为id)
- dubbo.registry.china.address = zookeeper://localhost:2181 等价于 <dubbo:registry id =”china” address=”zookeeper://localhost:2181”/>
典型配置
1 2 3
| dubbo.application.name=hello dubbo.application.owner=qzz dubbo.registry.address=zookeeper://localhost:2181
|
覆盖策略
- JVM启动参数优先,这样可以在部署和启动的时候进行参数重写,比如在启动的时候改变协议的端口号。
- XML次之,如果在XML中有配置,则dubbo.properties中的相应配置项会失效。
- Properties最后,相当于缺省值,只有XML和启动参数都有没有对应的配置项时,dubbo.properties中的相应配置项才会生效,通常用于共享公共配置,比如应用名。
API配置
API配置的使用范围用来做OpenAPI,ESB,Test,Mock等系统集成,普通服务的提供方和消费方,宜采用其他配置方式。API的属性与配置项一一对应,如:ApplicationConfig.setName(“hello”)对应<dubbo:application name=”hello”/>。
服务提供者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| package life.qzz.dubbodemo.api.impl;
import com.alibaba.dubbo.config.ApplicationConfig; import com.alibaba.dubbo.config.ProtocolConfig; import com.alibaba.dubbo.config.RegistryConfig; import com.alibaba.dubbo.config.ServiceConfig; import life.qzz.dubbodemo.api.DemoService;
import java.io.IOException;
public class App { public static void main(String[] args) throws IOException {
DemoService demoService = new DemoServiceImpl(); ApplicationConfig applicationConfig = new ApplicationConfig("hello");
RegistryConfig registryConfig = new RegistryConfig("zookeeper://localhost:2181");
ProtocolConfig protocolConfig = new ProtocolConfig("dubbo",20880);
ServiceConfig<DemoService> serviceConfig = new ServiceConfig<>(); serviceConfig.setInterface(DemoService.class); serviceConfig.setRef(demoService); serviceConfig.setProtocol(protocolConfig); serviceConfig.setRegistry(registryConfig); serviceConfig.setApplication(applicationConfig); serviceConfig.export(); System.in.read(); } }
|
服务消费者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package life.qzz;
import com.alibaba.dubbo.config.ApplicationConfig; import com.alibaba.dubbo.config.ReferenceConfig; import com.alibaba.dubbo.config.RegistryConfig; import life.qzz.dubbodemo.api.DemoService;
public class App { public static void main( String[] args ) {
ApplicationConfig applicationConfig = new ApplicationConfig("hello");
RegistryConfig registryConfig = new RegistryConfig("zookeeper://localhost:2181");
ReferenceConfig<DemoService> r = new ReferenceConfig<>(); r.setInterface(DemoService.class); r.setRegistry(registryConfig); r.setApplication(applicationConfig); DemoService service = r.get(); System.out.println( service.sayHello("qzz")); } }
|
特殊场景
方法级配置
1 2 3 4 5 6 7 8 9 10 11 12
| List<MethodConfig> methods = new ArrayList<MethodConfig>(); MethodConfig method = new MethodConfig(); method.setName("sayHello"); method.setTimeout(10000); method.setRetries(0); methods.add(method);
ReferenceConfig<DemoService> reference = new ReferenceConfig<DemoService>();
reference.setMethods(methods);
|
点对点直连
1 2 3 4 5
| ReferenceConfig<DemoService> reference = new ReferenceConfig<DemoService>();
reference.setUrl("dubbo://localhost:20880/com.xxx.XxxService");
|
官方文档上说ServiceConfig
,ReferenceConfig
为重对象,内部封装了与注册中心的连接,以及与服务提供者的连接,需要缓存,否则会造成内存和连接泄露。这里有点儿疑问:
- 需要暴露多个服务的时候需要new 多个ServiceConfig实例,每个实例中者封装了与注册中心的连接。这个应该没毛病,每个服务可以使用不一样的注册中心。个人觉得
ApplicationConfig
,RegistryConfig
,ProtocolConfig
这些实例应该单独实例化之后,再设置到ServiceConfig
,ReferenceConfig
中去比较好吧,因为ApplicationConfig
这些只需要初始化一次之后,可以在多个ServiceConfig
和ReferenceConfig
中引用,不需要在每个ServiceConfig
,ReferenceConfig
配置的过程中初始化。
- 在什么样的情况下需要获取这些实例?一般服务暴露出去之后这个实例也就用不上了吧?在做系统集成的时候如果需要管理这些Service的话,应该是需要拿到这些配置对象的。
demo地址
注解配置
dubbo 2.2.1以上版本开始支持注解配置。
服务提供方注解
1 2 3 4 5 6 7 8 9 10 11 12
| import com.alibaba.dubbo.config.annotation.Service; import life.qzz.dubbodemo.api.DemoService;
@Service(version = "1.0") public class DemoServiceImpl implements DemoService{ public String sayHello(String name) { return "hello :" + name; } }
|
配置:
1 2 3 4 5
| <dubbo:application name="hello-app"/> <dubbo:protocol name="dubbo" port="20880"/> <dubbo:registry address="zookeeper://localhost:2181"/>
<dubbo:annotation package="life.qzz.dubbodemo"/>
|
服务消费方注解
1 2 3 4 5 6 7 8
| @Component public class DemoController { @Reference(version = "1.0") private DemoService demoService; public void sayHello(String name){ System.out.println(demoService.sayHello(name)); } }
|
配置:
1 2 3 4
| <dubbo:application name="hello-app"/> <dubbo:registry address="zookeeper://localhost:2181"/>
<dubbo:annotation package="life.qzz.dubbodemo"/>
|
也可以使用spring的component-scan:
1 2 3 4
| <dubbo:annotation /> <context:component-scan base-package="life.qzz.dubbodemo"> <context:include-filter type="annotation" expression="com.alibaba.dubbo.config.annotation.Service" /> </context:component-scan>
|
demo地址