1 为什么要使用Dubbo
随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进。当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。
2 Dubbo的架构
节点角色说明
节点 | 角色说明 |
---|---|
Provider | 暴露服务的服务提供方 |
Consumer | 调用远程服务的服务消费方 |
Registry | 服务注册与发现的注册中心 |
Monitor | 统计服务的调用次数和调用时间的监控中心 |
Container | 服务运行容器 |
调用关系说明
- 服务容器负责启动,加载,运行服务提供者。
- 服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者在启动时,向注册中心订阅自己所需的服务。
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
Dubbo 架构具有以下几个特点,分别是连通性、健壮性、伸缩性、以及向未来架构的升级性。
3 Dubbo的使用
4 Dubbo注册中心原理
使用zookeeper作为Dubbo的注册中心,
5 如何快去启动Dubbo服务
接下来创建dubbo项目
首先在idea中创建两个maven项目 dubbo-client 和 dubbo-server
在dubbo-server下面创建两个Module为 server-api和server-provider。
server-api用来存放接口 server-provider用来做具体实现
在server-api中定义一个接口
public interface IJIYHello {
String sayHello(String msg);
}
server-provider的pom文件添加依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--依赖server-api项目 实现接口-->
<dependency>
<groupId>com.jiy.dubbo</groupId>
<artifactId>server-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--dubbo依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<!--zookeeper依赖-->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.10</version>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.8.0</version>
</dependency>
</dependencies>
在server-provider中实现接口
public class JiyHelloImpl implements IJIYHello{
@Override
public String sayHello(String msg) {
return "Hello"+msg;
}
}
配置dubbo-server.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://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!--提供方信息 -->
<dubbo:application name="dubbo-server" owner="jiy"/>
<!-- 注册中心-->
<dubbo:registry address="zookeeper://192.168.1.107:2181" file="e:/dubboCache/dubbo-server"/>
<dubbo:protocol name="dubbo" port="20880"/>
<dubbo:service interface="com.jiy.dubbo.IJIYHello" ref="jiyHelloService"/>
<bean id="jiyHelloService" class="com.jiy.dubbo.JiyHelloImpl"></bean>
</beans>
创建启动类
public class BootStrap {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("META-INF/spring/dubbo-server.xml");
applicationContext.start();
System.in.read();
}
}
也可以使用dubbo的Main方法启动
public class Main {
public static void main(String[] args) {
com.alibaba.dubbo.container.Main.main(new String[]{"spring","log4j"});
}
}
接下来看一个客户端
首先看pom文件
<dependency>
<groupId>com.jiy.dubbo</groupId>
<artifactId>server-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.10</version>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.8.0</version>
</dependency>
</dependencies>
创建配置文件调用服务 dubbo-client
<?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://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!--提供方信息 -->
<dubbo:application name="dubbo-client" owner="jiy"/>
<!-- 注册中心-->
<dubbo:registry address="zookeeper://192.168.1.107:2181"/>
<dubbo:protocol name="dubbo" port="20880"/>
<dubbo:reference interface="com.jiy.dubbo.IJIYHello" id="jiyHelloService"/>
</beans>
启动类
public class App
{
public static void main( String[] args ) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("dubbo-client.xml");
IJIYHello hello = (IJIYHello) context.getBean("jiyHelloService");
System.out.println(hello.sayHello("hi JIY"));
System.in.read();
}
}
接着启动自己的zookeeper注册中心 然后启动项目 简单的dubbo项目就运行起来了
6 多协议支持
多协议的支持是除了支持dubbo协议以外 还可以支持hessian等等。
可以通过集成dubbo做服务治理 可以平缓的迁移,不需要立刻迁移服务。不同的协议有不同的特性,可以给不同的接口提供不同的协议。
集成hessian需要添加一些依赖
<dependency>
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
<version>4.0.38</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>LATEST</version>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<version>6.1.25</version>
</dependency>
然后修改一下配置文件 dubbo-server.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://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!--提供方信息 -->
<dubbo:application name="dubbo-server" owner="jiy"/>
<!-- 注册中心-->
<dubbo:registry address="zookeeper://192.168.1.107:2181" file="e:/dubboCache/dubbo-server"/>
<!-- <dubbo:protocol name="dubbo" port="20880"/>-->
<dubbo:service interface="com.jiy.dubbo.IJIYHello" ref="jiyHelloService" protocol="hessian"/>
<bean id="jiyHelloService" class="com.jiy.dubbo.JiyHelloImpl"></bean>
</beans>
启动之后查看日志
发现已经注册了hessian发布了。
接下来去调用方同样添加相同的依赖,然后启动服务调用
发现调用成功了
在server-api中新定义一个接口 IDemoService
public interface IDemoService {
public String protocolDemo(String msg);
}
在server-provider中实现这个接口
public class DemService implements IDemoService {
@Override
public String protocolDemo(String msg) {
return "i am Protocol Demo"+ msg;
}
}
修改配置文件 dubbo-server.xml
<dubbo:service interface="com.jiy.dubbo.IJIYHello" ref="jiyHelloService" protocol="hessian"/>
<dubbo:service interface="com.jiy.dubbo.IDemoService" ref="demoService" protocol="dubbo"/>
<bean id="demoService" class="com.jiy.dubbo.DemService"></bean>
<bean id="jiyHelloService" class="com.jiy.dubbo.JiyHelloImpl"></bean>
启动项目发现有多个注册中心了。
7 同一个服务多种协议
修改配置文件
<dubbo:protocol port="20880" name="dubbo"/>
<dubbo:protocol port="8080" name="hessian"/>
<dubbo:service interface="com.jiy.dubbo.IJIYHello" ref="jiyHelloService" protocol="hessian,dubbo"/>
<dubbo:service interface="com.jiy.dubbo.IDemoService" ref="demoService" protocol="dubbo"/>
Zookeeper的显示
[dubbo%3A%2F%2F192.168.56.1%3A20880%2Fcom.jiy.dubbo.IJIYHello%3Fanyhost%3Dtrue%26application%3Ddubbo-server%26dubbo%3D2.6.2%26generic%3Dfalse%26interface%3Dcom.jiy.dubbo.IJIYHello%26methods%3DsayHello%26owner%3Djiy%26pid%3D7228%26side%3Dprovider%26timestamp%3D1565161142795, hessian%3A%2F%2F192.168.56.1%3A8080%2Fcom.jiy.dubbo.IJIYHello%3Fanyhost%3Dtrue%26application%3Ddubbo-server%26dubbo%3D2.6.2%26generic%3Dfalse%26interface%3Dcom.jiy.dubbo.IJIYHello%26methods%3DsayHello%26owner%3Djiy%26pid%3D7228%26side%3Dprovider%26timestamp%3D1565161132093
8 多注册中心支持
修改配置文件 添加新的<dubbo:registry/> 用id进行区分 然后在<dubbo:service/>指定调用的register.
<?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://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!--提供方信息 -->
<dubbo:application name="dubbo-server" owner="jiy"/>
<!-- 注册中心-->
<dubbo:registry id="zk1" address="zookeeper://192.168.1.107:2181" file="e:/dubboCache/dubbo-server"/>
<dubbo:registry id="zk2" address="zookeeper://192.168.1.108:2181" file="e:/dubboCache/dubbo-server"/>
<dubbo:protocol port="20880" name="dubbo"/>
<dubbo:protocol port="8080" name="hessian"/>
<dubbo:service interface="com.jiy.dubbo.IJIYHello" ref="jiyHelloService" protocol="hessian,dubbo" register="zk1"/>
<dubbo:service interface="com.jiy.dubbo.IDemoService" ref="demoService" protocol="dubbo" register="zk2"/>
<bean id="demoService" class="com.jiy.dubbo.DemService"></bean>
<bean id="jiyHelloService" class="com.jiy.dubbo.JiyHelloImpl"></bean>
</beans>
10 启动时检查配置
在调用方依赖服务方的服务时,如果服务放没有启动 启动客户端就会报错,如何解决这种依赖检查的问题呢
<dubbo:reference interface="com.jiy.dubbo.IJIYHello" id="jiyHelloService" check="false"/>
在调用的时候添加一个 check="false" 来关闭启动检查,可以避免循环依赖的调用
11集群的访问
接下来通过模拟不同的接口来模拟多个服务 修改端口号
在server-provider中添加两个新的实现类 一个是 DemService1,另一个是2
public class DemService1 implements IDemoService {
@Override
public String protocolDemo(String msg) {
return "i am serverice1"+ msg;
}
}
创建两个配置文件 dubbo-cluster1和dubbo-cluster2
dubbo-cluster1
<?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://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!--提供方信息 -->
<dubbo:application name="dubbo-server" owner="jiy"/>
<!-- 注册中心-->
<dubbo:registry id="zk1" address="zookeeper://192.168.1.107:2181" file="e:/dubboCache/dubbo-server"/>
<dubbo:protocol port="20880" name="dubbo"/>
<dubbo:service interface="com.jiy.dubbo.IDemoService" ref="demoService" registry="zk1"/>
<bean id="demoService" class="com.jiy.dubbo.DemService1"></bean>
</beans>
dubbo-cluster2
<?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://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!--提供方信息 -->
<dubbo:application name="dubbo-server" owner="jiy"/>
<!-- 注册中心-->
<dubbo:registry id="zk1" address="zookeeper://192.168.1.107:2181" file="e:/dubboCache/dubbo-server"/>
<dubbo:protocol port="20881" name="dubbo"/>
<dubbo:service interface="com.jiy.dubbo.IDemoService" ref="demoService" registry="zk1"/>
<bean id="demoService" class="com.jiy.dubbo.DemService2"></bean>
</beans>
创建两个启动类BootStrapCluster1和BootStrapCluster2加载两个配置文件
public class BootStrapCluster1 {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("META-INF/spring/dubbo-cluster1.xml");
applicationContext.start();
System.in.read();
}
}
然后指定dubbo-client的配置文件
<dubbo:reference interface="com.jiy.dubbo.IDemoService" id="demoService" check="false"/>
修改启动类 循环调用。
public class App
{
public static void main( String[] args ) throws IOException, InterruptedException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("dubbo-client.xml");
for(int i=0; i<10;i++) {
IDemoService hello = (IDemoService) context.getBean("demoService");
System.out.println(hello.protocolDemo("hi JIY"));
Thread.sleep(1000);
}
System.in.read();
}
}