SpringBoot integrates SpringCloud

created at 09-15-2021 views: 2

1. SpringCloud features

SpringCloud focuses on providing a good out-of-the-box experience for typical use cases and extension mechanisms to cover other situations:

  • Distributed/versioned configuration
  • Service registration and discovery Eureka
  • Routing Zuul
  • Service-to-service call
  • Load balancing Ribbon
  • Circuit breaker Hystrix
  • Distributed messaging

2. Three indicators of distributed system CAP

Before introducing the registry that SpringCloud uses by default, let's first introduce the three indicators of the distributed system, namely:

  • Consistency: Consistency. In a distributed system, all user read operations must return the latest value after the update operation is successfully executed; client writes and server synchronizes to the entire system;
  • Availability: Availability, as long as the user's request is received, the server must respond within a certain period of time, and the result of the response can be success or failure;
  • Partition tolerance: Partition tolerance, that is, inter-area communication may fail. In the case of network interruption and message loss, it still provides services to the outside; it is generally unavoidable. It can be considered that P in CAP is always established

CAP Theorem

The CAP law says that in a distributed computer system, the three guarantees of consistency C, availability A, and partition fault tolerance P cannot be satisfied at the same time, and at most two are satisfied:

Give up P
In order to avoid partition fault tolerance problems, one approach is to put all transaction-related data on a server. Although there is no guarantee that 100% of the system will be error-free, it will not encounter the negative effects brought about by partitions. , Such an approach will seriously affect the scalability of the system.

Give up A
Abandoning availability, once encountering a partition fault tolerance, the affected server needs to wait for a certain period of time, which will cause the system to be unable to provide services to the outside during the waiting period.

Give up C
The abandonment of consistency here is not to completely abandon the consistency of the data, but to abandon the strong consistency of the data, and retain the final consistency of the data. Taking online shopping as an example, if there is only one item in stock, if two orders are received at the same time, the later order will be notified that the item is out of stock.

3. Eureka

basic introduction

Eureka is officially recommended by SpringCloud for service registration and discovery, a REST-based service

SpringBoot implements the integration of Netflix OSS. One of the reasons for using Eureka is because it can use other components of Spring Cloud Netflix: intelligent routing (Zuul), client load balancing (Ribbon), etc.

basic component

Eureka is composed of multiple Instances (service instances), divided into Eureka Server and Eureka Client

Among them, Eureka Client can be subdivided into: Service Provider, Service Consumer

  • Eureka Server: server side, providing service registration and discovery;
  • Eureka Client: Client
    • Service Provider: service provider, register its own service to Eureka, let consumers find
    • Service Consumer: The service consumer obtains the list of registered services from Eureka to consume services

Eureka and Zookeeper

1) From the perspective of CAP theory

Zookeeper: ZK guarantees CP and highlights strong consistency, but cannot guarantee the availability of services every time it is accessed. For example, ZK will have such a situation: when the master node loses contact with other nodes due to a network failure, the remaining nodes will re-elect the leader. During the ZK election leader, the entire ZK cluster was unavailable, which caused the registration service to be paralyzed during the election. In a cloud deployment environment, it is a high probability that the ZK cluster will lose the master node due to network problems. Although the service will eventually recover, the long-term unavailability of registration caused by the long election time is intolerable.

Eureka: Eureka guarantees AP, and Eureka prioritizes availability during design. For the nodes in Eureka, each node is equal, and the failure of several nodes will not affect the work of normal nodes, and the remaining nodes can still provide registration and query services. However, Eureka does not guarantee strong consistency, that is, the information found may not be the latest. In addition, Eureka also has a self-protection mechanism. If more than 85% of the nodes do not have a normal heartbeat within 15 minutes, then Eureka will think that the client and registry have a network failure, but it will ensure that the current node is still available. Like ZK, the entire registration service is paralyzed.

2) From the point of view of the division of labor between nodes

Zookeeper: The nodes in the ZK cluster are divided into three categories and undertake different tasks

