Spring Cloud cognitive learning: introduction to Spring Cloud and use of Eureka

catalog

This is a series of Spring Cloud articles, which will not explain all the knowledge points. It is just based on the micro service scenario to gradually introduce the role and significance of common components, as well as the integration of scenario components. The knowledge of each component will not be explained too much, just common. The purpose is to have a basic understanding of the common components of Spring Cloud as quickly as possible. With the understanding, you can learn a component independently based on the scene you face, and gradually enrich your knowledge of Spring Cloud.

Introduction to Spring Cloud

  • Spring Cloud is a microservice architecture. It has a variety of components to manage all aspects of microservices. Spring cloud is a collection of frameworks for building microservice development and governance.
  • Spring Cloud is undoubtedly the most popular Java technology.
  • Official website

Introduction to microservices

  • What is microservice? Let's not go into details here. Application service has become a trend. Simply speaking, it is to split the internal functions of ALL-IN-ONE integrated application. For example, it can provide a service that can be called externally as a single SMS function, which not only provides the reusability of SMS service (other applications can also reuse this function), It also makes it possible to improve the load capacity of a function independently (if All In One wants to improve the load capacity of the function, deploying multiple servers to improve the load capacity of the function will also increase the load capacity of user registration, which wastes additional resources).
  • In the theory of microservice, in order to decouple, each microservice uses a separate database (of course, some people may think that the same name service uses the same database, and the concept of microservice is still controversial).
  • Martin Fowler on micro services

Reasons for Spring Cloud:

  • After you service the original application, you will encounter the management problems of these services, such as checking the availability of services, checking what services are available now, and how to balance the load of multiple services with the same name (the same function).
  • Spring Cloud, based on Spring Boot, provides a set of microservice solutions, including service registration and discovery, configuration center, full link monitoring, service gateway, load balancing, fuse and other components. These components are not all developed by spring itself. Some of them are open-source components, which spring encapsulates (Spring Cloud Netflix mainly comes from the open-source components of Netflix OSS, and Spring Cloud Alibaba is provided by ALI). Spring Cloud, like the starter of spinning boot, shields the complex configuration and enables us to develop microservices through simple configuration.

Common scenarios:

Spring Cloud can solve the following common scenarios (just list a few common scenarios for now, in fact, there are solutions for all aspects of microservices)

  • Service development: using Spring Boot to develop services is convenient and fast (Spring Boot is not actually an internal component of Spring Cloud, but only a family)
  • Service registration and discovery: mainly provided by Eureka, it is used to register the micro service to Eureka and let service consumers get the list of available micro services from Eureka. (of course, there are many other components used for service registration and discovery)
  • Load balancing: mainly provided by Ribbon, it is used for load balancing on the service consumer side, so as to balance requests to services with the same name.
  • API gateway: it is mainly provided by Zuul, which provides a unified service call entry. All service calls are called through Zuul, providing request forwarding, request filtering and other functions.
  • Fault tolerant processing of services -- circuit breaker: mainly provided by Hystrix, which is used to solve the problem of service fusing when calling microservices.
  • Distributed service configuration: mainly provided by Spring Cloud Config, it is used to solve the problem of unified configuration and distribution configuration of multiple microservices. (the configuration of a service can be pulled from the Config configuration center)
  • Data monitoring, message bus.......

Advantages and disadvantages of microservices:

Advantages:

  • After microservicing, the code tends to be simple and modular, which will be easier to understand. It's just like it's hard for you to build a proper mall, isn't it easy for you to build a registration function? 😀 Moreover, it is also convenient to manage after code modularization, for example, a department can be specially responsible for the development of a service; moreover, after code modularization and decoupling, new requirements can only be developed for a service.
  • A service is an independent server, which can be deployed independently and has low coupling with other services. (in All In One, you need to restart the whole server to change the registration function)
  • The service can be expanded dynamically. Since a service is an independent server, it can be expanded horizontally naturally, and multiple servers with the same name can be deployed.
  • . . .

