Dubbo
# Dubbo
- 阿里巴巴旗下
- 高性能Java RPC框架,和Spring无缝整合
- RPC(运程过程调用) 。两服务器相互调用,此时他们不在同一内存,需要网络进行传递语义和调用的数据
- 分别讲解构架
单体架构
、垂直架构
、SOA架构
、微服务
核心功能:
- 面向接口的远程方法调用
- 智能容错和负载均衡
- 服务自动注册 和 发现
# 环境搭建
# Window 搭建环境
步骤:
解压 zookeeper.gz 压缩包
在 解压后的根路径下 创建文件夹
data
和log
两个更改配置 , 拷贝 ==./conf/zoo_sample.cfg== 至本身路径并更改其名为
zoo.cfg
编辑
zoo.cfg
, 将指定内容 ==dataDir=/tmp/zookeeper== 覆盖为以下内容dataDir=../data dataLogDir=../log
zoo.cfg 包含有很多 和 Dobbo相关配置 自行翻译
初始化加载 , 打开 ==../bin/zkServer==脚本文件 进行加载
显示 ==binding to port 0.0.0.0/0.0.0.0:2181== 成功
# Tomcat 控制台页
- 解压 war包项目
- 将解压文件 放到 Tomcat 中的 webapps文件夹下 注意项目文件 : ==WEB-INF/dubbo.properties== 端口/账号 信息
- 启动tomcat
注意 :
- Tomcat端口更改为
8080
以外的端口- 启动 Tomcat前提 , 先启动 zookeeper
- 确定好 JDK 和 JRE 环境 ( 如果没有配好会加载不到上下文
# QA
页面控制台 Dubbo 上下文加载失败问题
- 环境配置 JRE , 新建环境变量
JRE_HOME
变量名 <-> ==C:\Program Files\Java\jre1.8.0_321==值 (JRE根路径 - 环境引入 Path 引入
JRE_HOME
==%JRE_HOME%\bin==
Controller层 进行RPC操作传参问题
- 实体对象必须实例化 ( 特别说明特殊类型也不行!!
- 传递的参尽可能是基本数据类型
# 首次应用
应用示例:
提供者项目
创建提供者 Maven项目
dubbo-project
配置 依赖、插件
pom.xml
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>5.0.5.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</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-webmvc</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-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- dubbo相关 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.7</version>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
</dependencies>
<build>
<plugins>
<!--Maven Tomcat插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<!-- 指定端口 -->
<port>8082</port>
<!-- 请求路径 -->
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
配置 连接远端zookeeper并注册
resources/applicationContext-service.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc" 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://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 当前应用名称,用于注册中心计算应用间依赖关系,注意:消费者和提供者应用名不要一样 --> <dubbo:application name="dubbo-project"/> <!-- 连接服务注册中心zookeeper ip为zookeeper所在服务器的ip地址--> <dubbo:registry address="zookeeper://192.168.230.132:2181"/> <!-- 注册 协议和port 对外提供的端口 (默认20880)--> <dubbo:protocol name="dubbo" port="20881"/> <!-- 扫描指定包,加入@Service注解的类会被发布为服务 --> <dubbo:annotation package="com.sans.service.impl"/> </beans>
这步IP/Port不知咋填? (Linux命令得知信息)
IP地址:
ifconfig
端口:
jsp
查 PID ,根据 PIDnetstat -tuunpl
查开放端口配置 监听器、配置文件加载
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!--配置文件参数--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext*.xml</param-value> </context-param> <!--监听--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
业务实现 Service
服务接口
HelloService
package com.sans.service; /** 服务接口 */ public interface HelloService { public String sayHello(String name); }
服务实现类
HelloServiceImpl
package com.sans.service.impl; import com.alibaba.dubbo.config.annotation.Service; import com.sans.service.HelloService; // 注意使用的jar包 @Service public class HelloServiceImpl implements HelloService { @Override public String sayHello(String name) { return "hello : " + name; } }
注意:
@Service
注解 是 Dubbo包提供的Linux 启动 Zookeeper
# 在bin目录下 Zookeeper 启动 (root权限)
./zkServer.sh start
> **注意:**连接的前提需要==关闭防火墙==
7. 运行测试
运行连接 : 在Maven执行 Tomcat插件的`run`命令
查看注册信息 : 在Linux执行 查看
```sh
## 在bin目录下 进入查看
./zkCli.sh
## 查看注册列表
ls /
## 查看详细
ls /[注册的名称]
01.png
@Service注解的类服务存在表示注册成功
消费者项目
拷贝生产者的项目
编辑项目名称
dubbo-consumer
配置 tomcat插件端口
pom.xml
(我的是8082端口号)配置 连接远端zookeeper并注册
resources/applicationContext-web.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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 当前应用名称,用于注册中心计算应用间依赖关系,注意:消费者和提供者应用名不要一样 --> <dubbo:application name="dubbo-consumer"/> <!-- 连接服务注册中心zookeeper ip为zookeeper所在服务器的ip地址--> <dubbo:registry address="zookeeper://192.168.230.134:2181"/> <!-- 扫描指定包,加入@RestController注解的类会被发布为服务 --> <dubbo:annotation package="com.sans.controller"/> </beans>
配置 访问的映射
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!--配置文件参数--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext*.xml</param-value> </context-param> <!--监听--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--入口组件 访问映射--> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext-web.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
业务实现 Controller 服务接口
HelloService
package com.sans.controller; import com.alibaba.dubbo.config.annotation.Reference; import com.sans.service.HelloService; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/demo") public class HelloController { // Controller中注入HelloService使用的是Dubbo提供的@Reference注解 (自动注入是无效的) // 注意导包 并非是 jdk @Reference private HelloService helloService; @RequestMapping("/hello") @ResponseBody public String getName(String name) { // 远程调用 String result = helloService.sayHello(name); System.out.println("result : " + result); return result; } }
注意:
@Reference
注解 是 Dubbo包提供的测试 访问 http://localhost:8082/demo/hello?name=test (opens new window) (观察页面返回的数据是否对应)
测试前提:提供者启动且已经连接服务注册中心zookeeper
# Dubbo其他配置
# 包扫描
扫描指定包下的所有类,服务提供者与服务消费者 都需要配置
在 resources
配置资源下的 .xml
(以上应用的是扫描包)
提供者 发布服务
<!-- 扫描指定包,加入@Service注解的类 会被发布为服务 -->
<dubbo:annotation package="com.sans.service.impl"/>
消费者 应用服务
<!-- 扫描指定包,加入@RestController注解的类 会被发布为服务 -->
<dubbo:annotation package="com.sans.controller"/>
服务类应用:(在以上注解类内自动注入应用)
//Dubbo提供的@Reference注解 (用法和自动注入一样) @Reference private HelloService helloService;
# 类扫描
扫描指定包下的指定类,通过以下方式进行发布服务:
在 resources
配置资源下的 .xml
提供者 发布服务
<!-- 扫描指定包的指定类。以下配置相当于 @Service注解 的配置-- >
<!-- 创建bean-->
<bean id="helloService" class="com.sans.service.impl.HelloServiceImpl" />
<!-- dubbo注册服务 (接口)-->
<dubbo:service interface="com.sans.service.HelloService" ref="helloService"/>
PS:
dubbo:service
配置相当于@Service
注解 ,因此必须注释掉@Service
注解
消费者 应用服务
<!-- 生成远程服务代理对象-->
<dubbo:reference id="helloService" interface="com.sans.service.HelloService"/>
<!-- 包扫描-->
<context:component-scan base-package="com.sans.controller"/>
PS:注入类应用时是用
@Autowired
注解,并非是@Reference
注解
# 协议
一般配置在提供者一方进行配置 Dubbo支持协议有:dubbo、rmi、http等协议
建议应用Dubbo协议自带的
Dubbo协议 用于传输小数据量并发的服务调用
同一个项目可配置多个协议,不同服务应用不同协议
<!-- 多协议配置 -->
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:protocol name="rmi" port="1099" />
<!-- 使用dubbo协议暴露服务 -->
<dubbo:service interface="com.sans.service.HelloService" ref="helloService"
protocol="dubbo" />
<!-- 使用rmi协议暴露服务 -->
<dubbo:service interface="com.sans.service.DemoService" ref="demoService"
protocol="rmi" />
服务类协议应用:(默认采用Dubbo协议)
如果该服务类使用Dubbo以外的协议需要指定协议
@Service(protocol = "rmi") public class HelloServiceImpl implements HelloService {····}
# 负载均衡
将服务集群分担完成共同任务,Dubbo提供有常用的均衡策略
负载均衡可在 服务 提供者/消费者 任意一方配置即可实现
提供者
// 生成前 预定策略
@Service(loadbalance = "random")
public class HelloServiceImpl implements HelloService {····}
消费者
// 注入时 应用策略
@Reference(loadbalance = "random")
private HelloService helloService;
PS:一台电脑集群测试是 Dubbo协议的端口 和 Tomcat的端口 不能一样,以防冲突