Spring cloud -- eureka local cluster construction and load balancing invocation of microservices

Keywords: Spring Cloud eureka

What is service governance?
Spring Cloud encapsulates the Eureka module developed by Netflix to realize service governance
In the traditional rpc remote invocation framework, it is complex to manage the dependency between each service. Therefore, it is necessary to use service governance to manage the dependency between services. Service invocation, load balancing, fault tolerance, etc. can be realized, and service discovery and registration can be realized!

What is service registration and discovery
Eureka adopts the design architecture of CS. Eureka Server is the server of service registration function, and it is the service registration center. Other microservices in the system use Eureka's client to connect to Eureka Server and maintain heart
Skip connection. In this way, the system maintenance personnel can monitor the normal operation of various services in the system through Eureka Server.
In service registration and discovery, there is a registry. When the server starts, it will register its current server information, such as service address and communication address, in the registry by alias. Other party (consumer) service provision
Get the actual service communication address from the registry in the way of this alias, and then implement the local RPC call. The core design idea of RPC remote call framework: the registry is used to manage each service and service
A dependency between services (service governance concept). In any rpc remote framework, there will be a registry (storing information related to the service address (interface address))  

Eureka consists of two components: Eureka Server and Eureka Client
Eureka Server provides service registration services:
After each micro service node is started through configuration, it will be registered in EurekaServer. In this way, the service registry in EurekaServer will store the information of all available service nodes, and the information of service nodes can be seen intuitively in the interface.


EurekaClient is accessed through the registry:
It is a Java client to simplify the interaction of Eureka Server. The client also has a built-in load balancer using round robin load algorithm. After the application starts, a heartbeat will be sent to Eureka Server. The default cycle is 30 seconds. If Eureka Server does not receive the heartbeat of a node in multiple heartbeat cycles, Eureka Server will remove the service node from the service registry (90 seconds by default).

https://www.cnblogs.com/dalianpai/p/12263438.html

We directly use eureka to build a service registration and discovery cluster to realize the function of microservice invocation

1. Create a maven parent project (spring cloud)

<!--unified management  jar Package version-->
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <junit.version>4.12</junit.version>
    <lombok.version>1.18.10</lombok.version>
    <log4j.version>1.2.12</log4j.version>
    <mysql.version>8.0.18</mysql.version>
    <druid.version>1.1.10</druid.version>
    <mybatis.spring.boot.version>1.3.2</mybatis.spring.boot.version>
  </properties>

  <!--After the sub module inherits, it provides the following functions: locking the version+son module Do not write groupId and version-->
  <dependencyManagement>
    <dependencies>
      <!--spring boot 2.2.2-->
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>2.2.2.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      <!--spring cloud Hoxton.SR1-->
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Hoxton.SR1</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      <!--spring cloud alibaba-->
      <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-dependencies</artifactId>
        <version>2.1.0.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      <!--mysql-->
      <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>${mysql.version}</version>
        <scope>runtime</scope>
      </dependency>
      <!-- druid-->
      <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>${druid.version}</version>
      </dependency>

      <!--mybatis-->
      <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>${mybatis.spring.boot.version}</version>
      </dependency>
      <!--junit-->
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>${junit.version}</version>
      </dependency>
      <!--log4j-->
      <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>${log4j.version}</version>
      </dependency>
    </dependencies>

  </dependencyManagement>

2. Create three eureka services (cloud eureka server7001, cloud eureka server7002 and cloud eureka server7003):

Main startup class: the other two will not be posted

@EnableEurekaServer //Indicates that this project is eureka's service registry
@SpringBootApplication
public class EurekaMain7001 {
    public static void main(String[] args) {
        SpringApplication.run(EurekaMain7001.class, args);
    }
}

pom.xml

<dependencies>
        <!-- eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--monitor-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- General configuration -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

application.yml the other two will not be posted. Change the port and defaultZone

server:
  port: 7001

eureka:
  instance:
    hostname: eureka7001.com  #Instance name of eureka server
  client:
    #false means you don't register yourself with the registry (you can register if you want, but it's not necessary)
    register-with-eureka: false
    #false means that the client is the registry, whose responsibility is to maintain service instances and does not need to retrieve services
    fetch-reapplication.ymlgistry: false
    service-url:
      #Setting the address query service and registration service that interact with Eureka server depends on this address
      #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
      #Cluster versions register and watch each other
      defaultZone: http://eureka7002.com:7002/eureka/, http://eureka7003.com:7003/eureka/

      #    defaultZone is a fixed writing method. If you want to customize it, you need to write it as follows:
      #    region: eureka-server
      #    availability-zones:
      #      eureka-server: server1,server2
      #    service-url:
      #      server1: http://eureka7002.com:7002/eureka/
      #      server2: http://eureka7003.com:7003/eureka/

  server:
    #Turn off self-protection. The default value is true
    enable-self-preservation: false
    #Heartbeat interval, in milliseconds
    eviction-interval-timer-in-ms: 2000

  Modify the following hosts file:

  3. Building consumers and service providers:

3.1. Create an entity middleware project cloud API Commons:

The package path is:

com.cjian.springcloud.bean
public class CommonResult<T> {

    private Integer code;
    private String message;
    private T data;

