掀开Dubbo的盖头来
为什么需要Dubbo
拿C2C网站来说,早期架构比较简单,如下图所示,其实当下对于大部分学生来说,平时做的一些项目就是如下的架构,因为我们不需要考虑流量啊,交互舒适度啊什么的,只要实现功能就可以了。
后面,当产品面向市场,用户量就会持续递增,那么这个架构肯定无法支撑。优先考虑的是服务器扩容,垂直扩展。但是这种方式虽然短期投入产出比不错,长期来看还是有问题的。因此我们会进行一些分表分表、读写分离。服务器会做一些水平分离、负载均衡等,之后我们的架构就会变成这样:
我们按照功能来对我们架构组件做一些拆分。
在服务层这一块,服务的集群会发生问题,比如说业务层一直在调用的话,如何去解决负载均衡问题?如果某个节点变化,能不能及时通知到?对于一些请求的限流,容错和降级怎么实现?URL是如何维护的?Dubbo就是用来去解决这些问题的。
Dubbo是一个服务治理的技术,什么是服务治理?就是治理负载、容错、降级、服务权重等东西。
Dubbo能解决什么问题?比如说各个服务之间需要通信,那就需要相关的技术,我们可以通过http或者webservice。Dubbo第一个解决的问题就是远程调用,它可以看做一个RPC框架,用一个图来介绍Dubbo的架构:
快速启动Dubbo
我们可以用一个简单的例子来说一下Dubbo在实际中的应用:
首先定义两个模块 ,一个是Server,一个是Client。在Server中配置一个接口和一个实现类:
public interface ILusheHello { String sayHello(String msg); }
public class LusheHelloImpl implements ILusheHello { @Override public String sayHello(String msg) { return "hello" + msg; } }
之后配置dubbo-server.xml,将其发布出去,xml文件如下
<?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="dubbo-server" owner="Lushe"/> <!--配置Dubbo注册中心--> <dubbo:registry address="N/A"/> <!--注册中心 <dubbo:registry id="zk1" address="zookeeper://10.10.101.104:2181"/> <dubbo:registry id="zk2" address="zookeeper://10.10.101.108:2181"/> --> <!--服务端口信息--> <dubbo:protocol port="20880" name="dubbo"/> <dubbo:protocol port="8080" name="hessian"/> <dubbo:service interface="lushe.study.dubbo.ILusheHello" ref="lusheHelloService" protocol="dubbo,hessian"/> <bean id="lusheHelloService" class="lushe.study.dubbo.LusheHelloImpl"/> </beans>
我们得到了协议地址
dubbo://192.168.0.106:20880/lushe.study.dubbo.ILusheHello
然后再Client里配置一个dubbo-client.xml的配置文件
<?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="dubbo-client" owner="Lushe"/> <!--配置Dubbo注册中心--> <dubbo:registry address="N/A"/> <dubbo:protocol name="dubbo" port="20880"/> <dubbo:reference id="lusheHelloService" interface="lushe.study.dubbo.ILusheHello" url="dubbo://192.168.0.106:20880/lushe.study.dubbo.ILusheHello"/> </beans>
这时候,按照Spring从配置文件中获取Bean的方式将内容加载出来,也可以说它实现了一个远程动态代理+反射得到Bean的工作:
public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("dubbo-client.xml"); ILusheHello hello = (ILusheHello) context.getBean("lusheHelloService"); System.out.println(hello.sayHello("lushe")); }
执行后,如下图所示 我们可以看到结果:
然而现在我们还没有实现注册中心的功能,dubbo中支持的注册中心有:Zookeeper、Redis等,我们把配置文件中的注册中心写成Zookeeper的地址,其实就是向Zookeeper的树状管理系统中加入了一个节点。然后再Client配置文件中就不用写url了,直接写Zookeeper的地址就可以了。
Dubbo里支持的容器:
Spring、jetty、Log4j,默认情况下会使用Spring容器来启动服务。
下面是通过Spring容器来启动Dubbo服务:
public static void main(String[] args) { com.alibaba.dubbo.container.Main.main(new String[] {"spring"}); }
--------------------------------------
2018-07-19 16:20:16,096 INFO [com.alibaba.dubbo.container.Main] - [DUBBO] Dubbo SpringContainer started!, dubbo version: 2.5.3, current host: 127.0.0.1
[2018-07-19 16:20:16] Dubbo service server started!
Dubbo多协议支持
Dubbo里支持hession、HTTP、webservice等协议。这样可以使得我们在利用Dubbo做服务治理的时候,适应性比较好。而且还可以满足我们对于不同的端口采用不同的协议的奇怪要求。
<dubbo:service interface="lushe.study.dubbo.ILusheHello" ref="lusheHelloService" protocol="dubbo,hessian"/>
上面的配置说明了这个接口使用dubbo和hessian协议