分布式软件架构(二)RPC框架dubbo

野性酷女 2022-11-07 13:26 320阅读 0赞

RPC框架

什么是RPC

RPC(remote procedure cal)l,即远程过程调用。比如两台服务器A和B,A服务器上部署一个应用,B服务器上部署一个应用,A服务器上的应用想调用B服务器上的应用提供的方法,由于两个应用不在一个内存空间,不能直接调用,所以需要通过网络来表达调用的语义和传达调用的数据。RPC并不是一个具体的技术,而是指整个网络远程调用过程。
RPC是一个泛化的概念,严格来说一切远程过程调用手段都属于RPC范畴。各种开发语言都有自己的RPC框架。 Java中的RPC框架比较多,广泛使用的有RMI、Hessian、Dubbo等。 *即dubbo 是javaRPC框架成员之一。

dubbo的简介

Apache Dubbo是一款高性能的Java RPC框架。其前身是阿里巴巴公司开源的一个高性能、轻量级的开源Java RPC框架,可以和Spring框架无缝集成。Dubbo 提供了六大核心能力:面向接口代理的高性能RPC调用,智能容错和负载均衡,服务自动注册和发现,高度可扩展能力,运行期流量调度,可视化的服务治理与运维。

dubbo 架构

在这里插入图片描述






























节点 角色名称
Provider 暴露服务的服务提供方
Consumer 调用远程服务的服务消费方
Registry 服务注册与发现的注册中心
Monitor 统计服务的调用次数和调用时间的监控中心(监控中心并不是必须的)
Container 服务运行容器

虚线都是异步访问,实线都是同步访问
蓝紫色色虚线:在启动时完成的功能
蓝绿色虚线(实线)都是程序运行过程中执行的功能

执行步骤

  1. 服务容器负责启动,加载,运行服务提供者。
  2. 服务提供者在启动时,向注册中心注册自己提供的服务。
  3. 服务消费者在启动时,向注册中心订阅自己所需的服务。
  4. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
  5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
  6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

服务注册中心

Zookeeper 是 Apache Hadoop 的子项目,是一个树型的目录服务,支持变更推送,适合作为 Dubbo 服务的注册中心,工业强度较高,可用于生产环境,并推荐使用 。

zookeeper 目录架构

在这里插入图片描述

基本工作流程
  1. 服务提供者(Provider)启动时: 向 /dubbo/com.foo.BarService/providers 目录下写入自己的 URL 地址
  2. 服务消费者(Consumer)启动时: 订阅 /dubbo/com.foo.BarService/providers 目录下的提供者 URL 地址。并向 /dubbo/com.foo.BarService/consumers 目录下写入自己的 URL 地址
  3. 监控中心(Monitor)启动时: 订阅 /dubbo/com.foo.BarService 目录下的所有提供者和消费者 URL 地址
zookeeper的下载

zookeeper是常用的apache工具,下载可以直接上镜像即可。
在这里插入图片描述

zookeeper安装

上传到linux

  1. rz

在这里插入图片描述
查看是否有zookeeper运行

  1. ps -ef | grep zookeeper

若果界面干净就可以安装zookeeper
将压缩包解压解压到指定目录

  1. tar -zxvf apache-zookeeper-3.6.2-bin.tar.gz -C /usr/local/

在zookeeper中建立data文件夹,便于存储数据

  1. mkdir data

在这里插入图片描述
进入conf

  1. cd conf

重命名 zoo_sample.cfg为 zoo.cfg。

  1. mv zoo_sample.cfg zoo.cfg
  2. ### 或者采用
  3. cp zoo_sample.cfg zoo.cfg #### 源文件不删除

编辑 zoo.cfg

  1. vim zoo.cfg

在这里插入图片描述
保存 esc+wq!即可。

zookeeper的启动和停止

进入zookeeper的bin目录

  1. cd bin

启动本zookeeper
在这里插入图片描述

  1. ./zkServer.sh start

在这里插入图片描述
查看zookeeper是否运行

  1. ps -ef | grep zookeeper
  2. ####或者采用
  3. ./zkServer.sh status

