分布式入门教程记录。由于dubbo依赖zookeeper,前置条件需掌握zookeeper相关知识,可跳转至zookeeper指南提前进行了解。
官网解释如下:Apache Dubbo 是一款微服务框架,为大规模微服务实践提供高性能 RPC 通信、流量治理、可观测性等解决方案,
涵盖 Java、Golang 等多种语言 SDK 实现。
主要为了实现生产环境中单体服务无法满足日趋增长的访问量所做的横向扩展,使用以下粗略的草图来表示使用dubbo前和使用dubbo后的区别:

(简单表示单点服务)

(引入dubbo/zookeeper后)
我们可以横向扩展多个服务,有多种场景可以适用,例如在一个系统中我们将用户中心作为单独一个服务A,订单系统作为单独一个服务B,并且服务A和服务B都可以作为多个副本部署在不同的服务器并注册到dubbo上。
当用户访问的时候就会经过dubbo来分配请求,其中在dubbo这一层还有zookeeper的参与。本文重点突出dubbo的使用,故假设读者已经具备zookeeper的使用能力,若有疑问可以转至笔者的另一篇文章进行了解:zookeeper指南
talk is cheap,show me the code,我们直接上手玩一把。
网上也有较多的例子,这里以保姆教学的心态将每个细节都呈现给读者。
我们首先需要建立一个多模块聚合工程,包含以下三个模块:
其中,consumer和provider都依赖api模块,这里将关键的pom文件展示出来:
root父工程的pom依赖:
<modelVersion>4.0.0modelVersion>
<packaging>pompackaging>
<name>mydubboname>
<groupId>org.vainycosgroupId>
<artifactId>mydubboartifactId>
<version>1.0version>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.7.2version>
<relativePath/>
parent>
<modules>
<module>apimodule>
<module>consumermodule>
<module>providermodule>
modules>
<properties>
<java.version>1.8java.version>
<maven.compiler.source>8maven.compiler.source>
<maven.compiler.target>8maven.compiler.target>
properties>
api模块:
<parent>
<groupId>org.vainycosgroupId>
<artifactId>mydubboartifactId>
<version>1.0version>
parent>
<groupId>com.vainycosgroupId>
<artifactId>apiartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>apiname>
<description>apidescription>
<dependencies>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
dependencies>
provider模块:
<parent>
<groupId>org.vainycosgroupId>
<artifactId>mydubboartifactId>
<version>1.0version>
parent>
<dependencies>
<dependency>
<groupId>com.vainycosgroupId>
<artifactId>apiartifactId>
<version>0.0.1-SNAPSHOTversion>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-spring-boot-starterartifactId>
<version>2.7.6version>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-dependencies-zookeeperartifactId>
<version>2.7.6version>
<type>pomtype>
<exclusions>
<exclusion>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
dependencies>
<build>
<finalName>dubbo-providerfinalName>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<mainClass>com.vainycos.provider.ProviderApplicationmainClass>
configuration>
<executions>
<execution>
<goals>
<goal>repackagegoal>
goals>
execution>
executions>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-surefire-pluginartifactId>
<version>2.21.0version>
<configuration>
<skipTests>trueskipTests>
configuration>
plugin>
plugins>
build>
consumer模块:
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.7.2version>
<relativePath/>
parent>
<dependencies>
<dependency>
<groupId>com.vainycosgroupId>
<artifactId>apiartifactId>
<version>0.0.1-SNAPSHOTversion>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-spring-boot-starterartifactId>
<version>2.7.6version>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-dependencies-zookeeperartifactId>
<version>2.7.6version>
<type>pomtype>
<exclusions>
<exclusion>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
exclusion>
exclusions>
dependency>
dependencies>
<build>
<finalName>dubbo-consumerfinalName>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<mainClass>com.vainycos.consumer.ConsumerApplicationmainClass>
configuration>
<executions>
<execution>
<goals>
<goal>repackagegoal>
goals>
execution>
executions>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-surefire-pluginartifactId>
<version>2.21.0version>
<configuration>
<skipTests>trueskipTests>
configuration>
plugin>
plugins>
build>
spring:
application:
name: provider
server:
port: 60001
dubbo:
registry:
# zookeeper的注册地址
address: zookeeper://x.x.x.x:2181
timeout: 10000
protocol:
name: dubbo
# 线上环境可使用-1,由dubbo分配端口
port: 20880
scan:
base-packages: com.vainycos.provider.service
spring:
application:
name: consumer
server:
port: 50001
dubbo:
registry:
address: zookeeper://x.x.x.x:2181
timeout: 10000
定义接口
public interface OrderService {
List<Order> findOrdersByUserId(Integer userId);
}
定义model
@Data
public class Order implements Serializable {
private Long id;
private Date createTime;
private Integer userId;
private List<OrderItem> orderItemList;
}
@Data
public class Order implements Serializable {
private Long id;
private Date createTime;
private Integer userId;
private List<OrderItem> orderItemList;
}
服务实现类
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import java.util.ArrayList;
import java.util.List;
/**
* @author: Vainycos
* @description
* @date: 2022/8/4 15:29
*/
// 需注意这里引入@Service注解是dubbo包下的
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
@Override
public List<Order> findOrdersByUserId(Integer userId) {
// do something
log.info("获取订单消息...");
Order order = new Order();
order.setId(1L);
order.setUserId(userId);
List<Order> list = new ArrayList<>();
list.add(order);
return list;
}
}
service:
public interface UserService {
List<Order> findOrdersByUserId(Integer id);
}
import com.vainycos.consumer.service.UserService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author: Vainycos
* @description
* @date: 2022/8/4 15:57
*/
// Spring的Service注解
@Service
public class UserServiceImpl implements UserService {
@Reference
private OrderService orderService;
@Override
public List<Order> findOrdersByUserId(Integer id) {
return orderService.findOrdersByUserId(id);
}
}
controller:
@RequestMapping("/test")
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/getUser")
public List<Order> getUser(Integer userId){
List<Order> ordersByUserId = userService.findOrdersByUserId(userId);
return ordersByUserId;
}
}
此时,我们分别启动provider以及consumer,并访问consumer的接口:localhost:50001/test/getUser,观察provider的日志正确输出:获取订单消息…即表示成功了。
dubbo-admin是一个官方的可视化服务,这里我们通过Github的源代码仓库进行构建。
访问Github地址:https://github.com/apache/dubbo-admin,并clone至本地
目录结构如下

