Dubbo的概念
Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。
其核心部分包含:
1. 远程通讯: 提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。
2. 集群容错: 提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。
3. 自动发现: 基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。
Dubbo原理如下:
ConfigServer
配置中心,和每个Server/Client之间会作一个实时的心跳检测(因为它们都是建立的Socket长连接),比如几秒钟检测一次。收集每个Server提供的服务的信息,每个Client的信息,整理出一个服务列表,如:
serviceName | serverAddressList | clientAddressList |
UserService | 192.168.0.1,192.168.0.2,192.168.0.3,192.168.0.4 | 172.16.0.1,172.16.0.2 |
ProductService | 192.168.0.3,192.168.0.4,192.168.0.5,192.168.0.6 | 172.16.0.2,172.16.0.3 |
OrderService | 192.168.0.10,192.168.0.12,192.168.0.5,192.168.0.6 | 172.16.0.3,172.16.0.4 |
当某个Server不可用,那么就更新受影响的服务对应的serverAddressList,即把这个Server从serverAddressList中踢出去(从地址列表中删除),同时将推送serverAddressList给这些受影响的服务的clientAddressList里面的所有Client。如:192.168.0.3挂了,那么UserService和ProductService的serverAddressList都要把192.168.0.3删除掉,同时把新的列表告诉对应的Client 172.16.0.1,172.16.0.2,172.16.0.3;
当某个Client挂了,那么更新受影响的服务对应的clientAddressListConfigServer根据服务列表,就能提供一个web管理界面,来查看管理服务的提供者和使用者。
新加一个Server时,由于它会主动与ConfigServer取得联系,而ConfigServer又会将这个信息主动发送给Client,所以新加一个Server时,只需要启动Server,然后几秒钟内,Client就会使用上它提供的服务
Client
调用服务的机器,每个Client启动时,主动与ConfigServer建立Socket长连接,并将自己的IP等相应信息发送给ConfigServer。
Client在使用服务的时候根据服务名称去ConfigServer中获取服务提供者信息(这样ConfigServer就知道某个服务是当前哪几个Client在使用),Client拿到这些服务提供者信息后,与它们都建立连接,后面就可以直接调用服务了,当有多个服务提供者的时候,Client根据一定的规则来进行负载均衡,如轮询,随机,按权重等。
一旦Client使用的服务它对应的服务提供者有变化(服务提供者有新增,删除的情况),ConfigServer就会把最新的服务提供者列表推送给Client,Client就会依据最新的服务提供者列表重新建立连接,新增的提供者建立连接,删除的提供者丢弃连接
Server
真正提供服务的机器,每个Server启动时,主动与ConfigServer建立Scoket长连接,并将自己的IP,提供的服务名称,端口等信息直接发送给ConfigServer,ConfigServer就会收集到每个Server提供的服务的信息。
优点:
1,只要在Client和Server启动的时候,ConfigServer是好的,服务就可调用了,如果后面ConfigServer挂了,那只影响ConfigServer挂了以后服务提供者有变化,而Client还无法感知这一变化。
2,Client每次调用服务是不经过ConfigServer的,Client只是与它建立联系,从它那里获取提供服务者列表而已
3,调用服务-负载均衡:Client调用服务时,可以根据规则在多个服务提供者之间轮流调用服务。
4,服务提供者-容灾:某一个Server挂了,Client依然是可以正确的调用服务的,当前提是这个服务有至少2个服务提供者,Client能很快的感知到服务提供者的变化,并作出相应反应。
5,服务提供者-扩展:添加一个服务提供者很容易,而且Client会很快的感知到它的存在并使用它。
dubbo架构
Provider: 暴露服务的服务提供方。
Consumer: 调用远程服务的服务消费方。
Registry: 服务注册与发现的注册中心。
Monitor: 统计服务的调用次调和调用时间的监控中心。
Container: 服务运行容器。
调用关系说明:
0服务容器负责启动,加载,运行服务提供者。
1. 服务提供者在启动时,向注册中心注册自己提供的服务。
2. 服务消费者在启动时,向注册中心订阅自己所需的服务。
3. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
4. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
Dubbo接口配置
1.服务端接口配置(providr样例)applicationContext-dubbo-smk.xml:
<?xmlversion="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
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" >
<!-- 声明需要暴露的服务接口,直连时,token=true要去掉,会有不安全因素,但直连一般用于内部使用,安全问题可以暂忽略-->
<dubbo:serviceinterface="com.hoperun.biz.smk.service.SmkService"ref="smkService" version="1.0"/>
</beans>
2.服务端注册配置:
<?xmlversion="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:applicationname="znmhcommon"></dubbo:application>
<!-- dubbo接口去除注册中心,采用直连的方式 -->
<dubbo:registryaddress="N/A" />
<!-- 使用multicast广播注册中心暴露发现服务地址 -->
<!-- <dubbo:registryaddress="multicast://224.5.6.7:1234?unicast=false" />-->
<!--dubbo集群开发,请激活下面条目,并注销上面的多播multicast -->
<!--<dubbo:registry protocol="zookeeper"address="10.254.201.232:2181,10.254.201.68:2181" />-->
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880"></dubbo:protocol>
<!-- <dubbo:serviceinterface="com.hoperun.biz.commons.service.DownloadService"version="1.0" ref="downloadService" />
<dubbo:serviceinterface="com.hoperun.biz.commons.service.UploadService"version="1.0" ref="uploadService" />-->
</beans>
3.dubbo客户端配置(consumer)
<?xmlversion="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
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="consumer-of-znmhcommon" />
<!-- dubbo接口去除注册中心,采用直连的方式 -->
<!-- <dubbo:registry address="N/A"></dubbo:registry> -->
<!-- 使用multicast广播注册中心暴露发现服务地址 -->
<!-- <dubbo:registryaddress="multicast://224.5.6.7:1234?unicast=false" />-->
<!--
<dubbo:registryprotocol="zookeeper"address="10.254.201.68:2181,10.254.201.232:2181"
/>
-->
<!-- 生成远程服务代理,可以和本地bean一样使用 -->
<dubbo:consumer timeout="30000" >
</dubbo:consumer>
<dubbo:reference
id="demoService"
interface="com.hoperun.biz.demoservice.service.DemoService"
url="dubbo://127.0.0.1:20880/com.hoperun.biz.demoservice.service.DemoService"
version="1.0" />
<dubbo:reference
id="smkService"
interface="com.hoperun.biz.smk.service.SmkService"
url="dubbo://10.254.201.123:20880/com.hoperun.biz.smk.service.SmkService"
version="1.0" />
</beans>
Provider端学习
服务端的配置文件: provider.xml
1. <?xml version="1.0" encoding="UTF-8"?>
2. <beans xmlns="http://www.springframework.org/schema/beans"
3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4. xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
5. xsi:schemaLocation="http://www.springframework.org/schema/beans
6. http://www.springframework.org/schema/beans/spring-beans.xsd
7. http://code.alibabatech.com/schema/dubbo
8. http://code.alibabatech.com/schema/dubbo/dubbo.xsd ">
9. <!-- Application name -->
10. <dubbo:application name="Frame" />
11. <!-- registry address, used for service to register itself -->
12. <dubbo:registry address="multicast://224.5.6.7:1234" />
13. <!-- expose this service through dubbo protocol, through port 20880 -->
14. <dubbo:protocol name="dubbo" port="20880" />
15. <!-- which service interface do we expose? -->
16. <dubbo:service interface="merchant.shop.service.IHelloService" ref="helloService" />
17. <!-- bean配置 -->
18. <bean id="helloService"
19. class="merchant.shop.service.impl.HelloServiceImpl">
20. </bean>
21. </beans>
此处interface的地址要与consumer端的一致,所以在服务端工程中新建了和客户端工程一样的路径来保存service,如果同一个服务有多个实现,可以使用group设置分组。当一个接口的实现出现版本不兼容的情况的时候,可以通过版本号进行过度。
服务端需要启动的两个文件如下 :
1. package com.sitech.comm.dubbo;
2. import org.springframework.context.ApplicationContext;
3. import org.springframework.context.support.ClassPathXmlApplicationContext;
4.
5. public class Provider {
6. public static void init() throws Exception {
7. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"provider.xml"});
8. context.start();
9. singleton();
10. }
11. public static ApplicationContext context = null;
12. public static ApplicationContext singleton() {
13. if (context == null) {
14. context = new ClassPathXmlApplicationContext(new String[] {"providerApplicationContext.xml"});
15. }
16. return context;
17. };
18. }
1. package com.sitech.comm.dubbo;
2.
3.
4. import javax.servlet.ServletException;
5. import javax.servlet.http.HttpServlet;
6.
7. import com.sitech.comm.log.LogWritter;
8.
9. public class ProviderInit extends HttpServlet {
10.
11. public void init() throws ServletException {
12. try {
13. System.out.println("初始化dubbo服务端");
14. Provider.init();
15. } catch (Exception e) {
16. System.out.println("初始化dubbo服务端失败");
17. }
18. }
19.
20. }
web.xml 中增加启动如下 :
1. <servlet>
2. <servlet-name>ProviderInit</servlet-name>
3. <servlet-class>
4. com.sitech.comm.dubbo.ProviderInit
5. </servlet-class>
6. <load-on-startup>1</load-on-startup>
7. </servlet>
Consumer端学习
1、客户端配置文件 consumer.xml
1. <?xml version="1.0" encoding="UTF-8"?>
2. <beans xmlns="http://www.springframework.org/schema/beans"
3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4. xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
5. xsi:schemaLocation="http://www.springframework.org/schema/beans
6. http://www.springframework.org/schema/beans/spring-beans.xsd
7. http://code.alibabatech.com/schema/dubbo
8. http://code.alibabatech.com/schema/dubbo/dubbo.xsd ">
9. <!-- consumer application name -->
10. <dubbo:application name="Frame" />
11. <!-- registry address, used for consumer to discover services -->
12. <dubbo:registry address="multicast://224.5.6.7:1234" />
13. <!-- which service to consume? -->
14.
15. <dubbo:reference id="helloService" interface="merchant.shop.service.IHelloService" />
16. </beans>
这里dubbo的地址需要与下面服务端的一致
客服端只有action 和 service 的接口 ,没有service 的实现类
需要启动的文件有下面的两个:
1. package com.sitech.comm.dubbo;
2.
3. import org.springframework.context.support.ClassPathXmlApplicationContext;
4. public class Consumer {
5. public static ClassPathXmlApplicationContext context = null;
6. public static ClassPathXmlApplicationContext singleton() {
7. if (context == null) {
8. context = new ClassPathXmlApplicationContext(new String[] {"consumer.xml"});
9. context.start();
10. }
11. return context;
12. };
13. }
14.
1. package com.sitech.comm.dubbo;
2.
3.
4. import javax.servlet.ServletException;
5. import javax.servlet.http.HttpServlet;
6.
7. import com.sitech.comm.log.LogWritter;
8.
9. public class ConsumerInit extends HttpServlet {
10.
11. public void init() throws ServletException {
12. try {
13. System.out.println("初始化dubbo客户端");
14. Consumer.singleton();
15. } catch (Exception e) {
16. System.out.println("初始化dubbo客户端失败");
17. }
18. }
19.
20. }
在 web.xml 中添加个启动:
1. <servlet>
2. <servlet-name>ConsumerInit</servlet-name>
3. <servlet-class>com.sitech.comm.dubbo.ConsumerInit</servlet-class>
4. <load-on-startup>1</load-on-startup>
5. </servlet>
acton 中的使用方法:
1. import javax.servlet.http.HttpServletRequest;
2. import javax.servlet.http.HttpServletResponse;
3.
4. import merchant.shop.service.IHelloService;
5.
6. import org.springframework.web.servlet.ModelAndView;
7. import org.springframework.web.servlet.mvc.AbstractController;
8.
9. import com.sitech.comm.dubbo.Consumer;
10.
11. public class TestAction extends AbstractController{
12.
13. @Override
14. protected ModelAndView handleRequestInternal(HttpServletRequest arg0,
15. HttpServletResponse arg1) throws Exception {
16. IHelloService helloService = (IHelloService) Consumer.singleton().getBean("helloService");
17. helloService.sayHello();
18. return null;
19. }
20.
21. }
sevice 接口如下:
1. package merchant.shop.service;
2.
3. public interface IHelloService {
4. public String sayHello();
5. }
示例
服务提供者
1. package com.unj.dubbotest.provider;
2.
3. import java.util.List;
4.
5. public interface DemoService {
6.
7. String sayHello(String name);
8.
9. public List getUsers();
10.
11. }
在服务提供方实现接口:(对服务消费方隐藏实现)
1. package com.unj.dubbotest.provider;
2.
3. import java.util.ArrayList;
4. import java.util.LinkedList;
5. import java.util.List;
6.
7.
8. public class DemoServiceImpl implements DemoService{
9.
10. public String sayHello(String name) {
11. return "Hello " + name;
12. }
13. public List getUsers() {
14. List list = new ArrayList();
15. User u1 = new User();
16. u1.setName("jack");
17. u1.setAge(20);
18. u1.setSex("男");
19.
20. User u2 = new User();
21. u2.setName("tom");
22. u2.setAge(21);
23. u2.setSex("女");
24.
25. User u3 = new User();
26. u3.setName("rose");
27. u3.setAge(19);
28. u3.setSex("女");
29.
30. list.add(u1);
31. list.add(u2);
32. list.add(u3);
33. return list;
34. }
35. }
用Spring配置声明暴露服务:
1. <?xml version="1.0" encoding="UTF-8"?>
2. <beans xmlns="http://www.springframework.org/schema/beans"
3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4. xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
5. xsi:schemaLocation="http://www.springframework.org/schema/beans
6. http://www.springframework.org/schema/beans/spring-beans.xsd
7. http://code.alibabatech.com/schema/dubbo
8. http://code.alibabatech.com/schema/dubbo/dubbo.xsd
9. ">
10.
11. <!-- 具体的实现bean -->
12. <bean id="demoService" class="com.unj.dubbotest.provider.DemoServiceImpl" />
13.
14. <!-- 提供方应用信息,用于计算依赖关系 -->
15. <dubbo:application name="xixi_provider" />
16.
17. <!-- 使用multicast广播注册中心暴露服务地址
18. <dubbo:registry address="multicast://224.5.6.7:1234" />-->
19.
20. <!-- 使用zookeeper注册中心暴露服务地址 -->
21. <dubbo:registry address="zookeeper://127.0.0.1:2181" />
22.
23. <!-- 用dubbo协议在20880端口暴露服务 -->
24. <dubbo:protocol name="dubbo" port="20880" />
25.
26. <!-- 声明需要暴露的服务接口 -->
27. <dubbo:service interface="com.unj.dubbotest.provider.DemoService" ref="demoService" />
28.
29. </beans>
加载Spring配置,启动服务:
1. package com.unj.dubbotest.provider;
2.
3. import org.springframework.context.support.ClassPathXmlApplicationContext;
4.
5. public class Provider {
6.
7. public static void main(String[] args) throws Exception {
8. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml"});
9. context.start();
10.
11. System.in.read(); // 为保证服务一直开着,利用输入流的阻塞来模拟
12. }
13.
14. }
服务消费者
1.通过Spring配置引用远程服务:
1. <?xml version="1.0" encoding="UTF-8"?>
2. <beans xmlns="http://www.springframework.org/schema/beans"
3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
4. xsi:schemaLocation="http://www.springframework.org/schema/beans
5. http://www.springframework.org/schema/beans/spring-beans.xsd
6. http://code.alibabatech.com/schema/dubbo
7. http://code.alibabatech.com/schema/dubbo/dubbo.xsd
8. ">
9.
10. <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
11. <dubbo:application name="hehe_consumer" />
12.
13. <!-- 使用zookeeper注册中心暴露服务地址 -->
14. <!-- <dubbo:registry address="multicast://224.5.6.7:1234" /> -->
15. <dubbo:registry address="zookeeper://127.0.0.1:2181" />
16.
17. <!-- 生成远程服务代理,可以像使用本地bean一样使用demoService -->
18. <dubbo:reference id="demoService"
19. interface="com.unj.dubbotest.provider.DemoService" />
20.
21. </beans>
2.加载Spring配置,并调用远程服务:
1. package com.alibaba.dubbo.demo.pp;
2.
3. import java.util.List;
4.
5. import org.springframework.context.support.ClassPathXmlApplicationContext;
6.
7. import com.unj.dubbotest.provider.DemoService;
8.
9. public class Consumer {
10.
11. public static void main(String[] args) throws Exception {
12. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
13. new String[] { "applicationContext.xml" });
14. context.start();
15.
16. DemoService demoService = (DemoService) context.getBean("demoService"); //
17. String hello = demoService.sayHello("tom"); // ִ
18. System.out.println(hello); //
19.
20. //
21. List list = demoService.getUsers();
22. if (list != null && list.size() > 0) {
23. for (int i = 0; i < list.size(); i++) {
24. System.out.println(list.get(i));
25. }
26. }
27. // System.out.println(demoService.hehe());
28. System.in.read();
29. }
30.
31. }
调用结果为:
dubbo管理页面:
应用页面:
提供者页面:
消费者页面:
服务页面:
PPT资料可参考:http://wenku.baidu.com/view/8a6c8af7c77da26925c5b0f1.html