在这里插入图片描述
停止zookeeper再次查看状态

  1. ./zkServer.sh stop

在这里插入图片描述
zookeeper重启
在这里插入图片描述

dubbo管理控制台

我们在开发时,需要知道Zookeeper注册中心都注册了哪些服务,有哪些消费者来消费这些服务。我们可以通过部署一个管理中心来实现。其实管理中心就是一个web应用,部署到tomcat即可。除了这种思路外,我们还可以参考 dubbo管理工具之dubbo-admin安装使用,这篇文章也写得非常详细,这篇文章是直接运行在将dubbo-admin直接在idea中运行。

控制台安装

如何制作war包和安装控制台也可以参考这篇文章
(1)将dubbo-admin-2.6.0.war文件复制到tomcat的webapps目录下

(2)启动tomcat,此war文件会自动解压

(3)修改WEB-INF下的dubbo.properties文件,注意dubbo.registry.address对应的值需要对应当前使用的Zookeeper的ip地址和端口号

  1. dubbo.registry.address=zookeeper://192.168.168.128:2181
  2. dubbo.admin.root.password=root
  3. dubbo.admin.guest.password=guest

(4)重启tomcat

使用

默认用户root和guest,直接采用root登录即可默认密码也是root。

在这里插入图片描述
在这里插入图片描述
小猿的服务一致处于开启状态,所以在服务列表中会自动展现。

doubbo的应用

案例目录结构
在这里插入图片描述

父工程pom文件。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <groupId>com.feitian</groupId>
  7. <artifactId>mavendubbo</artifactId>
  8. <packaging>pom</packaging>
  9. <version>1.0-SNAPSHOT</version>
  10. <modules>
  11. <module>dubboprovider</module>
  12. <module>dubboconsumer</module>
  13. <module>dubbodao</module>
  14. </modules>
  15. <properties>
  16. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  17. <maven.compiler.source>1.8</maven.compiler.source>
  18. <maven.compiler.target>1.8</maven.compiler.target>
  19. <spring.version>5.0.5.RELEASE</spring.version>
  20. <log4j.version>1.2.17</log4j.version>
  21. <slf4j-log4j12.version>1.7.7</slf4j-log4j12.version>
  22. <commons-logging.version>1.2</commons-logging.version>
  23. <mysql-connector-java.version>5.1.47</mysql-connector-java.version>
  24. <druid.version>1.1.6</druid.version>
  25. <mybatis-spring.version>1.3.2</mybatis-spring.version>
  26. </properties>
  27. <dependencyManagement>
  28. <dependencies>
  29. <dependency>
  30. <groupId>org.springframework</groupId>
  31. <artifactId>spring-context</artifactId>
  32. <version>${ spring.version}</version>
  33. </dependency>
  34. <dependency>
  35. <groupId>org.springframework</groupId>
  36. <artifactId>spring-beans</artifactId>
  37. <version>${ spring.version}</version>
  38. </dependency>
  39. <dependency>
  40. <groupId>org.springframework</groupId>
  41. <artifactId>spring-webmvc</artifactId>
  42. <version>${ spring.version}</version>
  43. </dependency>
  44. <dependency>
  45. <groupId>org.springframework</groupId>
  46. <artifactId>spring-core</artifactId>
  47. <version>${ spring.version}</version>
  48. </dependency>
  49. <dependency>
  50. <groupId>org.springframework</groupId>
  51. <artifactId>spring-jdbc</artifactId>
  52. <version>${ spring.version}</version>
  53. </dependency>
  54. <dependency>
  55. <groupId>org.springframework</groupId>
  56. <artifactId>spring-aop</artifactId>
  57. <version>${ spring.version}</version>
  58. </dependency>
  59. <dependency>
  60. <groupId>org.springframework</groupId>
  61. <artifactId>spring-web</artifactId>
  62. <version>${ spring.version}</version>
  63. </dependency>
  64. <dependency>
  65. <groupId>org.springframework</groupId>
  66. <artifactId>spring-expression</artifactId>
  67. <version>${ spring.version}</version>
  68. </dependency>
  69. <dependency>
  70. <groupId>org.springframework</groupId>
  71. <artifactId>spring-aspects</artifactId>
  72. <version>${ spring.version}</version>
  73. </dependency>
  74. <dependency>
  75. <groupId>org.springframework</groupId>
  76. <artifactId>spring-jms</artifactId>
  77. <version>${ spring.version}</version>
  78. </dependency>
  79. <dependency>
  80. <groupId>org.springframework</groupId>
  81. <artifactId>spring-context-support</artifactId>
  82. <version>${ spring.version}</version>
  83. </dependency>
  84. <dependency>
  85. <groupId>mysql</groupId>
  86. <artifactId>mysql-connector-java</artifactId>
  87. <version>${ mysql-connector-java.version}</version>
  88. </dependency>
  89. <dependency>
  90. <groupId>com.alibaba</groupId>
  91. <artifactId>druid</artifactId>
  92. <version>${ druid.version}</version>
  93. </dependency>
  94. <dependency>
  95. <groupId>org.mybatis</groupId>
  96. <artifactId>mybatis-spring</artifactId>
  97. <version>${ mybatis-spring.version}</version>
  98. </dependency>
  99. </dependencies>
  100. </dependencyManagement>
  101. <build>
  102. <plugins>
  103. <plugin>
  104. <groupId>org.apache.maven.plugins</groupId>
  105. <artifactId>maven-compiler-plugin</artifactId>
  106. <version>3.1</version>
  107. <configuration>
  108. <source>1.8</source>
  109. <target>1.8</target>
  110. <encoding>UTF-8</encoding>
  111. </configuration>
  112. </plugin>
  113. </plugins>
  114. </build>
  115. </project>