inferiority:

  • The difficulty of operation and maintenance has increased. ALL IN ONE used to be a server. Now, due to the micro service, more than N servers are generated. The deployment and monitoring of these servers are all problems. (so this leads to the need for automatic deployment and monitoring.)
    • Take an accident I've heard about before as an example: a securities company is going to update a certain code, which results in the omission of a server on a computer. Then because of the problem of cooperation between the server and other services, the server keeps getting "automatic receipt". It can be understood that the merchants in the game automatically sweep the goods in the auction house at a low price.
  • The test is more difficult. If you have manually tested your own BUG, you should know that if one of your methods has been modified, then you should check whether the BUG may occur where this method is called. The same is true for service calls. If a service is modified, you should test all related services for security reasons. (so this leads to the need for automated testing)
    • If only for one end of the test, the test difficulty is reduced, but for the overall business process, the test difficulty is increased.
  • Of course, the problem of distributed transaction caused by distributed is also a headache.
  • (but such a popular technology, I believe everyone knows that its advantages are far greater than its disadvantages.)

Spring Cloud version problems

Version introduction

  • The version name of Spring Cloud does not use numbers like 1.0 as other projects do. It uses the name of London subway as the version name. It is said that this is because of the dependency between Spring Cloud and subprojects, in order to avoid the conflict and misunderstanding of the version name.
  • Following the version with SR (Service Release) indicates that this is a stable version, followed by a number indicating the iteration number, such as Hoxton.SR3

Corresponding relationship with Spring Boot version

  • The version compatibility of Spring Cloud and Spring Boot should be considered. The following is the corresponding relationship between Spring Cloud and Spring Boot.
  • Please note: Dalston and Edgware are spring boots corresponding to version 1.5, which cannot be used on version 2.0.
Release version (Metro name) Corresponding Spring Boot version
Hoxton 2.2.x
Greenwich 2.1.x
Finchley 2.0.x
Edgware 1.5.x
Dalston 1.5.x

At present, the latest version is Hoxton.SR3, but the domestic mainstream should be Finchley or Greenwich, so the following examples will take Finchley as an example. Note that the components in this version are basically version 2.0.0.

---Split line - premise of learning - split line---

The following will learn about the common components of Spring Cloud. If you continue to learn downward, make sure you have mastered the knowledge of Spring Boot

be careful:
💡 In the following study, only part of the code will be posted, and the rest of the code will be stored on github. The code will be committed step by step according to the learning of components. Therefore, you can compare the differences of each version of the code according to the differences of the code, and learn which code needs to be changed to add new components. (you can view the code update of each commit from the history to learn about the modification of new components What code is there) to make a deep impression. Of course, it's also important to do it yourself.

[PS: for the following code, I found out later that I wrote a wrong word Service, some of which was right, some of which was wrong, but it did not affect the code operation. 😓 It's mainly because the capitalization is not checked properly]

Basic project construction

  • Spring Cloud mainly focuses on service governance, and microservices are mainly developed by Spring Boot, so we first build a simple microservice project based on Spring Boot, and then learn Spring Cloud by gradually adding functions.

Please refer to the following example code: Basic construction of micro service project

1. Create a Maven parent project:

The creation method of the parent project is different in IDEA and Eclipse. Here, the IDEA and Eclipse can be self checked (just search Eclipse to create the parent project)



The directory structure of the parent project is as follows: ![20200408145332](https://progor.oss-cn-shenzhen.aliyuncs.com/img/20200408145332.png)

Add the following code to POM.XML of the parent project to lock the later dependent versions:

    <!--use dependencyManagement Lock dependent versions start-->
    <dependencyManagement>
        <dependencies>
            <!--Because it's gone sping boot starter As parent Engineering, need to use spring-boot-dependencies To achieve similar results-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.0.6.RELEASE</version>
                <!--However, it should be noted that the version here may be similar to spring cloud Conflict, because I chose Finchley,So here we use 2.0.6-->
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.4</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.47</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.0.31</version>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
                <version>1.2.3</version>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.17</version>
            </dependency>

        </dependencies>

    </dependencyManagement>
    <!--use dependencyManagement Lock dependent versions end-->

Note: when you create a new module under the parent project, the POM.xml of the parent project will add content:
In IDEA, when module is added under the parent project, the parent project automatically changes packaging to pom.

2. Create a common dependency package:

If you have studied maven's sub module development, you should know that some things that are dependent on multiple modules will be pulled into a single module, and then other modules can rely on this module. The common dependency package that contains the User entity (corresponding to the data table) is created below.


Right click 'new' - > 'module' on the parent project to create a new module 'spring cloud common data' under the parent project. Select Maven mode for the module. After naming the module, go all the way to next (or redefine the storage path of the module in the last step): ![20200408152755](https://progor.oss-cn-shenzhen.aliyuncs.com/img/20200408152755.png)

Create a User class:

package com.progor.study.entity;
// Notice which package the class is in.

public class User {
    private Integer id;
    private String username;
    private String fullName;

    public User() {
    }

    public User(Integer id, String username, String fullName) {
        this.id = id;
        this.username = username;
        this.fullName = fullName;
    }

    // Space consideration, omitting setter and getter code
}

Execute a section of SQL, and our later tests create data:

DROP DATABASE IF EXISTS cloud01;
CREATE DATABASE cloud01 CHARACTER SET UTF8;
USE cloud01;
CREATE TABLE user
(
  id int PRIMARY KEY AUTO_INCREMENT,
  username VARCHAR(255),
  fullName  VARCHAR(255)
);

INSERT INTO user(username,fullName) VALUES('zhangsan','Zhang San');
INSERT INTO user(username,fullName) VALUES('lisi','Li Si');
INSERT INTO user(username,fullName) VALUES('wangwu','Wang Wu');
INSERT INTO user(username,fullName) VALUES('zhaoliu','Zhao Liu');
INSERT INTO user(username,fullName) VALUES('lidazhuang','Li Dazhuang');

SELECT * FROM user;

3. Create a service provider:


3.1 right click 'new' - > 'module' on the parent project to create a new module 'spring cloud user service-8001' under the parent project. ![20200408145419](https://progor.oss-cn-shenzhen.aliyuncs.com/img/20200408145419.png)
![20200408145450](https://progor.oss-cn-shenzhen.aliyuncs.com/img/20200408145450.png)

3.2 introduce web development related dependency package:

    <dependencies>
        <!--Introduce public dependency package start-->
        <dependency>
            <groupId>com.progor.study</groupId>
            <artifactId>spring-cloud-common-data</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--Introduce public dependency package end-->
        <!--introduce web Development related package start-->
        <!--web modular-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--use jettey As default server-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <!--introduce web Development related package end-->
    </dependencies>

3.3. Create two interfaces based on spring boot (as well as Service and Mapper. As mentioned above, you need spring boot foundation, so you will not explain these by default):

The core code of the Controller is as follows:

// Because the json data is returned, I don't need to annotate @ ResponseBody. Add a RestController
@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/user/{id}")
    public User getUser(@PathVariable Integer id) {
        User user = userService.getUser(id);
        if (user == null) {
            throw new RuntimeException("The ID: " + id + "No corresponding user information");
        }
        return user;
    }

    @GetMapping("/user/list")
    public List<User> listUser() {
        List<User> users = userService.listUser();
        return users;
    }

}

Mapper Code:

@Mapper
public interface UserMapper {
    List<User> listUser();

    User getUser(Integer id);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.progor.study.dao.UserMapper">
    <select id="listUser" resultType="com.progor.study.entity.User">
        SELECT * FROM user
    </select>
    <select id="getUser" parameterType="Integer" resultType="com.progor.study.entity.User">
        SELECT * FROM user WHERE id =#{id}
    </select>

</mapper>

application.yml:

server:
  port: 8001

spring:
  datasource:
    # Configure data sources
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/cloud01
mybatis:
  # Global profile location:
  config-location: classpath:mybatis/mybatis-config.xml
  # Map file location:
  mapper-locations: classpath:mybatis/mapper/*.xml

Note that there is SQL execution above. Here, the data to be queried by mybatis is is obtained from cloud01 database.

Visit http://localhost:8001/user/list to test whether the interface can be called.

4. Create a service consumer

4.1: create module spring cloud user consumer 80

4.2: import dependency:

    <dependencies>
        <!--Introduce public dependency package start-->
        <dependency>
            <groupId>com.progor.study</groupId>
            <artifactId>spring-cloud-common-data</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--Introduce public dependency package end-->
        <!--introduce web Development related package start-->
        <!--web modular-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--jettey As default server-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>
    </dependencies>

4.3: create code:

application.yml Code:

server:
  port: 80

Visit http://localhost:80/user/list to test whether the interface of 8001 service can be called (80 has no business content, and it calls 8001 business).

Section summary

The above basic project construction should successfully realize that the service consumer calls the service of the service provider through the Http request.
Next, we will use Spring Cloud to add functions to this simple microservice project to explain the role of various components in microservices.
If you don't understand the above example, you'd better study it again and then look at the following.

Eureka service registration and discovery

introduce

  • Eureka. Eureka.
  • Eureka is used for service registration and discovery. Eureka is an open-source service registration and discovery component of Netflix, which is also integrated into the Spring Cloud Netflix module by Spring Cloud.
  • Registration and discovery of services solve the following problems:
    • Service registration: service registration enables multiple servers of the same service to use the same server name to register in the service registration center (for example, the SMS function has three servers A1, A2 and A3, but their names in the registration center are all SMS functions, When I need the SMS function, I can check the registration center and find that there are three servers I can call), so that I can manage the service uniformly in the service registration center and view the various states of the service.
    • Service discovery: service discovery should be based on service registration first. In the above simple example of invoking a service, you need to specify the URL path of the service provider, which is a very coupled behavior. A more appropriate way is to make it change, rather than a fixed value. How to change? After service registration, you can pull multiple service instance information of a service from the registry, and then get one of the service instances to resolve the URL of the service provider you need. In fact, the service instance we use each time can be different, so that the URL of the service provider becomes variable, and the following service instances with the same name can be changed Load balancing is also possible.
  • Eureka like service registration and discovery components: consumer, etcd, zookeeper.
  • Principle: Eureka is composed of Eureka Server and Eureka Client. Eureka Server is used to maintain the list of services (Registration Center). Service providers register their service information to Eureka Server through Eureka Client. Service consumers register their service information from Eureka Client through Eureka Client Pull the service registered in the server. After obtaining the service list, the service consumer will know the IP address and other information of the service, and can call the service through http.

Some people say that many people have begun to give up eureka. Why should we talk about it here?
Although it's old, it's still valuable as a reference for the company you've been in, and you don't know if the technology of the company you're in keeps pace with the times. Or what if I let you take over the project of transforming eureka?
Of course, to keep learning new technologies, consumer should be a good alternative at present, and I will write this later.

Simple steps

The following code can be referred to: Eureka easy to use steps


1. Import dependency of parent project:

1.1 modify the dependency of the parent project:
Now we start to learn about spring cloud. First, we add the dependency lock of spring cloud under pom.xml of the parent project to lock the version of our component:

            <!--locking spring cloud edition start-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.SR4</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--locking spring cloud edition end-->

1.2 modify the spring cloud Eureka server-7001 module dependency:
Then configure pom.xml of spring-cloud-eureka-server-7001 module. Since the previous parent project imported spring cloud dependencies, your Eureka here does not specify a version, but inherits the previously locked version.

    <dependencies>
        <!--Here's an old version eureka-server Depending on the package, pay attention to the new version of eureka The position has changed-->
        <!--<dependency>-->
            <!--<groupId>org.springframework.cloud</groupId>-->
            <!--<artifactId>spring-cloud-starter-eureka-server</artifactId>-->
        <!--</dependency>-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>


2. Create a new spring cloud Eureka server-7001 module:

2.1 new module spring cloud Eureka server-7001
As mentioned above, Eureka has a server and a client. The client is integrated with the service consumer and service provider. The server needs to be created separately. We need to create an Eureka Server separately.

2.2: create the main startup class code:

package com.progor.study;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;


@SpringBootApplication
@EnableEurekaServer //Use enable Eureka server to make the current server an Eureka server
public class EurekaServer7001Application {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServer7001Application.class, args);
    }
}

2.3 modify application.yml:

# Configure service port
server:
  port: 7001

# Configure eureka correlation
eureka:
  instance:
    hostname: localhost # Name of the eureka instance
  client:
    register-with-eureka: false # This option is "register yourself to the eureka server". Since it is the server itself, choose false
    fetch-registry: false # Whether to pull the service from the registry? Since it is the server itself, select false
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka / ා set the interaction address (registration address) of Eureka Server for service retrieval and service registration

2.4. Test access to Eureka Server:
After running the main program class, visit localhost:7001. If there is a display of eureka interface, the configuration of eureka server is successful.



3. Modify service provider

Configure eureka in the service provider spring cloud user service-8001 to register the service in eureka:
We modified the original spring cloud user service-8001 module:

3.1 modify pom.xml:

        <!--increase eureka Client dependency start-->
            <!--Dependencies for older versions:-->
        <!--<dependency>-->
            <!--<groupId>org.springframework.cloud</groupId>-->
            <!--<artifactId>spring-cloud-starter-eureka</artifactId>-->
        <!--</dependency>-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--increase eureka Client dependency end-->

3.2 modify the main program class userservice8001aapplication:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient // Enable Eureka Client
public class UserService8001Application {
    public static void main(String[] args) {
        SpringApplication.run(UserService8001Application.class, args);
    }
}

3.3 modify application.yml:

server:
  port: 8001

spring:
  datasource:
    # Configure data sources
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/cloud01
  application:
    name: UserSerive # Multiple services with the same function are registered with the application name application.name. As you can see in eureka, the application name becomes the service name
mybatis:
  # Global profile location:
  config-location: classpath:mybatis/mybatis-config.xml
  # Map file location:
  mapper-locations: classpath:mybatis/mapper/*.xml

# eureka configuration:
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka ා specify the eureka server interaction address
  instance:
    instance-id: UserService8001 # Current service instance name
    prefer-ip-address: true # Whether to use the IP address as the identification of the current service, some will use the host number, you can try to comment to see the effect
    # Since the pull service and whether to register itself to eureka are both true by default, there is no need to configure

3.4 run the main program class and check http://localhost:7001 to see if there is any information as follows:



4. Modify service consumers

Configure eureka in the service consumer so that the registered service can be obtained from eureka and called:
Modify the module spring cloud user consumer-80:
4.1 modify pom.xml:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

4.2 modify the main program class:

package com.progor.study;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient
public class UserConsumer80Application {
    public static void main(String[] args) {
        SpringApplication.run(UserConsumer80Application.class, args);
    }
}

4.3 modify application.yml:

server:
  port: 80

eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka
    register-with-eureka: false # Because it is not a service provider, it is not registered with eureka

4.4 modify AppConfig
Modify the Bean--RestTemplate and add @ LoadBalanced to enable the restTemplate to resolve the request address to the service name:

package com.progor.study.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class AppConfig {
    @Bean
    @LoadBalanced // In combination with this, eureka uses LoadBalanced to call the services registered in eureka
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

4.5 modify controller:

package com.progor.study.Controller;

import com.progor.study.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@RestController
public class UserController {
    // Note that this restTemplate needs to generate its own Bean. Refer to com.progor.study.config.AppConfig
    @Autowired
    private RestTemplate restTemplate;
    // Specifies the URL for remote access, which is the URL of the service provider
//    private static final String REST_URL_PREFIX = "http://localhost:8001";
    // 1. Comment the code that directly uses the URL to call the service,
    // 2. Use Eureka to call. The user service of "http: / / user service" below is the name of the service. You can see it on the Eureka page
    // 3. In this way, pull the list of services named userservice from eureka and select a service instance to call
    private static final String REST_URL_PREFIX = "http://USERSERIVE";

    @GetMapping("/user/{id}")
    public User getUser(@PathVariable Integer id) {
        return restTemplate.getForObject(REST_URL_PREFIX + "/user/" + id, User.class);
    }

    @GetMapping("/user/list")
    public List<User> listUser() {
        return restTemplate.getForObject(REST_URL_PREFIX + "/user/list", List.class);
    }

}

4.6 run the main program class and access the interface http://localhost/user/list to see if it can be accessed.
🟠 if your code is correct, it should be accessed normally. Notice that we don't write a fixed URL for the service consumer, so how does it access? He parsed it by pulling the list of services in eureka. [due to the possible delay of pull data sometimes, if it is not equal, it is better to start 70018001,80 in sequence]



💡 Here's a reminder: all of them are equipped with defaultZone. In fact, in the case of a single Eureka Server, Eureka The server's defaultZone can not be matched, because it has no meaning (but consumers and producers need to match). For service consumers and producers, as long as it runs, it can be obtained according to the IP (even if the above is not matched, it can also be accessed through http://localhost:7001/eureka). Consumers and producers do not care about Eureka The name of the server. He only cares about the address. But in a cluster, defaultZone has a unique meaning. Next.



Eureka cluster

There may be many services registered in Eureka, and service consumers pull the service list from Eureka Server. This load pressure may be great for Eureka, and since the service list is pulled from Eureka Server, Eureka Server is also very important. In order to ensure the robustness of Eureka Server, we usually build Eureka cluster.



Construction steps

The following code can be referred to: Eureka simple cluster experiment

1. Create three Eureka server modules,

spring-cloud-eureka-cluster-server-7002
spring-cloud-eureka-cluster-server-7003
spring-cloud-eureka-cluster-server-7004

2. Import all dependent packages:

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>

3. Modify the main startup class accordingly:

// spring-cloud-eureka-cluster-server-7002:
@SpringBootApplication
@EnableEurekaServer //Use enable Eureka server to make the current server an Eureka server
public class EurekaClusterServer7002Application {
    public static void main(String[] args) {
        SpringApplication.run(EurekaClusterServer7002Application.class, args);
    }
}
// spring-cloud-eureka-cluster-server-7003:
@SpringBootApplication
@EnableEurekaServer //Use enable Eureka server to make the current server an Eureka server
public class EurekaClusterServer7003Application {
    public static void main(String[] args) {
        SpringApplication.run(EurekaClusterServer7003Application.class, args);
    }
}
// spring-cloud-eureka-cluster-server-7004:
@SpringBootApplication
@EnableEurekaServer //Use enable Eureka server to make the current server an Eureka server
public class EurekaClusterServer7004Application {
    public static void main(String[] args) {
        SpringApplication.run(EurekaClusterServer7004Application.class, args);
    }
}


4. Modify host

A kind of This is because Eureka uses eureka.instance.name as the identification name in the Eureka cluster by default. When the host is not modified, there will be a problem:

  • If you use host as the eureka.instance.name of three servers, how can Eureka distinguish these three servers? No access to Eureka
  • In addition, when configuring the defaultZone, you cannot configure more than one with the same name. You can try to write down multiple localhost URL s with different ports in defaultZone.
  • Therefore, when setting up a cluster locally, you need to configure host.
127.0.0.1 eureka7001.com
127.0.0.1 eureka7002.com
127.0.0.1 eureka7003.com
127.0.0.1 eureka7004.com

5. Modify application.yml:

7002:

# Configure service port
server:
  port: 7002

# Configure eureka correlation
eureka:
  instance:
    hostname: eureka7002 # Name of the eureka instance
  client:
    register-with-eureka: false # This option is whether to register itself to the eureka server. Since it is the server itself, select false
    fetch-registry: false # Whether to pull the service from the registry? Since it is the server itself, select false
    service-url:
      defaultZone: http://eureka7003.com:7003/eureka/,http://eureka7004.com:7004/eureka / ා set the interaction address (registration address) of Eureka Server for service retrieval and service registration

7003:

# Configure service port
server:
  port: 7003

# Configure eureka correlation
eureka:
  instance:
    hostname: eureka7003 # Name of the eureka instance
  client:
    register-with-eureka: false # This option is whether to register itself to the eureka server. Since it is the server itself, select false
    fetch-registry: false # Whether to pull the service from the registry? Since it is the server itself, select false
    service-url:
      defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7004.com:7004/eureka / ා set the interaction address (registration address) of Eureka Server for service retrieval and service registration

7004:

# Configure service port
server:
  port: 7004

# Configure eureka correlation
eureka:
  instance:
    hostname: eureka7004 # Name of the eureka instance
  client:
    register-with-eureka: false # This option is whether to register itself to the eureka server. Since it is the server itself, select false
    fetch-registry: false # Whether to pull the service from the registry? Since it is the server itself, select false
    service-url:
      defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka / ා set the interaction address (registration address) of Eureka Server for service retrieval and service registration

A kind of Why is the address of another cluster node configured here, and you don't need to configure your own address?
First of all, it's not important to match yourself. Even if you don't, your service address is still there. Consumers and producers can still access eureka server through the port. What is configured here is the interaction address with other cluster nodes.



6. Start three server s to check the effect:

You can see that there are two other nodes in DS Replicas. The following figure is 7001.


7. Treatment of consumers and producers

If you want to register a service or pull a service at this time, the defaultZone should be changed to a clustered one:

Reference code: spring cloud user service 8002 Eureka cluster

7.1. Then you can see the services you registered in three eureka:

When a cluster service is configured and a node is hung up as a result, an error will be reported, but the service will not be affected.


Knowledge supplement:

  • Service renewal: every 30s, eureka checks the availability of the service.
  • Self protection: you can see that if you stop the service after registering it with eureka, the service will not be removed from eureka for a long time. This is eureka's self-protection mechanism, optimistic that the service will be available again soon.
  • Service rejection: if the Eureka Client (and if it is a service provider) 90s does not send heartbeat to Eureka Server, then Eureka Server will think that this service instance is no longer available, and delete it from the service list. [but it will not be deleted based on self-protection. ]

Add:

  • Eureka can enable Spring Security based security authentication to prevent anyone from retrieving services. This knowledge is not covered here. I will write it out separately (but for the time being, I'm interested in self checking.

Tags: Java Spring Mybatis xml MySQL

Posted on Thu, 14 May 2020 08:21:46 -0700 by misteryoji