E-commerce project part04 microservice split

Microservice architecture split

Introduction to microservices

English: https://martinfowler.com/articles/microservices.html
Chinese: http://blog.cuicc.com/blog/2015/07/22/microservices
Insert image description here

When to split microservices

Does the following scenario require microservice splitting?

  • Code maintenance is difficult, hundreds of people develop a module at the same time, and a large number of conflicts frequently occur when submitting code
    ;
  • The modules are severely coupled and interdependent, and small functional modifications must be accumulated into a large version before they can go online
    . Going online requires the director to coordinate various teams to hold meetings to confirm;
  • The horizontal expansion process is complex and the primary business and secondary business are coupled. For example, the ordering and payment business
    needs to be expanded, but the registration business does not need to be expanded.
    Insert image description here
    When to split the microservices:
  • Business scale: The business model has been verified by the market, and it is necessary to further accelerate the pace of quickly occupying the market. At this time, the scale of the business becomes larger and larger, divided according to the product life cycle (introduction period, growth period, maturity period, decline period). Usually in the growth stage. If it is the introduction period, try to adopt a monolithic architecture.
  • Team size: Generally when the team reaches a hundred people, it mainly depends on the complexity of the business.
  • Technical reserves: domain-driven design, registration center, configuration center, log system, continuous delivery, monitoring system, distributed scheduled tasks, CAP theory, distributed call chain, API gateway, etc.
  • Talent reserve: Architects and corresponding developers who are proficient in microservice implementation experience.
  • R&D efficiency: R&D efficiency has dropped significantly.

Some general principles for microservice splitting

The internal functions of a single service have high cohesion and low coupling:

Each service only completes the tasks within its own responsibilities, and leaves functions that are not its own responsibilities to other services to complete.

  • Closure Principle (CCP): The closure principle of microservices is that when we need to change a microservice, all dependencies are within the components of this microservice, and there is no need to modify other microservices.

  • Principle of service autonomy and interface isolation: Try to eliminate strong dependence on other services, which can reduce communication costs and improve service stability. Services are isolated through standard interfaces, hiding internal implementation details. This allows services to be independently developed, tested, deployed, and run, and delivered continuously as service units.

  • Principle of continuous evolution: In the early stages of service splitting, it is actually difficult to determine what the service will be split into. It should be divided gradually and continuously evolved to avoid explosive growth in the number of services.

  • The process of splitting should try to avoid affecting the daily functional iteration of the product: that is to say, the service-oriented split should be completed while iterating product functions. For example, prioritizing the separation of relatively independent boundary services (such as SMS services, etc.), starting from non-core services to reduce the impact of splitting on existing businesses, and also giving the team an opportunity to practice and trial and error. At the same time, when two services have dependencies, the dependent service will be split first.

  • The definition of the service interface must be scalable: for example, the microservice interface has been upgraded from three parameters to four, resulting in a large number of errors reported by the caller after going online. It is recommended that the parameter type of the service interface should be an encapsulated class. In this way, if you add parameters, you don’t have to change the signature of the interface.

  • Avoid circular dependencies and two-way dependencies: Try not to have circular dependencies or two-way dependencies between services. The reason is that the existence of this situation indicates that our functional boundaries are not clearly defined or that common functions are not sinking.
    Insert image description here

  • Phased merger: As your understanding of the business domain gradually deepens or the business logic itself changes significantly, or the previous split was not clearly considered, the service boundaries after the split become more and more confusing. , at this time it is necessary to reorganize the boundaries of the field and constantly correct the rationality of the split.

  • Automation-driven: The cost of deployment and operation and maintenance will increase exponentially as the number of services increases. Each service requires deployment, monitoring, log analysis and other operation and maintenance work, and the cost will increase significantly. Therefore, before service division, automated tools and environments should be built first. Developers should use automation as the driving force to simplify
    the repetitive work of service creation, development, testing, deployment, and operation and maintenance, achieve more reliable operations through tools, and avoid development and management complexity problems caused by the increase in the number of microservices. .

  • Functional dimension splitting strategy
    The general principle is to split services based on business complexity: If the business complexity is high enough, services should be split based on domain drivers. The business complexity is low and data-driven split services are chosen.


    • Split services based on data-driven: Bottom-up architecture design method, determine the overall data structure by analyzing requirements, and split services based on the relationship between tables .
      Split steps: Requirements analysis, abstract data structure, divide services, determine calling relationship and business process verification.
    • Based on domain-driven split services: Top-down architecture design method, through establishing a unified language with domain experts, continuous communication, identifying key business scenarios, and gradually determining the boundary context. Domain-driven puts more emphasis on business implementation effects and believes that bottom-up design may cause technical personnel to fail to better understand the business direction and thus deviate from business goals.
      Splitting steps: establishing a unified language through models and domain experts, business analysis, finding aggregations, determining service calling relationships, business process verification and continuous optimization.
  • There is also a common splitting scenario, where services are gradually split from the existing monolithic architecture.
    Splitting steps: Separate front-end and back-end, extract public basic services (such as single sign-on), continuously extract services from the old system, prioritize vertical division, and appropriate horizontal splitting. The above
    splitting
    methods are not to choose one from many, but can be based on actual conditions. Situations can be freely arranged and combined. At the same time, splitting is not only an architectural adjustment, but also means making corresponding adaptive optimizations in the organizational structure to ensure that the split services are maintained by relatively independent teams.

