Dubbo 2.7 快速入门实战指南
学习目标
学完本章后,你能够:
- 独立搭建第一个Dubbo直连式调用项目(Provider + Consumer)
- 配置ZooKeeper注册中心并实现服务的自动注册与发现
- 将Dubbo服务集成到Spring MVC Web工程中
- 部署和使用Dubbo Admin管理控制台进行服务治理
- 理解Main类启动与Spring容器启动的区别及适用场景
1. 第一个Dubbo应用------直连模式
直连模式(Point-to-Point)是学习Dubbo最简方式:Consumer通过硬编码的URL直接连接Provider,不依赖任何注册中心。虽然生产环境不会这样使用,但它是理解Dubbo工作原理的最佳起点。
1.1 项目结构与模块划分
bash
dubbo-quickstart/
├── dubbo-api/ # 公共接口模块
│ ├── pom.xml
│ └── src/main/java/
│ └── com/example/dubbo/api/
│ └── GreetingService.java
├── dubbo-provider/ # 服务提供者模块
│ ├── pom.xml
│ └── src/main/
│ ├── java/com/example/dubbo/provider/
│ │ ├── GreetingServiceImpl.java
│ │ └── ProviderApplication.java
│ └── resources/
│ └── spring-provider.xml
└── dubbo-consumer/ # 服务消费者模块
├── pom.xml
└── src/main/
├── java/com/example/dubbo/consumer/
│ └── ConsumerApplication.java
└── resources/
└── spring-consumer.xml
1.2 公共API模块
java
package com.example.dubbo.api;
/**
* 远程服务接口定义
*
* 设计原则:
* 1. 接口定义在独立的模块中,Provider和Consumer共同依赖
* 2. 接口即契约------只要接口不变,双方可以独立演化
* 3. 方法参数和返回值必须实现Serializable接口(跨JVM传输需要序列化)
*/
public interface GreetingService {
/**
* 发送问候消息
* @param name 用户名
* @return 问候语
*/
String sayHello(String name);
/**
* 获取服务版本信息
* @return 版本标识
*/
String getVersion();
}
xml
<!-- dubbo-api/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.example.dubbo</groupId>
<artifactId>dubbo-api</artifactId>
<version>1.0.0</version>
<packaging>jar</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>
</properties>
</project>
1.3 服务提供者实现
java
package com.example.dubbo.provider;
import com.example.dubbo.api.GreetingService;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* 远程服务接口的具体实现
*
* 注意:这是一个普通的Java类,不需要任何Dubbo特有的注解或继承
* 所有Dubbo相关的配置都在XML配置文件中完成
*/
public class GreetingServiceImpl implements GreetingService {
/** 当前提供者节点的标识 */
private final String nodeId;
public GreetingServiceImpl(String nodeId) {
this.nodeId = nodeId;
}
@Override
public String sayHello(String name) {
String timestamp = LocalDateTime.now()
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
// 在控制台打印日志,便于观察调用情况
System.out.printf("[%s] 节点 %s 收到请求,参数 name=%s%n",
timestamp, nodeId, name);
// 模拟业务处理耗时
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return String.format("你好 %s!由节点[%s]于 %s 响应",
name, nodeId, timestamp);
}
@Override
public String getVersion() {
return "Dubbo 2.7.0 Provider - Node " + nodeId;
}
}
Spring配置文件------服务暴露核心配置:
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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- ========== 1. 应用标识 ========== -->
<!-- 每个Dubbo应用必须有唯一的名称,用于在注册中心中标识自己 -->
<dubbo:application name="dubbo-quickstart-provider"/>
<!-- ========== 2. 注册中心配置(直连模式设置为N/A) ========== -->
<!-- N/A 表示不使用任何注册中心,完全依靠URL直连 -->
<dubbo:registry address="N/A"/>
<!-- ========== 3. 服务协议与端口 ========== -->
<!-- 指定使用dubbo协议,监听20880端口 -->
<dubbo:protocol name="dubbo" port="20880"/>
<!-- ========== 4. 服务实现Bean ========== -->
<!-- 这是普通的Spring Bean,由Spring容器管理其生命周期 -->
<bean id="greetingService" class="com.example.dubbo.provider.GreetingServiceImpl">
<constructor-arg value="Node-01"/>
</bean>
<!-- ========== 5. 服务暴露(最关键的配置) ========== -->
<!-- interface: 暴露的服务接口全限定名 -->
<!-- ref: 引用的Spring Bean,即服务实现类 -->
<dubbo:service interface="com.example.dubbo.api.GreetingService"
ref="greetingService"/>
</beans>
Provider启动类:
java
package com.example.dubbo.provider;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
/**
* 服务提供者入口------基于Spring容器启动
*
* 执行流程:
* 1. 加载Spring配置文件,初始化IoC容器
* 2. 创建GreetingServiceImpl实例
* 3. Dubbo检测到<dubbo:service>标签,自动暴露服务
* 4. 开启Netty端口监听(20880),等待消费者连接
*/
public class ProviderApplication {
public static void main(String[] args) throws IOException {
System.out.println("========== Dubbo Provider 启动中 ==========");
// 1. 创建Spring容器并加载Dubbo配置
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("spring-provider.xml");
// 2. 启动Spring容器(触发Dubbo服务暴露)
context.start();
System.out.println("========== Dubbo Provider 启动完成 ==========");
System.out.println("服务已暴露在: dubbo://localhost:20880");
System.out.println("按任意键停止服务...");
// 3. 阻塞主线程,保持服务持续运行
System.in.read();
// 4. 优雅关闭
context.close();
System.out.println("========== Dubbo Provider 已停止 ==========");
}
}
1.4 服务消费者实现
Spring配置文件:
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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 应用标识 -->
<dubbo:application name="dubbo-quickstart-consumer"/>
<!-- 不使用注册中心 -->
<dubbo:registry address="N/A"/>
<!-- ========== 服务引用------直连模式的核心 ========== -->
<!-- id: 在Spring容器中的Bean名称,通过它获取代理对象 -->
<!-- interface: 要调用的远程服务接口 -->
<!-- url: 直连地址,格式为 dubbo://主机:端口 -->
<dubbo:reference id="greetingService"
interface="com.example.dubbo.api.GreetingService"
url="dubbo://localhost:20880"/>
</beans>
Consumer启动类:
java
package com.example.dubbo.consumer;
import com.example.dubbo.api.GreetingService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 服务消费者入口
*
* 执行流程:
* 1. 加载Spring配置,初始化IoC容器
* 2. Dubbo根据<dubbo:reference>配置创建远程代理对象
* 3. 从Spring容器获取代理Bean
* 4. 调用代理方法时,Dubbo自动完成网络通信、序列化等底层操作
*/
public class ConsumerApplication {
public static void main(String[] args) {
// 1. 初始化Spring容器
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-consumer.xml");
// 2. 获取远程服务代理对象
// 注意:这里获取到的是Dubbo生成的动态代理,而非真正的实现类
GreetingService service = (GreetingService) context.getBean("greetingService");
// 3. 发起远程调用
// 对开发者来说,完全透明------就像调用本地方法一样
System.out.println("===== 发起第一次远程调用 =====");
String result1 = service.sayHello("张三");
System.out.println("响应结果: " + result1);
System.out.println("\n===== 发起第二次远程调用 =====");
String result2 = service.sayHello("李四");
System.out.println("响应结果: " + result2);
System.out.println("\n===== 获取服务版本 =====");
String version = service.getVersion();
System.out.println("版本信息: " + version);
// 4. 应用退出
((ClassPathXmlApplicationContext) context).close();
}
}
1.5 Dubbo Main类启动方式
除了手动创建Spring容器,Dubbo还提供了更轻量的Main类启动方式:
java
package com.example.dubbo.provider;
import org.apache.dubbo.container.Main;
/**
* 使用Dubbo Main类启动------更简洁的方式
*
* 要求:
* 1. Spring配置文件必须放在 classpath:META-INF/spring/ 目录下
* 2. 文件名随意,建议使用 spring-*.xml 模式
* 3. 无需手动创建Spring容器,Main类自动加载
*
* 适用场景:
* - 纯Java应用(非Web环境)的服务提供者
* - 测试和演示项目
* - 不需要完整Spring容器功能的轻量级部署
*/
public class ProviderMainApplication {
public static void main(String[] args) {
// 一行代码启动Dubbo服务
// Main内部会自动:
// 1. 扫描 META-INF/spring/ 下的所有Spring配置文件
// 2. 初始化Spring容器
// 3. 暴露所有<dubbo:service>标签定义的服务
// 4. 注册JVM关闭钩子,确保优雅停机
Main.main(args);
}
}
java
/**
* Dubbo Main类启动原理简析
* 帮助理解Main类的内部工作机制
*/
public class DubboMainPrinciple {
/**
* Dubbo Main类的核心逻辑简化版
* 展示其如何自动发现并加载Spring容器
*/
public static class SimplifiedMain {
private static final String SPRING_CONFIG_LOCATION =
"META-INF/spring/";
private final List<SpringContainer> containers = new ArrayList<>();
public void start() {
// 1. 扫描META-INF/spring/目录下所有xml文件
List<String> configFiles = scanSpringConfigs(SPRING_CONFIG_LOCATION);
// 2. 为每个配置文件创建Spring容器
for (String configFile : configFiles) {
SpringContainer container = new SpringContainer(configFile);
container.start();
containers.add(container);
}
// 3. 注册关闭钩子
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
for (SpringContainer container : containers) {
container.stop();
}
}));
}
private List<String> scanSpringConfigs(String location) {
// 实际实现使用类路径扫描,此处简化
return Collections.singletonList(
"META-INF/spring/spring-provider.xml");
}
}
static class SpringContainer {
private final ClassPathXmlApplicationContext context;
SpringContainer(String configLocation) {
this.context = new ClassPathXmlApplicationContext(configLocation);
}
void start() { context.start(); }
void stop() { context.close(); }
}
}
2. ZooKeeper注册中心集成
直连模式虽然简单,但生产环境必须使用注册中心。ZooKeeper是Dubbo最常用的注册中心。
2.1 ZooKeeper注册中心架构
bash
┌─────────────────────────────────────────────────────────┐
│ ZooKeeper 注册中心 │
│ │
│ /dubbo │
│ ├── /com.example.dubbo.api.GreetingService │
│ │ ├── /providers │
│ │ │ ├── dubbo://192.168.1.10:20880/... [临时节点] │
│ │ │ ├── dubbo://192.168.1.11:20880/... [临时节点] │
│ │ │ └── dubbo://192.168.1.12:20880/... [临时节点] │
│ │ ├── /consumers │
│ │ │ └── consumer://192.168.1.20/... [临时节点] │
│ │ ├── /routers │
│ │ │ └── ... [持久节点] │
│ │ └── /configurators │
│ │ └── ... [持久节点] │
│ └── /com.example.dubbo.api.OrderService │
│ └── ... │
└─────────────────────────────────────────────────────────┘
2.2 Provider配置改造
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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<dubbo:application name="greeting-provider"/>
<!-- ========== ZooKeeper注册中心配置 ========== -->
<!-- 方式一:最简配置(单机ZK) -->
<!-- <dubbo:registry address="zookeeper://127.0.0.1:2181"/> -->
<!-- 方式二:完整协议+地址写法(推荐,语义更清晰) -->
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"/>
<!-- 方式三:ZK集群配置(生产环境推荐) -->
<!-- <dubbo:registry address="zookeeper://10.0.0.1:2181?backup=10.0.0.2:2181,10.0.0.3:2181"/> -->
<!-- 方式四:集群配置的另一种写法 -->
<!-- <dubbo:registry protocol="zookeeper" address="10.0.0.1:2181,10.0.0.2:2181,10.0.0.3:2181"/> -->
<dubbo:protocol name="dubbo" port="20880"/>
<bean id="greetingService"
class="com.example.dubbo.provider.GreetingServiceImpl">
<constructor-arg value="ZK-Node-01"/>
</bean>
<!-- 注意:不再需要url属性,地址由注册中心自动管理 -->
<dubbo:service interface="com.example.dubbo.api.GreetingService"
ref="greetingService"/>
</beans>
2.3 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://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<dubbo:application name="greeting-consumer"/>
<!-- 与Provider使用同一个注册中心 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- ========== 关键变化 ========== -->
<!-- 不再指定url属性,Dubbo会自动从注册中心发现Provider地址 -->
<dubbo:reference id="greetingService"
interface="com.example.dubbo.api.GreetingService"/>
</beans>
2.4 日志配置与端口冲突解决
properties
# log4j.properties ------ 放置于 src/main/resources
# 通过日志可以观察到Dubbo的内部运行细节
# 控制台输出配置
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%d{HH:mm:ss}] %-5p %c{1}:%L - %m%n
# 根日志级别:info可以看到关键信息,debug可以看到详细调用链
log4j.rootLogger=info,console
# Dubbo核心日志(调试时建议debug级别)
log4j.logger.org.apache.dubbo=info
properties
# dubbo.properties ------ 放置于 src/main/resources
# 解决同一台机器上多个Dubbo应用的端口冲突
# QOS(Quality of Service)端口
# 当Provider和Consumer在同一主机时,需为Consumer设置不同的QOS端口
dubbo.application.qos.port=33333
java
/**
* QOS端口冲突解决方案汇总
*/
public class QosPortResolution {
/**
* 方案一:dubbo.properties文件(推荐)
* 在classpath下创建dubbo.properties,内容:
* dubbo.application.qos.port=33333
*/
/**
* 方案二:Spring XML配置
* <dubbo:application name="my-app">
* <dubbo:parameter key="qos.port" value="33333"/>
* </dubbo:application>
*/
/**
* 方案三:JVM启动参数
* -Ddubbo.application.qos.port=33333
*/
/**
* 方案四:完全禁用QOS(不推荐,会失去Telnet调试能力)
* -Ddubbo.application.qos.enable=false
*/
}
3. Web工程集成Dubbo
3.1 Provider Web工程
xml
<!-- 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_3_1.xsd"
version="3.1">
<display-name>Dubbo Provider Web</display-name>
<!-- ========== 关键配置:指定Spring配置文件路径 ========== -->
<!-- 通配符 spring-*.xml 可以加载所有匹配的配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-*.xml</param-value>
</context-param>
<!-- ========== Spring根容器监听器 ========== -->
<!-- ContextLoaderListener 会创建Spring的根WebApplicationContext -->
<!-- Dubbo的服务暴露正是发生在这个根容器初始化过程中 -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
</web-app>
3.2 Consumer Web工程
java
package com.example.dubbo.web.controller;
import com.example.dubbo.api.GreetingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
/**
* Spring MVC控制器------调用远程Dubbo服务
*
* 关键点:
* 1. 使用@Autowired注入远程Dubbo服务代理(就像注入本地Bean一样)
* 2. Controller不需要感知底层是Dubbo调用还是本地调用
* 3. 这就是透明化远程调用的价值所在
*/
@Controller
@RequestMapping("/greeting")
public class GreetingController {
/**
* 注入远程Dubbo服务代理
* 这个Bean由<dubbo:reference>标签在Spring容器中创建
*/
@Autowired
private GreetingService greetingService;
/**
* GET /greeting/say?name=xxx
* 前端发起请求 → Controller → Dubbo RPC → Provider → 返回结果
*/
@GetMapping("/say")
@ResponseBody
public Map<String, Object> sayHello(@RequestParam String name) {
long startTime = System.currentTimeMillis();
// 调用远程服务------对Controller完全透明
String result = greetingService.sayHello(name);
long elapsed = System.currentTimeMillis() - startTime;
Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("data", result);
response.put("elapsedMs", elapsed);
return response;
}
/**
* GET /greeting/version
* 获取远端服务的版本信息
*/
@GetMapping("/version")
@ResponseBody
public Map<String, Object> getVersion() {
String version = greetingService.getVersion();
Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("version", version);
return response;
}
}
xml
<!-- spring-consumer.xml ------ 整合Spring MVC + Dubbo -->
<?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"
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://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- Dubbo消费者配置 -->
<dubbo:application name="greeting-consumer-web"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:reference id="greetingService"
interface="com.example.dubbo.api.GreetingService"/>
<!-- Spring MVC配置 -->
<mvc:annotation-driven/>
<context:component-scan base-package="com.example.dubbo.web.controller"/>
</beans>
xml
<!-- web.xml ------ 消费者Web工程配置 -->
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
version="3.1">
<display-name>Dubbo Consumer Web</display-name>
<!-- 字符编码过滤器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Spring MVC中央调度器 -->
<!-- 注意:DispatcherServlet创建的是子容器,Dubbo的Bean在根容器中 -->
<!-- 通过contextConfigLocation可以让DispatcherServlet也加载Dubbo配置 -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
3.3 Root容器与Servlet容器的关系
java
/**
* Spring容器层级关系详解
*
* 在Web环境中,Spring存在两层容器:
* 1. Root WebApplicationContext(父容器)
* - 由 ContextLoaderListener 创建
* - 通常管理Service、DAO、Dubbo等业务Bean
*
* 2. Servlet WebApplicationContext(子容器)
* - 由 DispatcherServlet 创建
* - 通常管理Controller、ViewResolver等Web Bean
*
* 子容器可以访问父容器的Bean,反之则不行
*/
public class SpringContextHierarchy {
/**
* 容器层级关系示意:
*
* Root WebApplicationContext (父)
* ├── greetingService (Dubbo代理)
* ├── dataSource
* └── transactionManager
* │
* │ 子容器可以访问父容器的Bean
* ▼
* Servlet WebApplicationContext (子)
* ├── greetingController (@Autowired greetingService ✓)
* ├── viewResolver
* └── handlerMapping
*/
/**
* 重要结论:
* 如果Dubbo引用配置在DispatcherServlet的配置文件中(子容器),
* 那么Controller可以正常注入。
*
* 如果Dubbo引用配置在ContextLoaderListener的配置文件中(父容器),
* Controller同样可以注入(因为子容器能访问父容器Bean)。
*
* 推荐做法:将Dubbo相关配置放在根容器中,Web配置放在子容器中。
*/
}
4. Dubbo Admin管理控制台
4.1 部署与配置
Dubbo Admin是官方提供的Web管理界面,用于服务治理、路由规则配置、权重调整等操作。
yaml
# application.properties ------ Dubbo Admin配置
# 位于 dubbo-admin-server/src/main/resources/
# 服务端口
server.port=8080
# ========== 注册中心配置 ==========
# Dubbo 2.7版本专用配置方式
dubbo.registry.address=zookeeper://127.0.0.1:2181
# ========== 配置中心(可与注册中心共用ZK) ==========
dubbo.config-center.address=zookeeper://127.0.0.1:2181
# ========== 元数据中心 ==========
dubbo.metadata-report.address=zookeeper://127.0.0.1:2181
# ========== 管理员账号 ==========
# 默认账号密码均为 root
dubbo.admin.root.password=root
dubbo.admin.guest.password=guest
4.2 核心功能导航
javascript
Dubbo Admin 功能菜单
├── 服务查询
│ ├── 按应用名查询
│ ├── 按服务名查询
│ └── 查看服务提供者/消费者列表
├── 服务治理
│ ├── 路由规则(条件路由)
│ ├── 动态配置(参数覆盖)
│ ├── 权重调整
│ ├── 负载均衡策略切换
│ └── 服务禁用/启用
├── 服务测试
│ ├── 接口方法在线调用
│ └── 参数JSON编辑
├── 服务统计
│ ├── 调用次数统计
│ ├── 平均耗时
│ └── 并发数监控
└── 元数据管理
├── 接口元数据查看
└── 方法签名浏览
4.3 Maven打包与启动
bash
# 1. 克隆源码
git clone https://github.com/apache/dubbo-admin.git
cd dubbo-admin
# 2. Maven打包(跳过测试)
mvn clean package -DskipTests
# 3. 找到打包产物
# 位于 dubbo-admin-distribution/target/dubbo-admin-0.1.jar
# 4. 启动(确保ZK已启动)
java -jar dubbo-admin-0.1.jar
# 5. 浏览器访问
# http://localhost:8080
# 默认账号/密码:root/root
本章总结
通过本章的实战演练,你已经掌握了Dubbo从简单到复杂的完整使用链路:
- 直连模式:理解Dubbo的基本工作原理------Provider暴露服务,Consumer通过动态代理调用
- 注册中心模式:掌握ZK作为注册中心的配置方式,理解临时节点与Watcher机制
- Web集成:了解Spring容器层级关系,掌握Dubbo在Web环境中的配置方式
- 管理控制台:学会使用Dubbo Admin进行可视化的服务治理
关键要点:
- 服务接口需独立为API模块,Provider和Consumer共同依赖
- ZK注册中心使用临时节点存储Provider地址,Provider断开后节点自动删除
- 同一主机运行多个Dubbo应用时需配置不同的QOS端口