重点关注dubbo-admin-server以及dubbo-admin-ui模块,前者是springboot后端项目,后者是vue前端项目。
server.port=10080
admin.registry.address=zookeeper://10.8.3.173:2181
admin.config-center=zookeeper://10.8.3.173:2181
admin.metadata-report.address=zookeeper://10.8.3.173:2181
# 可选调整
admin.root.user.name=root
admin.root.user.password=root
本地调试模式启动:前后端分开启动;或者在根目录下打包后直接用根目录的jar包启动,两种启动结果是一致的。
启动后端,以下两种方式
启动前端
首先需要准备node环境
切换到dubbo-admin-ui目录下,运行命令npm install
修改dubbo-admin-ui/vue.config.js的代理后端地址,需要与dubbo-admin-server配置文件中的启动端口保持一致
proxy: {
'/': {
// 实际后端访问地址
target: 'http://localhost:10080/',
changeOrigin: true,
pathRewrite: {
'^/': '/'
}
}
}
执行启动命令,默认启动端口为8082
npm run dev

启动完成之后访问localhost:8082,默认账号密码是root/root。

作为dubbo的使用,仅仅作为开始,后续将会不断地丰富该项目,将以上代码在gitee上进行开源:https://gitee.com/dearvainycos/mydubbo.git。
参考资料: