Dubbo是一款高性能、轻量级的开源Java RPC框架,提供面向接口代理的高性能RPC调用、智能负载均衡、服务自动注册和发现、运行期流量调度、可视化服务治理和运维等功能。
课程连接:06-dubbo概述_哔哩哔哩_bilibili
一、Feign和Dubbo的比较
Feign和Dubbo都是用于实现分布式服务调用的工具,但它们再设计目标、使用场景和实现底层上有显著区别。以下是两者的对比:
(1)定位与设计目标
对比项 | Feign | Dubbo |
定位 | 声明式HTTP客户端(RESTful调用) | 高性能RPC框架(面向接口的远程调用) |
协议 | 基于HTTP(如REST/JSON) | 默认Dubbo协议(二进制TCP,也支持HTTP/gRPC) |
适用场景 | 微服务间轻量级HTTP通信(如Spring Cloud生态) | 高性能、低延迟的分布式服务调用(如传统RPC场景) |
(2)通信模型
对比项 | Feign | Dubbo |
通信方式 | 同步HTTP请求(通常短连接) | 默认长连接 + NIO(高并发下更高效) |
序列化 | 文本格式(JSON/XML) | 二进制序列化(Hessian2、Protobuf等,性能更高) |
性能 | 较低(HTTP头开销、文本解析) | 更高(二进制协议、长连接复用) |
(3)服务治理
对比项 | Feign | Dubbo |
服务发现 | 依赖外部组件(如Eureka、Nacos) | 内置服务发现(通过注册中心如(Zookeeper/Nacos) |
负载均衡 | 集成Ribbon(客户端LB) | 内置多种策略(随机、轮询、一致性Hash等) |
容错机制 | 需结合Hystrix/Sentinel | 内置容错(失败重试、熔断等) |
监控 | 需额外集成(如Sleuth + Zipkin) | 内置监控接口和SPI扩展 |
(4)生态与集成
对比项 | Feign | Dubbo |
主要生态 | Spring Cloud(与Eureka/Gateway等深度集成) | Apache生态(可独立使用,也支持Spring Cloud) |
开发体验 | 声明式接口(注解驱动,零代码侵入) | 需要定义服务接口和实现(类似传统RPC) |
语言支持 | 主要用于Java(多语言零额外适配) | 支持多语言(通过Triple协议/gRPC) |
(5)典型使用场景
Feign:
- 适合轻量级RESTFUL API调用(如前后端分离、跨团队写作);
- 与Spring Cloud全家桶(如Eureka、OpenFeign)无缝集成;
- 示例:电商系统中订单服务调用支付服务的HTTP接口。
Dubbo:
- 适合高性能、高并发的内部服务调用(如金融、电商核心链路);
- 需要复杂服务治理(如流量控制、分布式事务);
- 计划向云原生迁移(Dubbo 3.x支持应用级服务发现);
- 示例:用户服务查询数据库后通过Dubbo高效返回给网关。
二、分布式系统中的相关概念
1. 大型互连网项目架构目标
- 传统项目和互连网项目
互连网项目特点:
- 用户多
- 流量大,并发高
- 海量数据
- 易受攻击
- 功能繁琐
- 变更快
衡量网站的性能指标:
- 响应时间:指执行一个请求从开始到最后收到响应数据所花费的总体时间;
- 并发数:指系统同时能处理的请求数量;
- 并发连接数:指的是客户端向服务器发起请求,并建立了TCP连接。每秒钟服务器连接的总TCP数量;
- 请求数:也称为QPS(Query Per Second),指每秒多少请求;
- 并发用户数:单位时间内有多少用户;
- 吞吐量:指单位时间内系统能够处理的请求数量;
- QPS:Query Per Second每秒查询数;
- TPS:Transactions Per Second每秒事务数;
- 一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数;
- 一个页面的一次访问,只会形成一个TPS;但一次页面请求,可能产生多次对服务器的请求,就会有多个QPS;
大型互连网项目的目标:
- 高性能:提供快速的访问体验;
- 高可用:网站服务可以一直正常访问;
- 可伸缩:通过硬件增加/减少,提高/降低处理能力;
- 高可扩展:系统间耦合低,方便的通过新增/移除方式,增加/减少新的功能/模块;
- 安全性:提供网站安全访问和数据加密,安全存储等策略;
- 敏捷性:随需应变,快速响应。
2. 集群和分布式
- 集群:很多“人”一起,干一样的事;
- 一个业务模块,部署在多台服务器上。
- 分布式:很多“人”一起,干不一样的事。这些不一样的事,合起来就是一件大事;
- 一个大的业务系统,拆分为小的业务模块,分别部署在不同的机器上。
3. 架构演进
(1)单体架构
优点:
- 简单:开发部署都很方便,小型项目首选;
缺点:
- 项目启动慢
- 可靠性差
- 可伸缩性差
- 扩展性和可维护性差
- 性能低
(2)垂直架构
垂直架构是指将单体架构中的多个模块拆分为多个独立的项目。形成多个独立的单体架构。
垂直架构存在的问题:
- 重复功能太多(如用户信息的获取)
(3)分布式架构
分布式架构是指在垂直架构的基础上,将公共业务模块抽取出来,作为独立的服务,供其它调用者消费,以实现服务的共享和重用。
RPC:Remote Procedure Call远程过程调用。有非常多的协议和技术都实现了RPC的过程。比如:HTTP REST风格、Java RMI规范、WebService SOAP协议、Hession等等。
分布式架构存在的问题:
- 服务提供方一旦产生变更,所有消费者都需要变更
(4)SOA架构
SOA:(Service-Oriented Architecture,面向服务的架构)是一个组件模型,它将应用程序的不同功能单元(称为服务)进行拆分,并通过这些服务之间定义良好的接口和契约联系起来。
ESB:(Enterparise Servce Bus)企业服务总线,服务中介。主要是提供了一个服务于服务之间的交互。ESB包含的功能如:负载均衡、流量控制、加密处理、服务的监控、异常处理、监控告急等等。
(5)微服务架构
微服务架构是在SOA上做的升华,微服务架构强调的一个重点是“业务需要彻底的组件化和服务化”,原有的单个业务系统会拆分为多个可以独立开发、设计、运行的小应用。这些小应用之间通过服务完成交互和集成。
微服务架构 = 80%的SOA服务架构思想 + 100%的组件化架构思想 + 80%的领域建模思想
特点:
- 服务实现组件化:开发者可以自由选择开发技术。也不需要协调其它团队
- 服务之间交互一般使用REST API
- 去中心化:每个微服务都有自己私有的数据库持久化业务数据
- 自动化部署:把应用拆分为一个一个独立的单个服务,方便自动化部署、测试、运维
SOA架构 vs 微服务架构
对比维度 | SOA(面向服务架构) | 微服务架构 |
核心目标 | 服务复用(通过ESB集成企业级服务) | 独立部署与扩展(小型、自治服务) |
服务粒度 | 较粗(服务可能包含多个业务功能) | 较细(单一职责,一个服务对应一个功能) |
通信方式 | 依赖ESB(企业服务总线),中心化通信 | 轻量级协议(HTTP/REST、gRPC等) |
数据管理 | 共享数据库(或通过ESB协调) | 独立数据库(每个服务有自己的存储) |
技术栈 | 强标准化(如SOAP/WS-*协议) | 灵活(服务可选用不同技术) |
部署与扩展 | 整体部署或模块化部署(扩展成本高) | 独立部署(按需扩展单个服务) |
典型应用场景 | 企业级系统整合(如ERP、银行核心系统) | 互连网应用、云原生架构(如电商、社交) |
三、Dubbo概述
Dubbo是阿里巴巴公司开源的高性能、轻量级的Java RPC框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。
官网:Apache Dubbo
Dubbo 架构
- Provider:暴露服务的服务提供方
- Container:服务运行容器
- Consumer:调用远程服务的服务消费方
- Registry:服务注册与发现的注册中心
- Monitor:统计服务的调用次数和调用时间的监控中心
四、Dubbo快速入门
注册中心:使用 Zookeeper 作为注册中心实现自动服务发现 | Apache Dubbo
1. Zookeeper安装
步骤①:把资料中的apache-zookeeper-3.5.6-bin.tar.gz上传到虚拟机的/opt/zookeeper目录下:
使用的是《黑马头条》课程提供的虚拟机。
②把tar包解压到/opt/zookeeper目录下:
cd /opt/zookeeper
tar -zxvf apache-zookeeper-3.5.6-bin.tar.gz
③配置zoo.cfg:
# 进入conf目录
cd /opt/zookeeper/apache-zookeeper-3.5.6-bin/conf/
# 拷贝文件
cp zoo_sample.cfg zoo.cfg
cd /opt/zookeeper
# 创建zookeeper存储目录
mkdir zkdata
④修改zoo.cfg:
修改存储目录为:/opt/zookeeper/zkdata
⑤启动zookeeper:
cd /opt/zookeeper/apache-zookeeper-3.5.6-bin/bin/
# 启动zookeeper
./zkServer.sh start
⑥查看zookeeper状态:
./zkServer.sh status
Mode为standalone代表zk没有搭建集群,现在是单节点。
2. 快速入门
实现步骤:
- 创建服务提供者Provider模块;
- 创建服务消费者Consumer模块;
- 在服务提供者模块编写UserServiceImpl提供服务;
- 在服务消费者中的UserController远程调用UserServiceImpl提供的服务;
- 分别启动两个服务,进行测试
步骤①:创建一个空项目dubbo-pro:
JDK选择1.8:
设置Maven信息:
②创建模块dubbo-service和dubbo-web:
③导入相关依赖:
pom.xml(dubbo-service)
<?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.heima</groupId><artifactId>dubbo-service</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring.version>5.1.9.RELEASE</spring.version><dubbo.version>2.7.4.1</dubbo.version><zookeeper.version>4.0.0</zookeeper.version></properties><dependencies><!-- servlet3.0规范的坐标 --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><!--spring的坐标--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><!--springmvc的坐标--><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><!--日志--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.21</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.21</version></dependency><!--Dubbo的起步依赖,版本2.7之后统一为rg.apache.dubb --><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo</artifactId><version>${dubbo.version}</version></dependency><!--ZooKeeper客户端实现 --><dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>${zookeeper.version}</version></dependency><!--ZooKeeper客户端实现 --><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>${zookeeper.version}</version></dependency></dependencies>
</project>
pom.xml(dubbo-web):
<?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.heima</groupId><artifactId>dubbo-web</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring.version>5.1.9.RELEASE</spring.version><dubbo.version>2.7.4.1</dubbo.version><zookeeper.version>4.0.0</zookeeper.version></properties><dependencies><!-- servlet3.0规范的坐标 --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><!--spring的坐标--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><!--springmvc的坐标--><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><!--日志--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.21</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.21</version></dependency><!--Dubbo的起步依赖,版本2.7之后统一为rg.apache.dubb --><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo</artifactId><version>${dubbo.version}</version></dependency><!--ZooKeeper客户端实现 --><dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>${zookeeper.version}</version></dependency><!--ZooKeeper客户端实现 --><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>${zookeeper.version}</version></dependency></dependencies><build><plugins><!--tomcat插件--><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.1</version><configuration><port>8000</port><path>/</path></configuration></plugin></plugins></build></project>
⑤创建接口UserService和实现类UserServiceImpl:
package com.heima.service;public interface UserService {public String sayHello();
}
package com.heima.service.impl;import com.heima.service.UserService;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl implements UserService {@Overridepublic String sayHello() {return "Hello, Dubbo!";}
}
⑥从资料中拷贝以下文件到dubbo-service的resource目录下:
修改applicationContext.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://dubbo.apache.org/schema/dubbo" xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.heima.service" /></beans>
<context:component-scan base-package="com.heima.service" />:
- Spring会扫描com.heima.service包及其子包下的所有类;
- 识别带有Spring注解的类,并将其注册为Spring容器管理的Bean
⑦在dubbo-web新建目录如下,在WEB-INF添加web.xml文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"version="2.5"><!-- spring --><context-param><param-name>contextConfigLocation</param-name><param-value>classpath*:spring/applicationContext*.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- Springmvc --> <servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- 指定加载的配置文件 ,通过参数contextConfigLocation加载--><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/springmvc.xml</param-value></init-param></servlet><servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>*.do</url-pattern></servlet-mapping></web-app>
⑧在pom.xml(dubbo-web)添加对dubbo-service的依赖:
<dependency><groupId>com.heima</groupId><artifactId>dubbo-service</artifactId><version>1.0-SNAPSHOT</version></dependency>
⑨从资料中复制如下文件到resource目录下:
springmvc.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://dubbo.apache.org/schema/dubbo"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><mvc:annotation-driven /><context:component-scan base-package="com.heima.controller" />
</beans>
⑩新增UserController:
package com.heima.controller;import com.heima.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/user")
public class UserController {// 注入service@Autowiredprivate UserService userService;@RequestMapping("/sayHello")public String sayHello() {return userService.sayHello();}
}
(11)安装dubbo-service:
(12)双击tomcat7:run,运行dubbo-web:
访问:http://localhost:8000/user/sayHello.do
改造:
①修改dubbo-service的打包方式为war,添加一个tomcat的插件:
<?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.heima</groupId><artifactId>dubbo-service</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring.version>5.1.9.RELEASE</spring.version><dubbo.version>2.7.4.1</dubbo.version><zookeeper.version>4.0.0</zookeeper.version></properties><dependencies><!-- servlet3.0规范的坐标 --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><!--spring的坐标--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><!--springmvc的坐标--><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><!--日志--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.21</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.21</version></dependency><!--Dubbo的起步依赖,版本2.7之后统一为rg.apache.dubb --><dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo</artifactId><version>${dubbo.version}</version></dependency><!--ZooKeeper客户端实现 --><dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>${zookeeper.version}</version></dependency><!--ZooKeeper客户端实现 --><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>${zookeeper.version}</version></dependency></dependencies><build><plugins><!--tomcat插件--><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.1</version><configuration><port>9000</port><path>/</path></configuration></plugin></plugins></build>
</project>
②更改UserServiceImpl中@Service注解的包:
package com.heima.service.impl;import com.heima.service.UserService;
import org.apache.dubbo.config.annotation.Service;@Service // 将这个类提供的方法(服务)对外发布。将访问的地址 ip,端口,路径注册到注册中心
public class UserServiceImpl implements UserService {@Overridepublic String sayHello() {return "Hello, Dubbo!";}
}
③修改dubbo-service的applicationContext.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://dubbo.apache.org/schema/dubbo" xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><!-- <context:component-scan base-package="com.heima.service" />--><!--dubbo的配置--><!--1. 配置项目的名称,唯一--><dubbo:application name="dubbo-service" /><!--2. 配置注册中心的地址--><dubbo:registry address="zookeeper://192.168.200.130:2181" /><!--3. 配置dubbo包扫描--><dubbo:annotation package="com.heima.service.impl" />
</beans>
④把dubbo-web的webapp文件夹拷贝到dubbo-service,删除web.xml中关于springmvc的配置:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"version="2.5"><!-- spring --><context-param><param-name>contextConfigLocation</param-name><param-value>classpath*:spring/applicationContext*.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>
</web-app>
⑤启动虚拟机中的zookeeper,双击tomcat7:run启动dubbo-service
注意:如果之前有用docker安装zookeeper,记得先停掉
⑥注释掉pom.xml(dubbo-web)对dubbo-service的依赖:
⑦在dubbo-web创建UserService接口:
package com.heima.service;public interface UserService {public String sayHello();
}
⑧删除dubbo-web中web.xml中spring的加载配置:
⑨更改UserController:
package com.heima.controller;import com.heima.service.UserService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/user")
public class UserController {// 注入service(本地注入)// @Autowired/*** 1. 从zookeeper注册中心获取userService的访问url* 2. 进行远程调用RPC* 3. 将结果封装为一个代理对象,给变量赋值*/@Reference // 远程注入private UserService userService;@RequestMapping("/sayHello")public String sayHello() {return userService.sayHello();}
}
⑩在springmvc.xml添加dubbo的配置:
<!--dubbo的配置--><!--1. 配置项目的名称,唯一--><dubbo:application name="dubbo-web"><dubbo:parameter key="qos.port" value="33333" /></dubbo:application><!--2. 配置注册中心的地址--><dubbo:registry address="zookeeper://192.168.200.130:2181" /><!--3. 配置dubbo包扫描--><dubbo:annotation package="com.heima.controller" />
(11)双击运行dubbo-web,访问http://localhost:8000/user/sayHello.do
(12)改进反向:把UserService提取出来
新建一个module:dubbo-interface
新建com.heima.service包,把UserService接口粘贴到dubbo-interface:
package com.heima.service;public interface UserService {public String sayHello();
}
删除dubbo-service和dubbo-web中的UserService接口,然后在pom文件中添加依赖:
<dependency><groupId>com.heima</groupId><artifactId>dubbo-interface</artifactId><version>1.0-SNAPSHOT</version></dependency>
(13)先install dubbo-interface,然后重启dubbo-service和dubbo-web测试:
五、Dubbo高级特性
1. dubbo-admin管理平台
- dubbo-admin管理平台,是图形化的服务管理页面;
- 从注册中心中获取到所有的提供者/消费者进行配置管理;
- 路由配置、动态配置、服务降级、访问控制、权重调整、负载均衡等管理功能;
- dubbo-admin是一个前后端分离的项目,前端使用vue,后端使用springboot;
- 安装dubbo-admin,其实就是部署该项目
(1)安装dubbo-admin
前提:安装 maven、jdk8、Node.js
步骤①:解压资料中的dubbo-admin-develop.zip,找到dubbo-admin-server下的 application.properties 配置文件,修改zookeeper地址:
-
admin.registry.address:注册中心 admin.config-center:配置中心 admin.metadata-report.address:元数据中心
②在dubbo-admin-develop目录执行打包命令:
mvn clean package -Dmaven.test.skip=true
注意:使用JDK 1.8运行项目
③启动dubbo-admin-distribution:(不要关闭窗口)
java -jar ./dubbo-admin-0.1.jar
④启动前端工程:
npm run dev
⑤访问:http://localhost:8081/#/,用户名和密码都是root
(2)使用dubbo-admin
步骤①:修改dubbo-service的applicationContext.xml,加入元数据的配置:
<!--1. 配置项目的名称,唯一--><dubbo:application name="dubbo-service" /><!--2. 配置注册中心的地址--><dubbo:registry address="zookeeper://192.168.200.130:2181" /><!--3. 配置dubbo包扫描--><dubbo:annotation package="com.heima.service.impl" /><!--4. 元数据配置--><dubbo:metadata-report address="zookeeper://192.168.200.130:2181" />
②先启动之前的dubbo-service和dubbo-web,点击服务查询进行查看:
- 点击“详情”,查看详情信息:
可以修改端口:
- 访问http://localhost:8000/user/sayHello.do后,即可查看消费者:
- 点击“测试”,测试方法:
2. dubbo 常用高级配置
2.1 序列化
问题1:两个机器传输数据,如何传输Java对象?
- dubbo内部已经序列化和反序列化的过程内部封装了;
- 我们只需在定义pojo类时实现Serializable接口即可;
- 一般会定义一个公共的pojo模块,让生产者和消费者都依赖该模块。
步骤①:新增dubbo-pojo模块:
②新建User类:
package com.heima.pojo;public class User {private Integer id;private String username;private String password;public User() {}public User(Integer id, String username, String password) {this.id = id;this.username = username;this.password = password;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}
}
③pom.xml(dubbo-interface)新增对dubbo-pojo的依赖:
<dependencies><dependency><groupId>com.heima</groupId><artifactId>dubbo-pojo</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies>
④UserService新增findUserById方法:
public User findUserById(Integer id);
⑤UserServiceImpl实现findUserById方法:
@Overridepublic User findUserById(Integer id) {return new User(id, "zhangsan", "123");}
⑥UserController新增接口:
/*** 根据id查询用户信息* @param id* @return*/@RequestMapping("/find")public User find(int id) {return userService.findUserById(id);}
⑦先在maven中install dubbo-pojo,然后install dubbo-interface,再启动dobbo-service和dubbo-web,访问:http://localhost:8000/user/find.do?id=2
⑧在User类implements java.io.Serializable接口:
⑨然后重复步骤⑦:
2.2 地址缓存
问题:注册中心挂了,服务是否可以正常访问?
- 可以,因为dubbo服务消费者在第一次调用时,会将服务提供方地址缓存在本地,以后再调用则不会访问注册中心;
- 当服务提供者地址发生变化时,注册中心会通知服务消费者。
2.3 超时与重试
- 服务消费者在调用服务提供者的时候发生了阻塞、等待等情形,这个时候,服务消费者就会一直等待下去;
- 在某个峰值时刻,大量的请求都在同时请求服务消费者,会造成线程的大量堆积,势必会造成雪崩;
- dubbo利用超时机制来解决这个问题,设置一个超时时间,在这个时间段内,无法完成服务访问,则自动断开连接;
- 使用timeout属性配置超时时间,默认值1000,单位毫秒;
- 如果出现网络抖动,则这一次请求就会失败;
- dubbo提供重试机制来避免类似问题的发生;
- 通过retries属性来设置重试次数,默认为2次
示例代码:
①UserServiceImpl:
package com.heima.service.impl;import com.heima.pojo.User;
import com.heima.service.UserService;
import org.apache.dubbo.config.annotation.Service;// 将这个类提供的方法(服务)对外发布。将访问的地址 ip,端口,路径注册到注册中心
@Service(timeout = 3000, retries = 0) // 超时时间3秒,不重试
public class UserServiceImpl implements UserService {@Overridepublic String sayHello() {return "Hello, Dubbo!";}@Overridepublic User findUserById(Integer id) {try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}return new User(id, "zhangsan", "123");}
}
②UserController:
package com.heima.controller;import com.heima.pojo.User;
import com.heima.service.UserService;
import org.apache.dubbo.config.annotation.Reference;
//import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/user")
public class UserController {// 注入service(本地注入)// @Autowired/*** 1. 从zookeeper注册中心获取userService的访问url* 2. 进行远程调用RPC* 3. 将结果封装为一个代理对象,给变量赋值*/@Reference // 远程注入private UserService userService;@RequestMapping("/sayHello")public String sayHello() {return userService.sayHello();}int i = 1;/*** 根据id查询用户信息* @param id* @return*/@RequestMapping("/find")public User find(int id) {new Thread(new Runnable() {@Overridepublic void run() {while (true) {System.out.println(i++);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}}).start();return userService.findUserById(id);}
}
③启动dubbo-service和dubbo-web,访问http://localhost:8000/user/find.do?id=2,查看控制台日志:
④在UserController的UserService注入时设置timeout为1秒:
重启dubbo-service和dubbo-web进行测试(1秒超时)
注意:建议在服务提供者设置超时时间
⑤修改重试次数,重启dubbo-service和dubbo-web进行测试
2.4 多版本
- 灰度发布:当出现新功能时,会让一部分用户先使用新功能,用户反馈没问题时,再将所有用户迁移到新功能;
- dubbo中使用version属性来设置和调用同一个接口的不同版本。
步骤①:复制一份UserServiceImpl:
②UserController选择调用版本为v1.0:
③重启dubbo-service和dubbo-web进行测试:http://localhost:8000/user/find.do?id=2
④修改为v2.0进行测试:
2.5 负载均衡
负载均衡策略:
- Random:按权重随机,默认值。按权重设置随机概率;
- RoundRobin:按权重轮询;
- LeastActive:最少活跃调用数,相同活跃数的随机;
- ConsistentHash:一致性Hash,相同参数的请求总是发到同一提供者
示例:
步骤①:启动dubbo-service:
②修改端口信息:
- 修改tomcat端口:
- 修改dubbo配置:applicationContext.xml
- 启动另外一个dubbo-service(不是重启)
- 在dubbo-admin即可查看到两个服务
③重复步骤②,启动第三个实例:
④在UserController配置负载均衡策略为random,然后启动dubbo-web,访问 http://localhost:8000/user/sayHello.do 进行测试(第一次访问在3号实例上)
2.6 集群容错
集群容错模式:
- Failover Cluster:失败重试。默认值。当出现失败,重试其它服务器,默认重试2次,使用retries配置。一般用于读操作;
- Failfast Cluster:快速失败,只发起一次调用,失败立即报错。通常用于写操作;
- Failsafe Cluster:失败安全,出现异常时,直接忽略。返回一个空结果;
- Failback Cluster:失败自动恢复,后台记录失败请求,定时重发;
- Forking Cluster:并行调用多个服务器,只要一个成功即返回;
- Broadcast Cluter:广播调用所有提供者,逐个调用,任意一台报错则报错。
2.7 服务降级
服务降级方式:
- mock=force:return null -> 表示消费方对该服务的方法调用直接返回null值,不发起远程调用。用来频闭不重要服务不可用时对调用方的影响;
- mock=fail:return null -> 表示消费方对该服务的方法调用在失败后,再返回null值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。