注意父工程可能内导入的jar包原型可能不是全部都有用。

dubboprovider

目录结构
在这里插入图片描述

dubboprovider pom文件
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <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">
  3. <parent>
  4. <artifactId>mavendubbo</artifactId>
  5. <groupId>com.feitian</groupId>
  6. <version>1.0-SNAPSHOT</version>
  7. <relativePath>../pom.xml</relativePath>
  8. </parent>
  9. <modelVersion>4.0.0</modelVersion>
  10. <artifactId>dubboprovider</artifactId>
  11. <packaging>war</packaging>
  12. <dependencies>
  13. <dependency>
  14. <groupId>org.springframework</groupId>
  15. <artifactId>spring-web</artifactId>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.springframework</groupId>
  19. <artifactId>spring-webmvc</artifactId>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.springframework</groupId>
  23. <artifactId>spring-core</artifactId>
  24. </dependency>
  25. <dependency>
  26. <groupId>com.feitian</groupId>
  27. <artifactId>dubbodao</artifactId>
  28. <version>1.0-SNAPSHOT</version>
  29. </dependency>
  30. </dependencies>
  31. <build>
  32. <plugins>
  33. <plugin>
  34. <groupId>org.apache.tomcat.maven</groupId>
  35. <artifactId>tomcat7-maven-plugin</artifactId>
  36. <version>2.2</version>
  37. <configuration>
  38. <!-- 指定端口 -->
  39. <port>8081</port>
  40. <!-- 请求路径 -->
  41. <path>/</path>
  42. </configuration>
  43. </plugin>
  44. </plugins>
  45. </build>
  46. </project>

dubboprovider 需要依赖dubbodao 的jar包。

HiPyService
  1. public interface HiPyService {
  2. public String hiPyService(String name);
  3. }
HiPyServiceImpl
  1. /*@Service(protocol = "dubbo", interfaceClass = HiPyService.class, loadbalance="random")*/
  2. @Service
  3. public class HiPyServiceImpl implements HiPyService {
  4. @Override
  5. public String hiPyService(String name) {
  6. return "port8081hello" + name;
  7. }
  8. }

此处需要注意的@Service注解需要用dubbo下面注解。

applicationContext-service.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <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">
  3. <!-- 当前应用名称,用于注册中心计算应用间依赖关系,注意:消费者和提供者应用名不要一样 -->
  4. <dubbo:application name="dubbo_provider" />
  5. <!-- 连接服务注册中心zookeeper ip为zookeeper所在服务器的ip地址-->
  6. <dubbo:registry address="zookeeper://192.168.168.128:2181"/>
  7. <!-- 注册 协议和port 端口默认是20880 -->
  8. <dubbo:protocol name="dubbo" port="20881"></dubbo:protocol>
  9. <!-- 扫描指定包,加入@Service注解的类会被发布为服务 -->
  10. <dubbo:annotation package="com.feitian.service" />
  11. <!--<bean id="hiPyService" class="com.feitian.service.impl.HiPyServiceImpl"/> <dubbo:service interface="com.feitian.service.HiPyService" ref="hiPyService"/>-->
  12. </beans>

需要服务系统者将服务提供给注册中心。

web.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <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">
  3. <display-name>Archetype Created Web Application</display-name>
  4. <context-param>
  5. <param-name>contextConfigLocation</param-name>
  6. <param-value>classpath*:applicationContext*.xml</param-value>
  7. </context-param>
  8. <listener>
  9. <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  10. </listener>
  11. <!-- 防止Spring内存溢出监听器 -->
  12. <listener>
  13. <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
  14. </listener>
  15. </web-app>

在服务提供者tomcat服务器启动时,需要用监听器将服务添加到注册中心。

log4j配置文件
  1. ### direct log messages to stdout ###
  2. log4j.appender.stdout=org.apache.log4j.ConsoleAppender
  3. log4j.appender.stdout.Target=System.err
  4. log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
  5. log4j.appender.stdout.layout.ConversionPattern=%d{ ABSOLUTE} %5p %c{ 1}:%L - %m%n
  6. ### direct messages to file mylog.log ###
  7. log4j.appender.file=org.apache.log4j.FileAppender
  8. log4j.appender.file.File=c:/mylog.log
  9. log4j.appender.file.layout=org.apache.log4j.PatternLayout
  10. log4j.appender.file.layout.ConversionPattern=%d{ ABSOLUTE} %5p %c{ 1}:%L - %m%n
  11. ### set log levels - for more verbose logging change 'info' to 'debug' ###
  12. log4j.rootLogger=debug, stdout

需要观察日志,加入日志配置文件,zookeeper中已经导入日志依赖,无需再次导入。
在这里插入图片描述

dubboconsummer

目录结构

在这里插入图片描述

pom文件

pom文件与dubboprovider基本一致,需要改tomcat插件端口

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <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">
  3. <parent>
  4. <artifactId>mavendubbo</artifactId>
  5. <groupId>com.feitian</groupId>
  6. <version>1.0-SNAPSHOT</version>
  7. <relativePath>../pom.xml</relativePath>
  8. </parent>
  9. <modelVersion>4.0.0</modelVersion>
  10. <artifactId>dubboconsumer</artifactId>
  11. <packaging>war</packaging>
  12. <dependencies>
  13. <dependency>
  14. <groupId>org.springframework</groupId>
  15. <artifactId>spring-context</artifactId>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.springframework</groupId>
  19. <artifactId>spring-beans</artifactId>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.springframework</groupId>
  23. <artifactId>spring-webmvc</artifactId>
  24. </dependency>
  25. <dependency>
  26. <groupId>org.springframework</groupId>
  27. <artifactId>spring-jdbc</artifactId>
  28. </dependency>
  29. <dependency>
  30. <groupId>org.springframework</groupId>
  31. <artifactId>spring-aspects</artifactId>
  32. </dependency>
  33. <dependency>
  34. <groupId>org.springframework</groupId>
  35. <artifactId>spring-jms</artifactId>
  36. </dependency>
  37. <dependency>
  38. <groupId>org.springframework</groupId>
  39. <artifactId>spring-context-support</artifactId>
  40. </dependency>
  41. <!-- dubbo相关 -->
  42. <dependency>
  43. <groupId>com.alibaba</groupId>
  44. <artifactId>dubbo</artifactId>
  45. <version>2.6.0</version>
  46. </dependency>
  47. <dependency>
  48. <groupId>org.apache.zookeeper</groupId>
  49. <artifactId>zookeeper</artifactId>
  50. <version>3.4.7</version>
  51. </dependency>
  52. <dependency>
  53. <groupId>com.github.sgroschupf</groupId>
  54. <artifactId>zkclient</artifactId>
  55. <version>0.1</version>
  56. </dependency>
  57. <dependency>
  58. <groupId>javassist</groupId>
  59. <artifactId>javassist</artifactId>
  60. <version>3.12.1.GA</version>
  61. </dependency>
  62. <dependency>
  63. <groupId>com.alibaba</groupId>
  64. <artifactId>fastjson</artifactId>
  65. <version>1.2.47</version>
  66. </dependency>
  67. <!--<dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </dependency>-->
  68. </dependencies>
  69. <build>
  70. <plugins>
  71. <plugin>
  72. <groupId>org.apache.tomcat.maven</groupId>
  73. <artifactId>tomcat7-maven-plugin</artifactId>
  74. <version>2.2</version>
  75. <configuration>
  76. <!-- 指定端口 -->
  77. <port>8083</port>
  78. <!-- 请求路径 -->
  79. <path>/</path>
  80. </configuration>
  81. </plugin>
  82. </plugins>
  83. </build>
  84. </project>
controller
  1. @Controller
  2. @RequestMapping("/hiPPyController")
  3. public class PyController {
  4. /*@Reference(check = false,loadbalance = "random")*/
  5. /* @Autowired*/
  6. @Reference
  7. private HiPyService hiPyService;
  8. @RequestMapping("/hiPython")
  9. @ResponseBody
  10. public String hiPython(String name){
  11. return hiPyService.hiPyService(name);
  12. }
  13. }
HiPyService
  1. public interface HiPyService {
  2. public String hiPyService(String name);
  3. }

需要将dubboprovider 的HiPyService接口拷贝一份,但拷贝是否构成了整个案例的代码冗余呢?

applicationContext_web.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <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">
  3. <!-- 当前应用名称,用于注册中心计算应用间依赖关系,注意:消费者和提供者应用名不要一样 -->
  4. <dubbo:application name="dubbo_consummer" />
  5. <!-- 连接服务注册中心zookeeper ip为zookeeper所在服务器的ip地址-->
  6. <dubbo:registry address="zookeeper://192.168.168.128:2181"/>
  7. <!-- 扫描指定包,加入@Service注解的类会被发布为服务 -->
  8. <dubbo:annotation package="com.feitian.controller" />
  9. <!--直接注入即可相当于替代了包扫描和reference标签-->
  10. <!--<dubbo:reference id="hiPyService" interface="com.feitian.service.HiPyService" />-->
  11. <!--启动不检查-->
  12. <dubbo:consumer check="false"/>
  13. </beans>

此处注意的是不再需要声明远程调用协议,如果开启了启动不检查,那么就无需顾忌provider和consummer的顺序了。

web.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <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">
  3. <servlet>
  4. <servlet-name>springmvc</servlet-name>
  5. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  6. <init-param>
  7. <param-name>contextConfigLocation</param-name>
  8. <param-value>classpath:applicationContext_web.xml</param-value>
  9. </init-param>
  10. <load-on-startup>1</load-on-startup>
  11. </servlet>
  12. <servlet-mapping>
  13. <servlet-name>springmvc</servlet-name>
  14. <url-pattern>/</url-pattern>
  15. </servlet-mapping>
  16. </web-app>

一般在前端控制器初始化时,将服务需求注册到服务中心。

日志文件

日志文件保持与provider一致即可。

dubbodao

文件目录

在这里插入图片描述

dubbodao pom配置文件
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <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">
  3. <parent>
  4. <artifactId>mavendubbo</artifactId>
  5. <groupId>com.feitian</groupId>
  6. <version>1.0-SNAPSHOT</version>
  7. </parent>
  8. <modelVersion>4.0.0</modelVersion>
  9. <artifactId>dubbodao</artifactId>
  10. <packaging>jar</packaging>
  11. <dependencies>
  12. <dependency>
  13. <groupId>org.springframework</groupId>
  14. <artifactId>spring-context</artifactId>
  15. </dependency>
  16. <dependency>
  17. <groupId>org.springframework</groupId>
  18. <artifactId>spring-beans</artifactId>
  19. </dependency>
  20. <dependency>
  21. <groupId>org.springframework</groupId>
  22. <artifactId>spring-jdbc</artifactId>
  23. </dependency>
  24. <dependency>
  25. <groupId>org.springframework</groupId>
  26. <artifactId>spring-aspects</artifactId>
  27. </dependency>
  28. <dependency>
  29. <groupId>org.springframework</groupId>
  30. <artifactId>spring-jms</artifactId>
  31. </dependency>
  32. <dependency>
  33. <groupId>org.springframework</groupId>
  34. <artifactId>spring-context-support</artifactId>
  35. </dependency>
  36. <!-- dubbo相关 -->
  37. <dependency>
  38. <groupId>com.alibaba</groupId>
  39. <artifactId>dubbo</artifactId>
  40. <version>2.6.0</version>
  41. </dependency>
  42. <dependency>
  43. <groupId>org.apache.zookeeper</groupId>
  44. <artifactId>zookeeper</artifactId>
  45. <version>3.4.7</version>
  46. </dependency>
  47. <dependency>
  48. <groupId>com.github.sgroschupf</groupId>
  49. <artifactId>zkclient</artifactId>
  50. <version>0.1</version>
  51. </dependency>
  52. <dependency>
  53. <groupId>javassist</groupId>
  54. <artifactId>javassist</artifactId>
  55. <version>3.12.1.GA</version>
  56. </dependency>
  57. <dependency>
  58. <groupId>com.alibaba</groupId>
  59. <artifactId>fastjson</artifactId>
  60. <version>1.2.47</version>
  61. </dependency>
  62. <dependency>
  63. <groupId>mysql</groupId>
  64. <artifactId>mysql-connector-java</artifactId>
  65. </dependency>
  66. <dependency>
  67. <groupId>com.alibaba</groupId>
  68. <artifactId>druid</artifactId>
  69. </dependency>
  70. <dependency>
  71. <groupId>org.mybatis</groupId>
  72. <artifactId>mybatis-spring</artifactId>
  73. </dependency>
  74. </dependencies>
  75. </project>
applicationContext-dao.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <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" xmlns:tx="http://www.springframework.org/schema/tx" 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/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
  3. <context:property-placeholder location="jdbc.properties"/>
  4. <!--配置数据源信息,使用druid连接池-->
  5. <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
  6. <property name="driverClassName" value="${jdbc.driver}"/>
  7. <property name="url" value="${jdbc.url}"/>
  8. <property name="username" value="${jdbc.username}"/>
  9. <property name="password" value="${jdbc.password}"/>
  10. </bean>
  11. <!-- 事务管理器 -->
  12. <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  13. <property name="dataSource" ref="dataSource"/>
  14. </bean>
  15. <!--开启事务控制的注解支持-->
  16. <tx:annotation-driven transaction-manager="transactionManager"/>
  17. </beans>

此处要加入事务管理器和数据库的一些配置,注意此处只是为了生成数据源进行事务管理,而非真正的操作数据库。

properties配置文件
  1. jdbc.driver=com.mysql.jdbc.Driver
  2. jdbc.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8
  3. jdbc.username=root
  4. jdbc.password=root

在这里插入图片描述
在这里插入图片描述
可以看出案例成功运行。

dubbo配置文件解析

包扫描

  1. <!-- 扫描指定包,加入@Service注解的类会被发布为服务 -->
  2. <dubbo:annotation package="com.feitian.service" />

服务提供者和服务消费者都需要配置,表示包扫描,作用是扫描指定包(包括子包)下的类。如果不使用包扫描,也可以通过如下配置的方式来发布服务:

  1. <bean id="hiPyService" class="com.feitian.service.impl.HiPyServiceImpl"/>
  2. <dubbo:service interface="com.feitian.service.HiPyService" ref="hiPyService"/>

