order-service:订单服务,服务消费者,远程调用商品服务
依赖关系dubbo-demo 的 pom.xml。
<?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 "> <modelVersion>4.0.0</modelVersion> <!-- 项目坐标地址 --> <groupId>com.example</groupId> <!-- 项目模块名称 --> <artifactId>dubbo-demo</artifactId> <packaging>pom</packaging> <!-- 项目版本名称 快照版本SNAPSHOT、正式版本RELEASE --> <version>1.0-SNAPSHOT</version> <modules> <module>service-api</module> <module>product-service</module> <module>order-service</module> </modules> <!-- 继承 spring-boot-starter-parent 依赖 --> <!-- 使用继承方式,实现复用,符合继承的都可以被使用 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.0.RELEASE</version> </parent> <!-- 集中定义依赖组件版本号,但不引入, 在子工程中用到声明的依赖时,可以不加依赖的版本号, 这样可以统一管理工程中用到的依赖版本 --> <properties> <!-- Spring Cloud Hoxton.SR5 依赖 --> <spring-cloud.version>Hoxton.SR5</spring-cloud.version> <!-- spring cloud alibaba 依赖 --> <spring-cloud-alibaba.version>2.1.0.RELEASE</spring-cloud-alibaba.version> </properties> <!-- 项目依赖管理 父项目只是声明依赖,子项目需要写明需要的依赖(可以省略版本信息) --> <dependencyManagement> <dependencies> <!-- spring cloud 依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- spring cloud alibaba 依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${spring-cloud-alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>service-api 的 pom.xml
<?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 "> <parent> <artifactId>dubbo-demo</artifactId> <groupId>com.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>service-api</artifactId> <dependencies> <!-- lombok 依赖 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> </project>product-service 需要依赖 Nacos 和 Dubbo 的依赖,还有 service-api 的依赖,完整依赖如下:
<?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 "> <!-- 继承父依赖 --> <parent> <artifactId>dubbo-demo</artifactId> <groupId>com.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>product-service</artifactId> <!-- 项目依赖 --> <dependencies> <!-- spring cloud alibaba nacos discovery 依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- spring cloud alibaba dubbo 依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dubbo</artifactId> </dependency> <!-- spring boot web 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- service-api 依赖 --> <dependency> <groupId>com.example</groupId> <artifactId>service-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!-- spring boot test 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> </project>order-service 需要依赖 Nacos 和 Dubbo 的依赖,还有 service-api 的依赖,完整依赖如下:
<?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 "> <!-- 继承父依赖 --> <parent> <artifactId>dubbo-demo</artifactId> <groupId>com.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>order-service</artifactId> <!-- 项目依赖 --> <dependencies> <!-- spring cloud alibaba nacos discovery 依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- spring cloud alibaba dubbo 依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dubbo</artifactId> </dependency> <!-- spring boot web 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- service-api 依赖 --> <dependency> <groupId>com.example</groupId> <artifactId>service-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!-- spring boot test 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> </project> 定义服务接口我们在 service-api 模块中定义实体类和服务接口信息。
实体类Product.java
package com.example.product.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; @Data @NoArgsConstructor @AllArgsConstructor public class Product implements Serializable { private Integer id; private String productName; private Integer productNum; private Double productPrice; }Order.java
package com.example.product.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; import java.util.List; @Data @NoArgsConstructor @AllArgsConstructor public class Order implements Serializable { private Integer id; private String orderNo; private String orderAddress; private Double totalPrice; private List<Product> productList; } 服务接口 package com.example.product.service; import com.example.product.pojo.Product; import java.util.List; /** * 商品服务 */ public interface ProductService { /** * 查询商品列表 * * @return */ List<Product> selectProductList(); } 定义服务提供者 配置文件配置文件需要配置 Nacos 注册中心和 Dubbo 相关信息,核心配置如下:
server: port: 7070 # 端口 spring: application: name: product-service # 应用名称 # 配置 Nacos 注册中心 cloud: nacos: discovery: enabled: true # 如果不想使用 Nacos 进行服务注册和发现,设置为 false 即可 server-addr: 127.0.0.1:8848 # Nacos 服务器地址,单机版 # Dubbo dubbo: # 提供方应用信息,用于计算依赖关系 application: name: product-service # 使用 nacos 注册中心暴露服务地址 registry: protocol: nacos address: spring-cloud://localhost # 用 dubbo 协议在 20880 端口暴露服务 protocol: name: dubbo port: 20880 # 扫描需要暴露的服务,可以被 @EnableDubbo 注解替代 #scan: # base-packages: com.example.service 服务提供者product-service 的 ProductServiceImpl.java
package com.example.service.impl; import com.example.product.pojo.Product; import com.example.product.service.ProductService; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.config.annotation.Service; import java.util.Arrays; import java.util.List; /** * 商品服务 * timeout 调用该服务的超时时间 * version 为版本号 * group 为分组 * interface、group、version 三者确定一个服务 */ @Slf4j @Service(timeout = 5000, version = "1.0", group = "product-service") public class ProductServiceImpl implements ProductService { /** * 查询商品列表 * * @return */ @Override public List<Product> selectProductList() { log.info("商品服务查询商品信息..."); return Arrays.asList( new Product(1, "华为手机", 1, 5800D), new Product(2, "联想笔记本", 1, 6888D), new Product(3, "小米平板", 5, 2020D) ); } }值得注意的是 @Service 注解不是 Spring 的注解而是 Dubbo 的注释:
启动类启动类通过 @EnableDubbo 注解扫描需要暴露的服务,如果配置文件中配置了该选项,那么这里可以省略。
package com.example; import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; // 扫描需要暴露的服务 @EnableDubbo(scanBasePackages = "com.example.service") // 开启 @EnableDiscoveryClient 注解,当前版本默认会开启该注解 //@EnableDiscoveryClient @SpringBootApplication public class ProductServiceApplication { public static void main(String[] args) { SpringApplication.run(ProductServiceApplication.class, args); } } 定义服务消费者 配置文件配置文件需要配置 Nacos 注册中心和 Dubbo 相关信息,核心配置如下:
server: port: 9090 # 端口 spring: application: name: order-service # 应用名称 # 配置 Nacos 注册中心 cloud: nacos: discovery: enabled: true # 如果不想使用 Nacos 进行服务注册和发现,设置为 false 即可 server-addr: 127.0.0.1:8848 # Nacos 服务器地址,单机版 # Dubbo dubbo: # 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 application: name: order-service # 发现 nacos 注册中心暴露的服务 registry: protocol: nacos address: spring-cloud://localhost cloud: subscribed-services: product-service # 订阅服务,远程调用的服务名称 服务消费者order-service 的 OrderServiceImpl.java
package com.example.service.impl; import com.example.product.pojo.Order; import com.example.product.service.ProductService; import com.example.service.OrderService; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.config.annotation.Reference; import org.springframework.stereotype.Service; @Slf4j @Service public class OrderServiceImpl implements OrderService { // dubbo 提供了 @Reference 注解,可替换 @Autowired 注解,用于引入远程服务 // 如果注册服务时设置了版本及分组信息,调用远程服务时也要设置对应的版本及分组信息 @Reference(timeout = 5000, version = "1.0", group = "product-service") private ProductService productService; /** * 根据主键查询订单 * * @param id * @return */ @Override public Order selectOrderById(Integer id) { log.info("订单服务查询订单信息..."); return new Order(id, "order-001", "中国", 22788D, productService.selectProductList()); } } 启动类 package com.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; // 开启 @EnableDiscoveryClient 注解,当前版本默认会开启该注解 //@EnableDiscoveryClient @SpringBootApplication public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } } 测试先启动 Nacos 服务器,然后启动服务提供者 product-service,访问::8848/nacos/ 控制台显示如下:
然后启动服务消费者,控制台显示如下:
订单服务调用远程商品服务,结果如下:
Dubbo 负载均衡在集群负载均衡时,Dubbo 提供了多种均衡策略,缺省为 random 随机调用,也可以自行扩展负载均衡策略。
负载均衡策略 Random LoadBalance「随机」,按权重设置随机概率。