    public CommonResult(Integer code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public CommonResult(Integer code, String message){
        this(code, message, null);
    }

    public CommonResult() {
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}
public class Payment implements Serializable {

    private Long id;
    private String serial;


    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getSerial() {
        return serial;
    }

    public void setSerial(String serial) {
        this.serial = serial;
    }
}

3.2. Build two service providers  

cloud-provider-payment8001,cloud-provider-payment8002
<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.cjian.springloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>

        <!-- alibaba of druid Database connection pool -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <!--mysql-connector-java-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.18</version>
        </dependency>
        <!--jdbc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

application.yml

server:
  port: 8001

spring:
  application:
    name: cloud-payment-service
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource      # Current data source operation type
    driver-class-name: com.mysql.cj.jdbc.Driver       # mysql driver package
    url: jdbc:mysql://127.0.0.1:3306/mysql?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
    username: root
    password: 123456

mybatis:
  mapperLocations: classpath:mapper/*.xml
  type-aliases-package: com.cjian.springcloud.bean    # Package of all Entity alias classes


eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      #defaultZone: http://localhost:7001/eureka
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7001.com:7002/eureka,http://eureka7001.com:7003/eureka

  instance:
    instance-id: payment8001
    prefer-ip-address: true   #The access path can display the ip address

  #The time interval between Eureka client sending heartbeat to server, unit: seconds (default: 30 seconds)
  lease-renewal-interval-in-seconds: 1
  #The upper limit of waiting time for Eureka server after receiving the last heartbeat, in seconds (90 seconds by default), and the timeout service is excluded
  lease-expiration-duration-in-seconds: 2

Package path: com.cjian.springcloud

@Mapper
public interface PaymentDao {

    public int create(Payment payment);

    public Payment getPaymentById(@Param("id") Long id);
}
public interface  PaymentService {
    public int create(Payment payment);

    public Payment getPaymentById(@Param("id") Long id);
}
@Service
public class PaymentServiceImpl implements PaymentService {
    @Resource
    private PaymentDao paymentDao;

    public int create(Payment payment)
    {
        return paymentDao.create(payment);
    }

    public Payment getPaymentById(Long id)
    {
        return paymentDao.getPaymentById(id);
    }
}
@RestController
public class PaymentController {
    @Resource
    private PaymentService paymentService;

    @Value("${server.port}")
    private String serverPort;

    @PostMapping(value = "/payment/create")
    public CommonResult create(@RequestBody Payment payment)
    {
        int result = paymentService.create(payment);
        System.out.println(("*****Insert result:" + result));

        if(result > 0)
        {
            return new CommonResult(200,"Insert database succeeded,serverPort: "+serverPort,result);
        }else{
            return new CommonResult(444,"Insert database failed",null);
        }
    }

    @GetMapping(value = "/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id)
    {
        Payment payment = paymentService.getPaymentById(id);

        if(payment != null)
        {
            return new CommonResult(200,"query was successful,serverPort:  "+serverPort,payment);
        }else{
            return new CommonResult(444,"No corresponding record,query ID: "+id,null);
        }
    }
}
<?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.cjian.springcloud.dao.PaymentDao">

    <resultMap id="BaseResultMap" type="com.cjian.springcloud.bean.Payment">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <id column="serial" property="serial" jdbcType="VARCHAR"/>
    </resultMap>

    <insert id="create" parameterType="com.cjian.springcloud.bean.Payment" useGeneratedKeys="true" keyProperty="id">
        insert into payment(serial)  values(#{serial});
    </insert>
    <select id="getPaymentById" parameterType="Long" resultMap="BaseResultMap">
        select * from payment where id=#{id};
    </select>

</mapper>

Main startup class:

here

@SpringBootApplication
//@EnableEurekaClient is OK without this annotation. We'll talk about it when we analyze the eureka principle
public class PaymentMain001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain001.class, args);
    }
}

Create table sql:

CREATE TABLE `payment`(
	`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
   `serial` varchar(200) DEFAULT '',
	PRIMARY KEY (id)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4

The other service provider will not repeat~

4. Build a consumer   cloud-consumer-order80 :

@Configuration
public class ApplicationContextConfig {
    //Add a RestTemplate to the container
    //RestTemplate provides a variety of convenient ways to access remote http access
    @Bean
    @LoadBalanced//Turn on the load balancing function
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}
@RestController
public class OrderController {

    // public static final String PAYMENT_URL = "http://localhost:8001";
     public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";

    @Resource
    private RestTemplate restTemplate;

    //Because the browser only supports get requests, get is used here for convenience
    @GetMapping("/consumer/payment/create")
    public CommonResult<Payment> create(Payment payment){
        System.out.println("********Inserted data:" + payment);
        //postForObject has three parameters: request address, request parameter and returned object type
        return restTemplate.postForObject(PAYMENT_URL + "/payment/create", payment, CommonResult.class);
    }

    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult<Payment> getPayment(@PathVariable("id") Long id){
        System.out.println("********Inquired id: " + id);
        //getForObject has two parameters: request address and returned object type
        return restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
    }

}

 application.yml

#When visiting a website, the default is port 80. If you give the user port 80, the user can directly access the page without port
server:
  port: 81

spring:
  application:
    name: cloud-order-service

eureka:
  client:
    register-with-eureka: true
    etch-registry: true
    service-url:
      #defaultZone: http://localhost:7001/eureka
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7001.com:7002/eureka,http://eureka7001.com:7003/eureka

  instance:
    instance-id: consumer81
    prefer-ip-address: true   #The access path can display the ip address

  #The time interval between Eureka client sending heartbeat to server, unit: seconds (default: 30 seconds)
  lease-renewal-interval-in-seconds: 1
  #The upper limit of waiting time for Eureka server after receiving the last heartbeat, in seconds (90 seconds by default), and the timeout service is excluded
  lease-expiration-duration-in-seconds: 2

Main startup class:

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

Test function

Start three registries, consumers and two service providers in turn, and visit localhost:7001

visit    http://localhost:81/consumer/payment/get/3

Visit again:

At the end of the foreplay, the focus of this time, the key functions of eureka and source code analysis: the length is too long. See the next article~

Posted by Naki-BoT on Tue, 07 Sep 2021 13:04:24 -0700