最近想学习一下 dubbo, 看了很多前辈们的文章和资料, 现对自己的理解做个总结:
要说 dubbo 就先了解一下 RPC:
概念:
RPC(Remote Procedure Call): 远程过程调用, 是一种通过网络从远程计算机程序上请求服务, 而不需要了解底层网络技术的协议. 它使得在本地调用远端的程序就好像是在调用本地的程序一样.
RPC 协议假定某些传输协议是存在的, 如 TCP 或 UDP, 为通信程序之间携带信息数据. 在 OSI 网络通信模型 (七层模型) 中, RPC 跨越了传输层和应用层. RPC 使得开发包括网络分布式多程序在内的应用程序更加容易.
RPC 调用过程:
客户端以本地服务方式调用服务
client stub 作为代理, 然后处理调用与调用的参数
client stub 发送调用到远端的系统, 通过 TCP 或 UDP
server stub 处理 client stub 发过来的调用与参数
server stub 调用真正提供的服务
server stub 处理回复, 然后发送给客户端
Dubbo
1, 什么是 dubbo :Dubbo 是阿里巴巴 SOA 服务化治理方案的核心框架, 是一个分布式服务框架, 致力于提供高性能和透明化的 RPC 远程服务调用方案, 以及 SOA 服务治理方案.
soa:"面向服务架构", 它提供的是一种架构风格和理念, 而并非是一种技术或者产品. SOA 提倡将不同应用程序的业务功能封装成 "服务" 并宿主起来, 通常以接口和契约的形式暴露并提供给外界应用访问(通过交换消息), 达到不同系统可重用的目的.
2,Dubbo 的技术架构图如下:
我们解释一下这个架构图:
a,Consumer 服务消费者(花钱的),Provider 服务提供者(给钱的),Container 服务容器(领钱的地方).
b, 服务提供者先启动, 然后注册服务(registry).
c,Monitor 这是一个监控, 图中虚线表明 Consumer 和 Provider 通过异步的方式发送消息至 Monitor,Consumer 和 Provider 会将信息存放在本地磁盘, 平均 1min 会发送一次信息. Monitor 在整个架构中是可选的.
d,Monitor 功能需要单独配置, 不配置或者配置以后, Monitor 挂掉并不会影响服务的调用.
3,Dubbo 服务消费者调用过程
上图是服务消费的主过程:
首先通过 ReferenceConfig 类的 private void init() 方法会先检查初始化所有的配置信息后, 调用 private T createProxy(Map map) 创建代理, 消费者最终得到的是服务的代理, 在 createProxy 接着调用 Protocol 接口实现的 Invoker refer(Class type, URL url) 方法生成 Invoker 实例(如上图中的红色部分), 这是服务消费的关键. 接下来把 Invoker 通过 ProxyFactory 代理工厂转换为客户端需要的接口(如: HelloWorld ), 创建服务代理并返回.
消费端的初始化过程
1, 把服务引用的信息封装成 URL 并注册到 zk 注册中心;
2, 监听注册中心的服务的上下线;
3, 连接服务提供端, 创建 NettyClient 对象;
4, 将这些信息包装成 DubboInvoker 消费端的调用链, 创建消费端 Invoker 实例的服务代理并返回;
消费端的服务引用过程
1, 经过负载均衡策略, 调用提供者;
2, 选择其中一个服务的 URL 与提供者 netty 建立连接, 使用 ProxyFactory 创建远程通信, 或者本地通信的, Invoker 发到 netty 服务端;
3, 服务器端接收到该 Invoker 信息后, 找到对应的本地 Invoker, 处理 Invocation 请求;
4, 获取异步, 或同步处理结果;
异步 不需要返回值: 直接调用 ExchangeClient.send()方法;
同步 需要返回值: 使用 ExchangeClient.request()方法, 返回一个 ResponseFuture, 一直阻塞到服务端返回响应结果;
4, 最简单的 dubbo 实例
1. 服务提供方和消费方都需要的包(这里我新建的 maven 工程为 pom 工程, 将共同的项目依赖写到 pom.xml 中)
总的项目结构为
pom.xml 文件内容为
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>com.test</groupId>
- <artifactId>dubbo-demo</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <packaging>pom</packaging>
- <properties>
- <motan.version>0.3.0</motan.version>
- <!-- 在阿里巴巴内部广泛使用的 GA 版本为: 2.4.9, 强烈推荐此版本 -->
- <dubbo.version>2.5.3</dubbo.version>
- <dubbox.version>2.8.4</dubbox.version>
- <spring.version>4.3.6.RELEASE</spring.version>
- <java.version>1.7</java.version>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- </properties>
- <dependencies>
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>dubbo</artifactId>
- <version>2.5.3</version>
- <exclusions>
- <exclusion>
- <groupId>org.springframework</groupId>
- <artifactId>spring</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>com.GitHub.sgroschupf</groupId>
- <artifactId>zkclient</artifactId>
- <version>0.1</version>
- </dependency>
- <!-- spring 相关 -->
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-core</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-beans</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-jdbc</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-web</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-aop</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-tx</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-ORM</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context-support</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-jms</artifactId>
- <version>${spring.version}</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>1.6.11</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjweaver</artifactId>
- <version>1.6.11</version>
- </dependency>
- </dependencies>
- <modules>
- <module>demo-API</module>
- <module>dubbo-consumer</module>
- <module>dubbo-provider</module>
- </modules>
- </project>
2. 在 demo-API 中定义服务接口(注意服务提供方和消费方都需要依赖这个项目)
- package com.test;
- public interface DemoService{
- String sayHello(String name);
- }
3. 服务提供方实现
项目结构
实现接口
- package com.test;
- import org.springframework.stereotype.Service;
- import com.test.DemoService;
- @Service("demoService")
- public class DemoServiceImpl implements DemoService{
- @Override
- public String sayHello(String name) {
- // TODO Auto-generated method stub
- return name;
- }
- }
声明暴露服务:
- <?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" />
- <!-- 使用 zookeeper 注册中心暴露服务地址 -->
- <dubbo:registry address="zookeeper://127.0.0.1:2181" />
- <!-- 用 dubbo 协议在 20880 端口暴露服务 -->
- <dubbo:protocol name="dubbo" port="20880" />
- <!-- 声明需要暴露的服务接口 -->
- <dubbo:service interface="com.test.DemoService" ref="demoService" />
- </beans>
在 springmvc.xml 中扫描 service 注解并将 dubbo-provider.xml 中的相关的 dubbo 配置引入进来
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
- http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-4.0.xsd
- http://www.springframework.org/schema/util
- http://www.springframework.org/schema/util/spring-util-4.0.xsd" default-autowire="byName">
- <aop:aspectj-autoproxy />
- <context:component-scan base-package="com.test" />
- <import resource="classpath:dubbo-provider.xml" />
- </beans>
加载 Spring 配置, 启动服务:
- package com.test;
- import java.io.IOException;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class Test {
- public static void main(String[] args) throws Exception {
- ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:springmvc.xml");
- context.start();
- System.out.println("Dubbo provider start...");
- try {
- System.in.read(); // 按任意键退出
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
4. 服务消费者实现
项目结构
在 dubbo-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" />
- <!-- 使用 multicast 广播注册中心暴露发现服务地址 -->
- <dubbo:registry protocol="zookeeper" address="zookeeper://127.0.0.1:2181" />
- <!-- 生成远程服务代理, 可以和本地 bean 一样使用 demoService -->
- <dubbo:reference id="demoService" interface="com.test.DemoService" />
- </beans>
在 springmvc.xml 中扫描 service 注解并将 dubbo-consumer.xml 中的相关的 dubbo 配置引入进来
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
- http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-4.0.xsd
- http://www.springframework.org/schema/util
- http://www.springframework.org/schema/util/spring-util-4.0.xsd" default-autowire="byName">
- <aop:aspectj-autoproxy />
- <context:component-scan base-package="com.test" />
- <import resource="classpath:/dubbo-consumer.xml" />
- </beans>
加载 Spring 配置, 调用服务:
- package com.test;
- import java.io.IOException;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class Test {
- public static void main(String[] args) {
- ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "classpath:springmvc.xml" });
- context.start();
- DemoService demoService = (DemoService) context.getBean("demoService");
- System.out.println(demoService.sayHello("哈哈哈"));
- try {
- System.in.read();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
如果出现以下结果则调用成功
通过 dubbo-admin 管理后台可以看到服务的提供方与消费方
具体搭建可参考博客:
提供方:
消费者:
来源: https://www.cnblogs.com/lixiangfei/p/9732800.html