锦通 发表于 6 小时前

微服务学习-快速搭建

1. 速通版

1.1. git clone 拉取项目代码,导入 idea 中

git clone icoolkj-microservices-code: 致力于搭建微服务架构平台
1.2. git checkout v1.0.1版本

链接地址:icoolkj-microservices-code 标签 - Gitee.com
2. 项目服务结构

https://i-blog.csdnimg.cn/direct/e3bb675420d6417483f311e5b5d870d9.png
3. 实现重点步骤

3.1. 业务需求

实现用户下单,扣减库存,查询商品单价,扣减账户余额的功能。
3.2. 怎样引入 Spring Cloud Alibaba 的依靠

3.2.1. 父工程 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.icoolkj</groupId>
   <artifactId>icoolkj-microservices-code</artifactId>
   <version>1.0.1</version>
   <packaging>pom</packaging>

   <properties>
      <java.version>17</java.version>
      <!-- 微服务版本 -->
      <spring-boot.version>3.2.4</spring-boot.version>
      <spring-cloud.version>2023.0.1</spring-cloud.version>
      <spring-cloud-alibaba.version>2023.0.1.0</spring-cloud-alibaba.version>

   </properties>

   <dependencyManagement>
      <dependencies>

         <!-- Spring Boot Starter父依赖 -->
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>${spring-boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>

         <!-- 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> 3.2.2. <dependencyManagement> 和 <dependency> 的区别

Mave 使用 dependencyManagement 元素来提供一种管理依靠版本号的方式。
使用 pom.xml 中的 dependencyManagement 元素能让子项目中引用同一个版本依靠,而不用显示的列出版本号。
长处:假如多个子项目引用同一个依靠,可以避免每个子项目里面再声明版本号。
优势:当升级或切换项目中的某个依靠版本时,只须要再父 pom.xml 文件里面更新,子项目无需修改;假如某个子项目须要别的一个依靠的版本,只须要再子项目声明 version 即可。
注意:

[*]dependencyManagement 里面只是声明依靠,并不实现引入,因此子项目须要显示声明须要用的依靠;
[*]假如不在子项目中声明依靠,是不会从父项目中继承下来的,只有在子项目中声明了依靠而且没有指定具体版本,才会从父项目继承该依靠项,且 version 和 scope 都读取父 pom;
[*]假如子项目中指定了依靠项版本号,那么就会使用子项目指定的 jar 版本。
3.3. 环境准备

3.3.1. 在启动服务前,请先设置 Host 地址映射,确保服务能够正常启动

# 服务
127.0.0.1 icoolkj-mall-account
127.0.0.1 icoolkj-mall-order
127.0.0.1 icoolkj-mall-product
127.0.0.1 icoolkj-mall-inventory
127.0.0.1 icoolkj-mall-gateway
# 中间件
127.0.0.1 icoolkj-mall-mysql
127.0.0.1 icoolkj-mall-nacos-server
127.0.0.1 icoolkj-mall-seata-server
127.0.0.1 icoolkj-mall-sentinel-dashboard
127.0.0.1 icoolkj-mall-skywalking-server Windows 体系路径:C:\Windows\System32\drivers\etc\hosts
macOS 体系路径:/etc/hosts
Linux 体系路径: /etc/hosts
3.3.2. 须要导入 MySQL 数据库脚本文件

脚本文件地址:spring-cloud-alibaba-examples/config/init.sql · icoolkj/icoolkj-microservices-code - Gitee.com
3.4. 项目演示

3.4.1. 启动所有服务,使用 Postman 举行测试

查询商品单价:localhost:8080/api/product/get-price-product?productId=1
查询商品库存:localhost:8081/api/inventory/get-inventory-quantity?productId=1
查询账户余额:localhost:8083/api/account/get-balance-account?userId=1
用户下单:localhost:8082/api/order/create-order
3.4.2. 发现问题

3.4.2.1. 用户正常下单,没有扣减库存,没有查询商品代价,没有扣减账户余额

微服务须要实现服务之间的调用,必须订单微服务 8082 怎样调用库存微服务 8081,怎样实现?
解决方案:利用 Spring 框架提供的 RestTemplate 实现服务间的调用
@Bean 的方式设置 RestTemplate
@Configuration
public class RestTemplateConfig {
    @Bean
    RestTemplate restTemplate(){
      return new RestTemplate();
    }

}  订单服务 OrderServiceImpl 引入RestTemplate
@Autowired
private RestTemplate restTemplate;  通过 restTemplate.postForObject restTemplate.exchange 等发放调用 商品服务,库存服务,账户服务
//deduct inventory
InventoryRequest inventoryRequest = new InventoryRequest();
inventoryRequest.setProductId(productId);
inventoryRequest.setInventoryQuantity(orderQuantity);
//RestTemplate 远程调用
String inventoryUrl = "http://localhost:8081/api/inventory/reduce-inventory";
int inventoryCode = restTemplate.postForObject(inventoryUrl, inventoryRequest, Result.class).getCode();
if(inventoryCode == Result.FAIL){
    throw new BusinessException("inventory not enough.");
}

// 获取商品单价
String getPriceProductUrl = "http://localhost:8080/api/product/get-price-product?productId=" + productId;
// 使用泛型解析嵌套数据
ParameterizedTypeReference<Result<ProductResponse>> responseType =
      new ParameterizedTypeReference<Result<ProductResponse>>() {};
ResponseEntity<Result<ProductResponse>> responseEntity =
      restTemplate.exchange(getPriceProductUrl, HttpMethod.GET, null, responseType);

// 获取返回结果
Result<ProductResponse> result = responseEntity.getBody();
BigDecimal orderCost = null;
if(result.getCode() == Result.SUCCESS){
    ProductResponse productResponse = result.getData();
    if (productResponse != null && productResponse.getProductPrice() != null) {
      orderCost= productResponse.getProductPrice().multiply(new BigDecimal(orderQuantity));
    }
}
if(orderCost == null){
    throw new BusinessException("product price wrong, please check the product price.");
}
AccountRequest accountRequest = new AccountRequest();
accountRequest.setUserId(userId);
accountRequest.setOrderCost(orderCost);
//RestTemplate远程调用
String account_url = "http://localhost:8083/api/account/reduce-balance";
int accountCode = restTemplate.postForObject(account_url, accountRequest, Result.class).getCode();
// Integer accountCode = accountService.reduceBalance(accountDTO).getCode();
if (accountCode == Result.FAIL) {
    throw new BusinessException("balance not enough");
} 3.4.2.2. 微服务地点的 IP 地址和端标语都是硬编码,假如库存服务(服务提供者)的 IP 和端口发送变革,大概增加多个库存服务怎样调用?

RestTemplate 远程调用
String inventoryUrl = "http://localhost:8081/api/inventory/reduce-inventory";
int inventoryCode = restTemplate.postForObject(inventoryUrl, inventoryRequest, Result.class).getCode(); 须要实现服务发现功能,好比订单服务调用前能够获取到最新的库存、商品、账户等服务的列表
解决方案:引入注册中央 Nacos,实现服务的注册与发现,好比将库存、商品、账户等服务注册到 Nacos 中,订单服务调用之前从 Nacos 获取相应的服务列表。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 微服务学习-快速搭建