相当于替代了

  1. <dubbo:annotation package="com.feitian.service" />

作为服务消费者,可以通过如下配置来引用服务:

  1. <dubbo:reference id="hiPyService" interface="com.feitian.service.HiPyService" />

在接口上加上@Autowired

  1. @Autowired
  2. private HiPyService hiPyService;

相当于替代了了dubbo的@Reference标签。

上面这种方式发布和引用服务,一个配置项(dubbo:service、dubbo:reference)只能发布或者引用一个服务,如果有多个服务,这种方式就比较繁琐了。推荐使用包扫描方式。

dubbo协议

一般dubbo的默认protocol为dubbo,一般建议在provider方指定协议。

  1. <!-- 注册 协议和port 端口默认是20880 -->
  2. <dubbo:protocol name="dubbo" port="20881"></dubbo:protocol>

Dubbo支持的协议有:dubbo、rmi、hessian、http、webservice、rest、redis等。推荐使用的是dubbo协议。

dubbo 协议采用单一长连接和 NIO 异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。 不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低。也可以在同一个工程中配置多个协议,不同服务可以使用不同的协议,例如:

  1. <!-- 多协议配置 -->
  2. <dubbo:protocol name="dubbo" port="20881" />
  3. <dubbo:protocol name="rmi" port="1099" />
  4. <!-- 使用dubbo协议暴露服务 -->
  5. <dubbo:service interface="com.feitian.service.HelloService" ref="helloService" protocol="dubbo" />
  6. <!-- 使用rmi协议暴露服务 -->
  7. <dubbo:service interface="com.feitian.service.DemoService" ref="demoService" protocol="rmi" />

也可以通过在注解中配置协议,指定所要的RPC协议

  1. @Service(protocol = "rmi")
  2. public class HiPyServiceImpl implements HiPyService {
  3. @Override
  4. public String hiPyService(String name) {
  5. return "hello" + name;
  6. }
  7. }

启动时检查

默认情况下 服务提供方和服务消费方启动有先后顺序,会检查对应的服务提供方有没有注册服务,若没有就会报错,这种情况就给开发者带来了困扰,所以在开发阶段建议停止检查则在服务消费方引入一下配置:

  1. <dubbo:consumer check="false"/>

也可用 @Reference(check = false)来替代删除xml配置文件。如果不配置默认check值为true。Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,以便上线时,能及早发现问题。可以通过将check值改为false来关闭检查。

建议在开发阶段将check值设置为false,在生产环境下改为true。

负载均衡

负载均衡(Load Balance):本质上就是将请求分摊到多个操作单元上进行执行,从而共同完成工作任务。

在集群负载均衡时,Dubbo 提供了多种均衡策略(包括随机、轮询、最少活跃调用数、一致性Hash),缺省为random随机调用。

配置负载均衡策略,既可以在服务提供者一方配置,也可以在服务消费者一方配置,如下:

负载均衡小案例
服务消费方
  1. @Controller
  2. @RequestMapping("/hiPPyController")
  3. public class PyController {
  4. @Reference(check = false,loadbalance = "random")
  5. /* @Autowired*/
  6. private HiPyService hiPyService;
  7. @RequestMapping("/hiPython")
  8. @ResponseBody
  9. public String hiPython(String name){
  10. return hiPyService.hiPyService(name);
  11. }
  12. }
服务提供方
  1. @Service(protocol = "dubbo",loadbalance="random")
  2. /*@Service*/
  3. @Transactional
  4. public class HiPyServiceImpl implements HiPyService {
  5. @Override
  6. public String hiPyService(String name) {
  7. return "port8081hello" + name;
  8. }
  9. }

注意要修改dubbo协议端口
在这里插入图片描述
在这里插入图片描述
由此就可以是此案consumer随机调用provider提供的service。

Dubbo的发布与事务代理问题