WeChat parent class

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.msb</groupId>
    <artifactId>SpringCloudAlibabaMSB</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>SpringCloudAlibabaMSB</name>
    <description>SpringCloudAlibabaMSB</description>
    <packaging>pom</packaging>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud-alibaba-version>2.2.6.RELEASE</spring-cloud-alibaba-version>
        <spring-cloud-gateway-version>Hoxton.SR5</spring-cloud-gateway-version>
        <pagehelper-starter.version>1.2.10</pagehelper-starter.version>
        <pagehelper.version>5.1.8</pagehelper.version>
        <druid.version>1.1.10</druid.version>
        <freemarker.version>2.3.30</freemarker.version>
        <hutool.version>4.5.7</hutool.version>
        <swagger2.version>2.7.0</swagger2.version>
        <mybatis-generator.version>1.3.7</mybatis-generator.version>
        <mybatis.version>3.5.3</mybatis.version>
        <mybatis-plus.version>3.3.2</mybatis-plus.version>
        <dynamic-datasource.version>3.5.2</dynamic-datasource.version>
        <mysql-connector.version>8.0.15</mysql-connector.version>
        <commons-pool2.version>2.4.3</commons-pool2.version>
        <dungproxy-client.version>0.0.4</dungproxy-client.version>
        <rocketmq-spring-boot-starter.version>2.2.1</rocketmq-spring-boot-starter.version>
        <mongodb-spring-boot-starter.version>2.2.6.RELEASE</mongodb-spring-boot-starter.version>
        <jjwt.version>0.9.0</jjwt.version>
        <aliyun-oss.version>2.5.0</aliyun-oss.version>
        <logstash-logback.version>5.3</logstash-logback.version>
    
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>


    <dependencyManagement>
    
        <dependencies>
        	<!--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>
			<!--Spring Cloud 相关依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud-gateway-version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
 			<!--业务通用模块-->
			......
			
			<!--MyBatis分页插件starter-->
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper-spring-boot-starter</artifactId>
                <version>${pagehelper-starter.version}</version>
            </dependency>
            <!--MyBatis分页插件-->
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper</artifactId>
                <version>${pagehelper.version}</version>
            </dependency>
            <!--集成druid连接池-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>${druid.version}</version>
            </dependency>
            <!--Hutool Java工具包-->
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>${hutool.version}</version>
            </dependency>
            <!--Swagger-UI API文档生产工具-->
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger2</artifactId>
                <version>${swagger2.version}</version>
            </dependency>
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger-ui</artifactId>
                <version>${swagger2.version}</version>
            </dependency>
            <!-- MyBatis 生成器 -->
            <dependency>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-core</artifactId>
                <version>${mybatis-generator.version}</version>
            </dependency>
            <!-- MyBatis-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>${mybatis.version}</version>
            </dependency>
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${mybatis-plus.version}</version>
            </dependency>
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
                <version>${dynamic-datasource.version}</version>
            </dependency>
            <!--Mysql数据库驱动-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql-connector.version}</version>
            </dependency>

            <!--JWT(Json Web Token)登录支持-->
            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt</artifactId>
                <version>${jjwt.version}</version>
            </dependency>
            <!-- 阿里云OSS -->
            <dependency>
                <groupId>com.aliyun.oss</groupId>
                <artifactId>aliyun-sdk-oss</artifactId>
                <version>${aliyun-oss.version}</version>
            </dependency>
            <!--集成logstash-->
            <dependency>
                <groupId>net.logstash.logback</groupId>
                <artifactId>logstash-logback-encoder</artifactId>
                <version>${logstash-logback.version}</version>
            </dependency>

            <dependency>
                <groupId>org.freemarker</groupId>
                <artifactId>freemarker</artifactId>
                <version>${freemarker.version}</version>
            </dependency>

            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-pool2</artifactId>
                <version>${commons-pool2.version}</version>
            </dependency>

            <dependency>
                <groupId>org.apache.rocketmq</groupId>
                <artifactId>rocketmq-spring-boot-starter</artifactId>
                <version>${rocketmq-spring-boot-starter.version}</version>
            </dependency>
			<dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-mongodb</artifactId>
                <version>${mongodb-spring-boot-starter.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

Subclass

	<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </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-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
		<!-- sentinel依赖 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
		<dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
        </dependency>

        
		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>
    </dependencies>

gateway

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <!--加入nacos的依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

        <!--添加Sentinel的依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
        </dependency>
		<dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
        </dependency>

Startup class annotation

@EnableFeignClients
@EnableDiscoveryClient
@FeignClient("") //服务名

Access Skywalking

Add agent configuration in jvm parameters

‐javaagent:路径\skywalking‐agent.jar
‐Dskywalking.agent.service_name=服务名
‐Dskywalking.collector.backend_service=ip地址:11800

Integrate log framework and generate traceId

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <!-- 日志的格式化 -->
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
                <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%tid] [%thread] %-5level %logger{36} -%msg%n</Pattern>
            </layout>
        </encoder>
    </appender>

    <!-- https://skywalking.apache.org/docs/skywalking-java/latest/en/setup/service-agent/java-agent/application-toolkit-logback-1.x/  -->
    <!-- 通过grpc上报日志到skywalking oap-->
    <appender name="grpc-log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
                <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%tid] [%thread] %-5level %logger{36} -%msg%n</Pattern>
            </layout>
        </encoder>
    </appender>
    <!-- 设置 Appender -->
    <root level="INFO">
        <appender-ref ref="console"/>
        <appender-ref ref="grpc-log"/>
    </root>
</configuration>

Guess you like

Origin blog.csdn.net/Forbidden_City/article/details/132384535