Leader: The only scheduler and processor for transaction requests (except for query requests)
Follower: Process non-transaction requests and participate in Leader election voting
Observer: Processing non-transactional requests, but not participating in Leader election voting
Eureka: Each node in the Eureka cluster is equal, and each node plays the same role. They perceive each other's existence by registering with each other. When the registration message is received, they will be synchronized to other nodes in the cluster.

4. SpringCloud Demo

Demo overall structure (parent-child project)

SpringCloud Demo

  • api: Bean, DTO, POJO, etc. and Service interface
  • controller: service consumer, front-end interaction
  • provider: service provider, service implementation
  • registry: Service registry

registry

1) pom.xml

The key point is to import eureka server dependencies and SpringCloud dependencies

<dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-eureka-server -->
        <!-- eureka server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR6</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

2) application.properties

Configure the Eureka server

spring.application.name=SpringCloudDemoRegistry

# server port, I like it
server.port=8888

# Eureka Server service url and default zone, the end must be eureka
eureka.client.service-url.defaultZone= http://127.0.0.1:8888/eureka/

# Eureka's self-protection mechanism, false is recommended in the k8s environment
eureka.server.enable-self-preservation=false

# false means that the own end is the registration center, my function is to maintain the service instance, no need to obtain the registered service information from the server
eureka.client.fetch-registry=false

# false means not to register yourself to Eureka Server
eureka.client.register-with-eureka=false

3) EurekaregistryApplication

Use @EnableEurekaServer to activate the relevant configuration and make the registry module as the registry server

@EnableEurekaServer // Declared as a registry server
@SpringBootApplication
public class EurekaregistryApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaregistryApplication.class, args);
    }
}

api

1) entity

The entity class takes department and user information as an example. Because the demonstration uses Lombok province code, it is used to implement basic CRUD

Department.class

@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Department {
    private Long id;
    private Integer dId;
    private String dName;
    private Date updateTime;
}

UserInfo.class

@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {
    private Long id;
    private Integer uId;
    private Integer dId;
    private String uName;
    private String uPhone;
    @Email(message = "Illegal mail format") //Validator format verification
    private String uEmail;
    private String uAddress;
    private Date updateTime;
    private Department department;
}

2)UserService

UserService is the service interface, which declares the methods that need to be provided and consumed, and writes a few simple queries

public interface UserService {

    /**
     * Judge whether the user exists, 0 means it does not exist, and if the return value is equal to uId, it exists
     * @param uId
     * @return
     */
    Integer userExist(Integer uId);

    /**
     * Get user's basic personal information
     * @param uId
     * @return
     */
    UserInfo getUserInfo(Integer uId);

    /**
     * Get user's personal details
     * @param uId
     * @return
     */
    UserInfo getUserDetailsInfo(Integer uId);
}

provider

1) pom.xml

The key point is to introduce eureka client dependencies, openfeign dependencies, and SpringCloud dependencies

<dependencies>
        <!-- Springboot's dependency is omitted... -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

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

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR6</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
</dependencyManagement>

2) application.properties

Configure Eureka, Mybatis, and DataSource data sources and other information

spring.application.name=SpringCloudDemoProvider

# Server port
server.port=9999

# Eureka service url
eureka.client.service-url.defaultZone= http://127.0.0.1:8888/eureka/
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true

