cloud Alibaba e-commerce project series: architecture evolution, understanding domain driven design, and writing of project common modules

cloud Alibaba project

Architecture evolution

Monomer architecture

  • The database and cache are shared in one program, and the deployment is simple
  • The disadvantages are obvious, and the code coupling seriously affects the whole body

Vertical Architecture

  • Advantages: service, independent deployment, easy horizontal expansion
  • Disadvantages: complex construction, complex relationship between services and difficult maintenance

SOA Architecture

  • At first, there was a function division of blocks, but it still called each service node through a bus
  • Advantages: it provides a unified route for the underlying services, which is convenient to call
  • Disadvantages: it is difficult to implement, and there is coupling between different architectures

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-rNaKHa12-1638451334849)(springcloudalibaba project. assets/image-20211202193441209.png)]

Microservice architecture

  • Compared with SOA, the entry of microservices began to change, no longer directly accessing programs, but dispatching and forwarding through gateways
  • The filtered requests will be forwarded to the corresponding microservices. Each service is independent and runs on different machines, communicating with rest or http

Cognitive Domain Driven Design

Advantages: entrance authentication, detailed function distribution and excellent performance
Disadvantages, complexity and difficulty of the project, information exposure, complex links and other problems

Understanding of Domain Driven Design

Understand domain concepts, learn domain knowledge, and model the domain

  • Analysis domain model, deduction entity, value object, domain service
  • Find the aggregation boundary and reduce the service coupling
  • Provide storage warehouse for coupling and data persistence
  • Practice DDD and push it to refactoring

Classic layered architecture

unscramble

  • User Interface the User Interface layer receives user instructions and displays information
  • The applcation application layer Controller provides service interfaces externally and calls the domain layer internally
  • The Domain domain layer is equivalent to an entity object, and the Domain model corresponds to a table in the database
  • Infrastructure infrastructure layer provides common basic capabilities, communication capabilities and persistence mechanisms for other layers

Traditional development:

The database tables will be designed before the start to meet the requirements. Later modifications will affect the function and even the overall structure

Domain Driven Design:

At the initial stage, the business is concerned, and persistence is only for the later stage of business design

E-commerce engineering business interpretation, micro service module splitting

Tips

The best way to learn domain knowledge is reference and reference

Simple understanding diagram

Microservice module splitting

Project portal and user authentication micro service

The gateway is the only entrance to the microservice architecture

This is the facade of e-commerce

Involve

  • Authority authentication
  • Service call
  • Current limiting, etc

Main function service module

Account, commodity, order, logistics

  • Reasonable division of micro services
  • Try to reduce the dependency of each service and the intersection with other services, preferably no intersection

E-commerce development

Implement common modules

step

Create project -- > import dependency – > write configuration

The parent project creates the corresponding dependencies required for e-commerce-springcloud import

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.hyc.ecommerce</groupId>
    <artifactId>e-commerce-springcloud</artifactId>
    <version>1.0-SNAPSHOT</version>

    <modules>
        <module>e-commerce-common</module>
        <module>e-commerce-mvc-config</module>
    </modules>

    <packaging>pom</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
    </parent>

    <properties>
        <!-- Spring Cloud Hoxton.SR8 rely on -->
        <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
        <!-- spring cloud alibaba rely on -->
        <spring-cloud-alibaba.version>2.2.4.RELEASE</spring-cloud-alibaba.version>
    </properties>

    <dependencies>
        <!-- lombok The tool dynamically replaces annotations with specific code during code compilation,
        IDEA Need to add lombok plug-in unit -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.18</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.11</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-collections4</artifactId>
            <version>4.4</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.6.0</version>
        </dependency>
        <!-- introduce jwt-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.10.5</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.10.5</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId>
            <version>0.10.5</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>
    </dependencies>

    <!-- Project dependency management the parent project only declares dependencies, and the child project needs to specify the required dependencies(Version information can be omitted) -->
    <dependencyManagement>
        <dependencies>
            <!-- spring cloud rely on -->
            <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 rely on -->
            <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>

    <!-- Configure remote warehouse -->
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

</project>

Common sub module common library commons

e-commerce-common module