如果在服务提供者类上加入@Transactional事务控制注解后,服务就发布不成功了。 原因是事务控制的底层原理是为服务提供者类创建代理对象,而默认情况下Spring是基于JDK动态代理方式创建代理对象,而此代理对象的完整类名为com.sun.proxy.$Proxy42(最后两位数字不是固定的),导致Dubbo在发布服务前进行包匹配时无法完成匹配,进而没有进行服务的发布。

修改案例,引入dao
在这里插入图片描述

修改dubboprovider的HiPyServiceImpl
  1. @Service(protocol = "dubbo", loadbalance="random")
  2. /*@Service*/
  3. @Transactional
  4. public class HiPyServiceImpl implements HiPyService {
  5. @Override
  6. public String hiPyService(String name) {
  7. return "port8081hello" + name;
  8. }
  9. }

启动provider和consummer
在这里插入图片描述
在这里插入图片描述
访问报错
在这里插入图片描述
其奥妙就在这个类中AnnotationBean这个类中。
在这里插入图片描述
dubbo对于服务的发布最终是通过AnnotationBean的postProcessAfterInitialization方法进行处理。
当以debug方式启动时,首先会进入下年的方法
在这里插入图片描述
然后会进入

在这里插入图片描述

在两种方法中都调用了下面的方法

  1. private boolean isMatchPackage(Object bean) {
  2. if (this.annotationPackages != null && this.annotationPackages.length != 0) {
  3. String beanClassName = bean.getClass().getName();
  4. String[] arr$ = this.annotationPackages;
  5. int len$ = arr$.length;
  6. for(int i$ = 0; i$ < len$; ++i$) {
  7. String pkg = arr$[i$];
  8. if (beanClassName.startsWith(pkg)) {
  9. return true;
  10. }
  11. }
  12. return false;
  13. } else {
  14. return true;
  15. }
  16. }

调试过程中发现有如下问题
在这里插入图片描述

解决问题的关键
  1. 指定cglib代理

  2. 指定代理接口

    @Service(protocol = “dubbo”, interfaceClass = HiPyService.class, loadbalance=”random”)
    @Transactional
    public class HiPyServiceImpl implements HiPyService {

    1. @Override
    2. public String hiPyService(String name) {
    3. return "port8081hello" + name;
    4. }

    }

发布成功
在这里插入图片描述
访问发信可以正常调用。

dubbo常见问题

思考一: 上面的Dubbo入门案例中我们是将HiPyService接口从服务提供者工程(dubboprovider)复制到服务消费者工程(dubboconsumer)中,这种做法是否合适?还有没有更好的方式?

答: 同一个接口被复制了两份,项目代码冗余严重,不利于后期维护。更好的方式是单独创建一个maven工程,将此接口创建在这个maven工程中。需要依赖此接口的工程只需要在自己工程的pom.xml文件中引入maven坐标即可。

思考二: 在服务消费者工程(dubboconsumer)中只是引用了HiPyService接口,并没有提供实现类,Dubbo是如何做到远程调用的?

答: Dubbo底层是基于代理技术为HiPyService接口创建代理对象,远程调用是通过此代理对象完成的。可以通过开发工具的debug功能查看此代理对象的内部结构。另外,Dubbo实现网络传输底层是基于Netty框架完成的。

思考三: 上面的Dubbo入门案例中我们使用Zookeeper作为服务注册中心,服务提供者需要将自己的服务信息注册到Zookeeper,服务消费者需要从Zookeeper订阅自己所需要的服务,此时Zookeeper服务就变得非常重要了,那如何防止Zookeeper单点故障呢?

答: Zookeeper其实是支持集群模式的,可以配置Zookeeper集群来达到Zookeeper服务的高可用,防止出现单点故障。

发表评论

表情:
评论列表 (有 0 条评论,320人围观)

还没有评论,来说两句吧...

相关阅读

    相关 RPC框架——Dubbo

    Dubbo简介 Dubbo是用来实现分布式RPC调用的框架。 Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。

    相关 RPC框架】之 Dubbo

    一、分布式基础理论 -------------------- 1、什么是分布式系统 《分布式系统原理与范型》定义: 分布式系统是若干独立计算机的集合,这些计算机