目录
4.可能会遇到的问题(解决Dubbo无法发布被事务代理的Service问题 )
1. Dubbo概述
1.1 Dubbo简介
- 面向接口的远程方法调用
- 智能容错和负载均衡
- 以及服务自动注册和发现
1.2 Dubbo架构
图片来源于网络.
节点
|
角色名称
|
---|---|
Provider
|
暴露服务的服务提供方
|
Consumer
|
调用远程服务的服务消费方
|
Registry
|
服务注册与发现的注册中心
|
Monitor
|
统计服务的调用次数和调用时间的监控中心
|
Container
|
服务运行容器
|
0. 服务容器负责启动,加载,运行服务提供者。1. 服务提供者在启动时,向注册中心注册自己提供的服务。2. 服务消费者在启动时,向注册中心订阅自己所需的服务。3. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。4. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
2. Zookeeper(服务注册中心)
通过前面的Dubbo架构图可以看到,Registry(服务注册中心)在其中起着至关重要的作用。Dubbo官 方推荐使用Zookeeper作为服务注册中心。
2.1 Zookeeper介绍
![](https://img-blog.csdnimg.cn/ff48c3832c0444d9bbaecc830c144458.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA566A57qm55qE5ra144CB,size_20,color_FFFFFF,t_70,g_se,x_16)
Zookeeper树型目录服务:
- 服务提供者(Provider)启动时: 向 /dubbo/com.foo.BarService/providers 目录下写入自己的URL 地址
- 服务消费者(Consumer)启动时: 订阅 /dubbo/com.foo.BarService/providers 目录下的提供者 URL 地址。并向 /dubbo/com.foo.BarService/consumers 目录下写入自己的 URL 地址
- 监控中心(Monitor)启动时: 订阅 /dubbo/com.foo.BarService 目录下的所有提供者和消费者 URL 地址
2.2 安装Zookeeper
下载地址:http://archive.apache.org/dist/zookeeper/
安装步骤:
第一步:安装 jdk (略)第二步:把 zookeeper 的压缩包( zookeeper-3.4.6.tar.gz )上传到 linux 系 统第三步:解压缩压缩包 tar -zxvf zookeeper-3.4.6.tar.gz -C /usr第四步:进入 zookeeper-3.4.6 目 录,创建 data 目录 mkdir data第五步:进入 conf 目录,把 zoo_sample.cfg 改名为 zoo.cfgcd confmv zoo_sample.cfg zoo.cfg第六步:打开 zoo.cfg 文件 , 修改 data 属性: dataDir=/usr/zookeeper- 3.4.6/data
2.3 Zookeeper基本指令
进入Zookeeper的bin目录,启动服务命令
./zkServer.sh start
停止服务命令
./zkServer.sh stop
查看服务状态:
./zkServer.sh status
客户端连接
./zkCli.sh
3. Dubbo入门案例
3.1 服务提供方开发
3.1.1 项目整体架构
3.1.2 各个部分代码
maven
<?xml version="1.0" encoding="UTF-8"?> <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.csh</groupId> <artifactId>provider</artifactId> <version>1.0-SNAPSHOT</version> <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> <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> <version>2.2</version> <configuration> <!-- 指定端口 --> <port>8081</port> <!-- 请求路径 --> <path>/</path> </configuration> </plugin> </plugins> </build> </project>
applicationContext-service.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="dubbodemo_provider"/> <!-- 连接服务注册中心zookeeper ip为zookeeper所在服务器的ip地址--> <dubbo:registry address="zookeeper://192.168.43.3:2181"/> <!-- 注册 协议和port 默认20880 --> <dubbo:protocol name="dubbo" port="20881"></dubbo:protocol> <!-- 扫描指定包,加入@Service注解的类会被发布为服务 --> <dubbo:annotation package="com.csh.service.impl"/> </beans>
HelloService
public interface HelloService { public String sayHello(String name); }
HelloServiceImpl
@Service public class HelloServiceImpl implements HelloService { @Override public String sayHello(String name) { return "Hello : "+name; } }
3.2 服务消费方开发
3.2.1 项目整体架构
maven
<?xml version="1.0" encoding="UTF-8"?> <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.csh</groupId> <artifactId>consumer</artifactId> <version>1.0-SNAPSHOT</version> <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> <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> <version>2.2</version> <configuration> <!-- 指定端口 --> <port>8082</port> <!-- 请求路径 --> <path>/</path> </configuration> </plugin> </plugins> </build> </project>
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="dubbodemo_consumer"/> <!-- 连接服务注册中心zookeeper ip为zookeeper所在服务器的ip地址--> <dubbo:registry address="zookeeper://192.168.43.3:2181"/> <!-- <!– 注册 协议和port 默认20880 消费者不需要发布所以不需要这个--> <!-- <dubbo:protocol name="dubbo" port="20881"></dubbo:protocol>--> <!-- 扫描指定包,加入@Service注解的类会被发布为服务 --> <dubbo:annotation package="com.csh.controller"/> </beans>
web.xml
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <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> </servlet> <servlet-mapping> <servlet-name>SpringMVC</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
HelloController
@RestController @RequestMapping("/demo") public class HelloController { @Reference private HelloService helloService; @RequestMapping("/hello") public String sayHello(String name){ String result = helloService.sayHello(name); System.out.println(result); return result; } }
HelloService
public interface HelloService { public String sayHello(String name); }
3.3 启动并测试
首先启动zookeeper
./zkServer.sh start //启动zookeeper
./zkCli.sh //与客户端连接
然后启动 provider
最后启动 consumer
使用浏览器 访问
localhost:8082/demo/hello?name=csh
出现结果
证明 测试成功
4.可能会遇到的问题(解决Dubbo无法发布被事务代理的Service问题 )
4.1 错误场景
![](https://img-blog.csdnimg.cn/89f62fbe1920432fb6bfd859e921bcd9.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA566A57qm55qE5ra144CB,size_20,color_FFFFFF,t_70,g_se,x_16)
4.2 错误提示
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982) org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866) javax.servlet.http.HttpServlet.service(HttpServlet.java:621) org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851) javax.servlet.http.HttpServlet.service(HttpServlet.java:728) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
4.3 解决办法
4.3.1 步骤一
修改applicationContext-service.xml配置文件,开启事务控制注解支持时指定proxy-target-class
属性,值为true。其作用是使用cglib代理方式为Service类创建代理对象
<!--开启事务控制的注解支持-->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-
class="true"/>
4.3.2 步骤二
修改HelloServiceImpl类,在Service注解中加入interfaceClass属性,值为HelloService.class,
作用是指定服务的接口类型
@Service(interfaceClass = HelloService.class)
@Transactional
public class HelloServiceImpl implements HelloService {
public String sayHello(String name) {
return "hello " + name;
}