Dependencies are as follows

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>e-commerce-springcloud</artifactId>
        <groupId>com.hyc.ecommerce</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>e-commerce-common</artifactId>

    <!-- Module name and description information -->
    <name>e-commerce-common</name>
    <description>General module</description>
</project>

In this way, many data models will be put into the module to be used by the function service module. First, create and respond uniformly, and then the corresponding data model will be added

Create response format

/**
 * @author : Leng Huanyuan
 * @date : 2021/12/2
 * @context: General response definition
 * {
 * "code":1
 * "message":hyc
 * "data":{}
 * }
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CommonResponse<T> implements Serializable {
    //Corresponding code
    private Integer code;
    //Return message information description
    private String message;

    public CommonResponse(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    //Generic content data
    private T Data;
}

Common sub module web unified return and global exception handling e-commerce-mvc-config

The e-commerce-mvc-config module is mainly used to isolate functions. Some service modules, such as the gateway, cannot be started with web dependencies. In this way, it can import commons to isolate the corresponding functions of services

Dependencies are as follows

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>e-commerce-springcloud</artifactId>
        <groupId>com.hyc.ecommerce</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>e-commerce-mvc-config</artifactId>
    <!-- Module name and description information -->
    <name>e-commerce-mvc-config</name>
    <description>General configuration module</description>

    <dependencies>
        <!-- introduce Web function -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.hyc.ecommerce</groupId>
            <artifactId>e-commerce-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>

Write annotation IgnoreResponseAdvice

IgnoreResponseAdvice ignores the definition of the unified response annotation, that is, it does not need to use the CommonsResponese class defined by us to use this annotation

Realize uniform response and uniform ignore response annotation
/**
 * @author : Leng Huanyuan
 * @date : 2021/12/2
 * @context: Realize uniform response and uniform ignore response annotation
 * @params :  null
 * @return :  * @return : null
 */
@RestControllerAdvice(value = "com.hyc.ecommerce")
//Implement the interface suggested by the responder
public class CommonResponseDataAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter methodParameter,
                            Class<? extends HttpMessageConverter<?>> aClass) {
        //Determine whether the annotation IgnoreResponseAdvice is available on the class
        if (methodParameter.getDeclaringClass().isAnnotationPresent(IgnoreResponseAdvice.class)) {
            return false;
        }
        //Judge whether the annotation IgnoreResponseAdvice is available on the method
        if (methodParameter.getMethod().isAnnotationPresent(IgnoreResponseAdvice.class)) {
            return false;
        }
        //If none, it means to use the public return format
        return true;
    }

    //How to use it if it needs to be used
    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter,
                                  MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass,
                                  ServerHttpRequest serverHttpRequest,
                                  ServerHttpResponse serverHttpResponse) {
        //Define the final return object
        CommonResponse<Object> response = new CommonResponse<>(0, "");
        //If it is equal to null, it means there is no direct return
        if (o == null) {
            return response;
            //If it is equal to the public return type, convert o to the public return commonresponse < >
        } else if (o instanceof CommonResponse) {
            response = (CommonResponse<Object>) o;
            //If not, the response content is set to the object
        } else {
            response.setData(o);
        }
        return response;
    }
}

Global exception handling

GlobalExceptionAdvice handles global exceptions. If a request occurs, an exception will be returned to a unified result

/**
 * @author : Leng Huanyuan
 * @date : 2021/12/2
 * @context:Global exception handling
 * @params :  null
 * @return :  * @return : null
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionAdvice {
    //This annotation means exception handling, and the parameter is the exception you want to catch
    @ExceptionHandler(value = Exception.class)
    public CommonResponse<String> handlerCommerceException(HttpServerRequest req, Exception ex) {
        //Initializes a public response object
        CommonResponse<String> response = new CommonResponse<>(
                -1, "business error"
        );
        //Add the error message to the message header
        response.setData(ex.getMessage());
        //Control the background print error log and return the public response body to give the caller a prompt
        log.error("commerce service has error:[{}]", ex.getMessage(), ex);
        return response;
    }

}

Keywords: Spring Cloud architecture Microservices

Added by tony.j.jackson@o2.co.uk on Fri, 03 Dec 2021 00:25:22 +0200