# Mybatis
mybatis.mapper-locations = classpath:com.maziyao.provider.mapper/*.xml
mybatis.type-aliases-package= com.maziyao.common.entity

# DataSource data source configuration
spring.datasource.type=com.zaxxer.hikari.HikariDataSource

# DataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/boot-demo?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root

3) EurekaproviderApplication

The provider startup class uses @EnableEurekaClient to declare it as an EurekaClient client and as a ServiceProvider

@EnableEurekaClient
@SpringBootApplication
@EnableAspectJAutoProxy
@MapperScan("com.maziyao.provider.mapper")
@ComponentScan(basePackages = {
        "com.maziyao.provider.rest",
        "com.maziyao.provider.redis",
        "com.maziyao.provider.service",
        "com.maziyao.provider.config"
})
public class EurekaproviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaproviderApplication.class, args);
    }
}

4) service

UserServiceImpl as the UserService interface implementation class, @Service is used to annotate business layer components

The mapper interface of the mapper layer is automatically injected and called. The SQL statement of the mapper is omitted below, which is very simple

It should be noted that for the data access layer component mapper, use @Repository for annotation

@Service("userService")
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public Integer userExist(Integer uId) {
        return userMapper.userExist(uId);
    }

    @Override
    public UserInfo getUserInfo(Integer uId) {
        return userMapper.getUserInfo(uId);
    }

    @Override
    public UserInfo getUserDetailsInfo(Integer uId) {
        return userMapper.getUserDetailsInfo(uId);
    }
}

5) rest

The focus is on UserServer under the rest package. You must know that Eureka is a REST-based service

Use @RestController to annotate and declare as userServer, this is SpringBoot annotation, used to annotate control layer components

5) rest

The focus is on UserServer under the rest package. You must know that Eureka is a REST-based service

Use @RestController to annotate and declare as userServer, this is SpringBoot annotation, used to annotate control layer components

consumer

1)pom.xml

The EurekaClient dependency also needs to be imported in the pom.xml of the Controller, which is Client for both Provider and Controller

<dependencies>
        <!-- SpringBoot dependency omitted... -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>

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

2)application.properties

Configure Eureka related information in application.properties

spring.application.name=springCloudDemoController

# Server port
server.port=8899

# Registry URL
eureka.client.service-url.defaultZone= http://127.0.0.1:8888/eureka/
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true

3) EurekacontrollerApplication

Consistent with the startup class of the Provider, declare that the startup class is the client of Eureka

And use @EnableFeignClients to turn on Feign, a declarative web service client

@EnableEurekaClient
@EnableFeignClients
@SpringBootApplication
@EnableAspectJAutoProxy
@ComponentScan({
        "com.maziyao.controller.config",
        "com.maziyao.controller.controller",
        "com.maziyao.controller.rest"
})
public class EurekacontrollerApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekacontrollerApplication.class, args);
    }

}

4) rest

The controller serves as the front-end interaction layer, that is, the control layer, where UserClient declares the calling method

Use @FeignClient to declare the spring.application.name configured by the service provider in application.properties

And the @RestController("userServer") that binds the service provider to the UserServer class under the rest package

@FeignClient(name = "springCloudDemoProvider",contextId = "userServer")
public interface UserClient {

    @ResponseBody
    @RequestMapping(value = "/exist",method = RequestMethod.GET)
    public Integer existUserByUid(@RequestParam("uId")Integer uId);

    @ResponseBody
    @RequestMapping(value = "/userInfo",method = RequestMethod.GET)
    public UserInfo getUserInfo(@RequestParam("uId")Integer uId);

    @ResponseBody
    @RequestMapping(value="/userDetailsInfo",method = RequestMethod.GET)
    public UserInfo getUserDetailsInfo(@RequestParam("uId")Integer uId);

}

5) UserController

Control layer, use @RestController annotation, and inject UserClient to call

@RestController
public class UserController {

    private static final Logger logger = LoggerFactory.getLogger(UserController.class);

    @Autowired
    private UserClient userClient;

    @ResponseBody
    @RequestMapping(value = "/exist",method = RequestMethod.GET)
    public Integer existUserByUid(@RequestParam("uId") Integer uId){
        return userClient.existUserByUid(uId);
    }

    @ResponseBody
    @RequestMapping(value = "/userInfo",method = RequestMethod.GET)
    public UserInfo getUserInfoByUid(@RequestParam("uId")Integer uId){
        return userClient.getUserInfo(uId);
    }

    @ResponseBody
    @RequestMapping(value = "/userDetailsInfo",method = RequestMethod.GET)
    public UserInfo getUserDetailsInfoByUid(@RequestParam("uId")Integer uId){
        return userClient.getUserDetailsInfo(uId);
    }

}

4.5 POSTMAN
Note: Finally, remember to mvn install, you need to run the registry first, and then run the provider and controller separately

Start the registry:

POSTMAN

start provider

start provider

start consumer

result

result

created at:09-15-2021
edited at: 09-15-2021: