为什么要有DUBBO
- 在传统的war包时代,所有的功能都放到一个项目中,这个项目打成一个war包发布到服务器,当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。
- 但是当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,提升效率的方法之一是将应用拆成互不相干的几个应用,以提升效率。
- 当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求,在这样的情况下,RPC(远程过程调用)技术就应运而生,而dubbo就是一种典型的RPC框架。
DUBBO架构
节点 | 说明 |
---|---|
Provider | 暴露服务的服务提供方 |
Consumer | 调用远程服务的服务消费方 |
Registry | 服务注册与发现的注册中心 |
Monitor | 统计服务的调用次数和调用时间的监控中心 |
Container | 服务运行容器 |
- 服务容器负责启动,加载和运行服务提供者;
- 服务提供者在启动时,会向注册中心注册自己提供的服务信息;
- 服务消费者在启动时会从注册中心订阅自己所需要的服务信息;
- 注册中心返回服务列表给服务消费方,如果注册中心中的信息有变更,注册中心会向服务消费方推送变更的数据;
- 服务消费者根据从得到的服务列表信息中,按照负载均衡算法,选一台提供者进行调用,如果调用失败,再调用另一台;
- 服务消费者和提供者,在内存中累计调用的次数和调用的时长,定时发送数据给监控中心;
DUBBO代码演示
- 服务提供者
- jar包引入
<dependencies> <!-- 添加dubbo依赖 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.6.9</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> </exclusion> </exclusions> </dependency> <!-- 添加zk客户端依赖 --> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.6.0</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> <exclusion> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </exclusion> </exclusions> </dependency> <!-- spring相关 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.0.0</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>1.8.7</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> </dependency> <!-- 日志相关依赖 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.10</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.63.Final</version> </dependency> <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> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>5.0.0</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>5.0.0</version> </dependency> </dependencies>
注意: 在上面的pom文件中,因为我要用比较新的spring版本,所以在引入dubbo时,排除了dubbo自带的spring引入,如在使用中没有要换spring的需求,可保留dubbo自带的spring。
- provider.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_provider"/>
<!-- 相当于是一个全局变量配置 -->
<dubbo:provider timeout="5000"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181" check="false"/>
<!-- 如果协议是dubbo ,就是netty的端口 -->
<dubbo:protocol name="dubbo" port="29015"/>
<bean id="userServiceImpl" class="com.cym.service.UserServiceImpl"/>
<!-- 要对外发布的服务 -->
<dubbo:service interface="com.cym.service.inter.UserService" ref="userServiceImpl"/>
</beans>
- 新增一个接口(UserService)
public interface UserService {
String queryUser(String var1);
void doKill(String var1);
}
- 接口的实现类
public class UserServiceImpl implements UserService {
@Override
public String queryUser(String s) {
System.out.println("=========queryUser=========" + s);
return "OK-----" + s;
}
@Override
public void doKill(String s) {
System.out.println("=========doKill=========" + s);
}
}
- 最后启动项目,加载provider.xml文件,这样dubbo的服务提供方就会启动起来。
public static void main(String[] args) throws IOException {
new ClassPathXmlApplicationContext("provider.xml");
System.in.read();
}
- 测试提供方启动
DUBBO服务消费方代码
- jar包的引入,用到的jar和提供方的一样,可以把服务提供方的jar复用过来。
- consumer.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_consumer"/>
<dubbo:consumer check="false"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181" check="false"/>
<dubbo:reference interface="com.cym.service.inter.UserService" check="false" id="userServiceImpl" />
</beans>
- 测试消费端调用提供方的接口代码
public class XmlConsumer {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationConsumer.xml");
UserService userService = (UserService) app.getBean("userServiceImpl");
String cym = userService.queryUser("88");
System.out.println(cym);
// 阻塞线程
System.in.read();
}
}
- 测试消费端的方法(运行XmlConsumer的main方法)
可以看到,已经打印出了正确的结课,说明我们dubbo的服务提供方和消费方都已经搭建成功。