[SpringCloud Alibaba] (2) Microservice environment construction

1. Project process establishment

The entire project is mainly divided into user microservices, product microservices and order microservices . The entire process simulates the operation of deducting inventory when users place orders. Here, in order to simplify the entire process, the inventory information of the product is saved to the product data table, and at the same time, the product microservice is used to deduct the inventory. When implementing, friends can also develop a separate microservice module for product inventory information. The main logic is the same as that of managing inventory information in product microservices. The calling process between each service is as follows:
insert image description here
The overall process of user microservice, product microservice and order microservice is: after the user calls the order submission interface of the order microservice through the client, the order microservice will call the user microservice and order microservice respectively. The interface of the product microservice is used to query user information and product information, and verify whether the product inventory is sufficient. If the product inventory is sufficient, the order will be saved. And the inventory reduction interface of the product microservice will be called to reduce the inventory.

2. Technology selection

The entire project is implemented using the SpringCloud Alibaba technology stack. The main technology selections are as follows:

  • Persistence layer framework: MyBatis, MyBatis-Plus
  • Microservice framework: SpringCloud Alibaba
  • Message middleware: RocketMQ
  • Service governance and service configuration: Nacos
  • Load balancing component: Ribbon
  • Remote service call: Fegin
  • Service current limiting and fault tolerance: Sentinel
  • Service gateway: SpringCloud-Gateway
  • Service link tracking: Sleuth + ZipKin
  • Distributed transactions: Seata
  • Data storage: MySQL+ElasticSearch

3. Module division

In order to facilitate development and maintenance, and for the reusability of modules, when the overall project is built, the user microservice, product microservice and order microservice will be placed under the same Maven parent project as sub-modules of the parent project. , the JavaBeans used by user microservices, product microservices and order microservices are separately used as a Maven module, and the tool classes used by each service are separately used as a Maven module.

insert image description here
The description of each module is as follows:

  • shop-springcloud-alibaba: Maven parent project.
  • shop-bean: JavaBean module used by each service, including entity classes, Dto, Vo and other JavaBeans.
  • shop-utils: Tool module used by each service.
  • shop-order: order microservice.
  • shop-product: product microservice.
  • shop-user: user microservice

4. Code address

Code code cloud address

Among them, the database file is located dbunder the folder.

5. Module development

The code has been hosted on Code Cloud, only part of the code is posted here.

5.1 Create maven parent project


Create a Maven project in IDEA named shop-springcloud-alibaba. After creation, add StringBoot and SpringCloud alibaba-related configurations in the project's pom.xml file , as shown below:

<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.6.RELEASE</version>
        <relativePath/>
    </parent>
    <packaging>pom</packaging>
    <groupId>com.zzc</groupId>
    <artifactId>shop-springcloud-alibaba</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>shop-springcloud-alibaba</name>
    <description>shop-springcloud-alibaba</description>
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
        <spring-cloud-alibaba.version>2.1.0.RELEASE</spring-cloud-alibaba.version>
        <logback.version>1.1.7</logback.version>
        <slf4j.version>1.7.21</slf4j.version>
        <common.logging>1.2</common.logging>
        <fastjson.version>1.2.51</fastjson.version>
        <mybatis.version>3.4.6</mybatis.version>
        <mybatis.plus.version>3.4.1</mybatis.plus.version>
        <mysql.jdbc.version>8.0.19</mysql.jdbc.version>
        <druid.version>1.1.10</druid.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <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>

5.2 Create tool modules

Create the tool module shop-utils under the parent project as a common tool module for the entire project. The overall structure of the tool module is as follows:
insert image description here
Code structure description:

  1. HttpCode:HTTP status code encapsulation class
  2. RestCtrlExceptionHandler: Global exception catching class
  3. md5Package: General MD5 and password encryption classes
  4. Result:Data response class
  5. idPackage: Generate Id using snowflake algorithm

5.3 Create other microservice modules

5.3.1 Create entity class module

Create the entity class module shop-bean under the parent project as a common entity class module for the entire project

The dependency of the shop-bean module is relatively simple. You only need to rely on the shop-utils module. Add the following configuration in the pom.xml file of the shop-bean module:

<dependency>
    <groupId>com.zzc</groupId>
    <artifactId>shop-utils</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

5.3.2 Create three major microservices and complete interaction

For user microservices, product microservices and order microservices , the ports occupied by each service and the basic access paths are different. Here, the ports occupied by each service and the basic access paths are organized into the following table. :

service name project name Occupy port base path to access Remark
User microservices shop-user 8060 /user User additions, deletions, modifications and checks
Product microservices shop-product 8070 /product Product addition, deletion, modification and check
Order microservice shop-order 8080 /order Add, delete, modify and check orders

Create microservices

Create a Maven project named shop-user. Since we have completed the overall structure of the project in the previous article, we can add the following dependencies to the pom.xml file of shop-user:

<dependency>
    <groupId>com.zzc</groupId>
    <artifactId>shop-bean</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

shop-product, shop-orderMicroservice is shop-usersimilar to , except that the configuration file application.ymlconfiguration port and access path are different.

6. Order microservice order interface

Here we focus on shop-orderthe ordering interface:

@Override
@Transactional(rollbackFor = Exception.class)
public void saveOrder(OrderParamVo orderParamVo) {
    
    
    if (orderParamVo.isEmpty()){
    
    
        throw new RuntimeException("参数异常: " + JSONObject.toJSONString(orderParamVo));
    }
    User user = restTemplate.getForObject("http://localhost:8060/user/get/" + orderParamVo.getUserId(), User.class);
    if (user == null){
    
    
        throw new RuntimeException("未获取到用户信息: " + JSONObject.toJSONString(orderParamVo));
    }
    Product product = restTemplate.getForObject("http://localhost:8070/product/get/" + orderParamVo.getProductId(), Product.class);
    if (product == null){
    
    
        throw new RuntimeException("未获取到商品信息: " + JSONObject.toJSONString(orderParamVo));
    }
    if (product.getProStock() < orderParamVo.getCount()){
    
    
        throw new RuntimeException("商品库存不足: " + JSONObject.toJSONString(orderParamVo));
    }
    Order order = new Order();
    order.setAddress(user.getAddress());
    order.setPhone(user.getPhone());
    order.setUserId(user.getId());
    order.setUsername(user.getUsername());
    order.setTotalPrice(product.getProPrice().multiply(BigDecimal.valueOf(orderParamVo.getCount())));
    baseMapper.insert(order);
    OrderItem orderItem = new OrderItem();
    orderItem.setNumber(orderParamVo.getCount());
    orderItem.setOrderId(order.getId());
    orderItem.setProId(product.getId());
    orderItem.setProName(product.getProName());
    orderItem.setProPrice(product.getProPrice());
    orderItemMapper.insert(orderItem);
    Result<Integer> result = restTemplate.getForObject("http://localhost:8070/product/update_count/" + orderParamVo.getProductId() + "/" + orderParamVo.getCount(), Result.class);
    if (result.getCode() != HttpCode.SUCCESS){
    
    
        throw new RuntimeException("库存扣减失败");
    }
    log.info("库存扣减成功");
}

In saveOrder()the implementation of the method, the main logic of the implementation is as follows:

  1. Determine whether the parameters encapsulated by orderParams are empty. If the parameters are empty, a parameter exception will be thrown.
  2. Call the user microservice through RestTemplate to obtain the user's basic information. If the obtained user information is empty,
    an exception that the user information was not obtained will be thrown.
  3. Call the product microservice through RestTemplate to obtain the basic information of the product. If the obtained product information is empty,
    an exception that the product information was not obtained will be thrown.

  4. Determine whether the inventory of the product is less than the quantity of the product to be deducted. If the inventory of the product is less than the quantity of the product to be deducted, an exception of insufficient product inventory is thrown .
  5. If the parameters encapsulated by orderParams are not empty, and the user information and product information obtained are not empty, and the inventory of the products is sufficient, an
    order object is created to save the order information, and an order entry object is created to save the order entry information.
  6. Call the interface of product microservice to deduct product inventory

In the process of the above implementation, there is an obvious problem:That is to hard-code the IP and port of the user microservice and the IP and port of the product microservice into the code of the order microservice.. There are many problems with this approach

Hard coding problem

If the IP address and port number of the user microservice and product microservice are hard-coded into the order microservice, there will be many problems. Among them, there are three most obvious problems, as shown below.

  1. If the IP address or port number of the user microservice and product microservice changes, the order microservice will become unavailable, and the
    IP address and port number of the order microservice that calls the user microservice and product microservice need to be modified synchronously. .
  2. If multiple user microservices and commodity microservices are provided in the system, the load balancing function of the microservices cannot be realized.
  3. If the system needs to support higher concurrency, more user microservices, product microservices, and order microservices need to be deployed. If the IP addresses and ports of the user microservices and product microservices are hard-coded into the order microservices, subsequent Maintenance can become incredibly complex.

Therefore, in the process of microservice development,It is necessary to introduce service governance functions to realize dynamic registration and discovery between microservices.

code address

The code has been uploaded to Code Cloud, Code Cloud address

Among them, the database file is located dbunder the folder.

Guess you like

Origin blog.csdn.net/sco5282/article/details/131737957