Eureka service registration and discovery in spring cloud

1. Eureka Basics

1.1 what is service governance?

In the traditional rpc remote invocation framework, it is complex to manage the dependency relationship between each service and service, so it is necessary to use service governance to manage the dependency relationship between services, so as to realize service invocation, load balancing, fault tolerance, service discovery and registration.

  • Spring cloud encapsulates the Eureka module developed by Netflix to realize service governance.

1.2. What is service registration and discovery?

  • Eureka Server is the server of service registration function. It is the service registration center. Other microservices in the system use Eureka's client to connect to Eureka Server and maintain heartbeat connection. In this way, the maintenance personnel of the system can monitor whether each micro service of the system is running normally through Eureka Server.

Service registration and discovery

In service registration and discovery, there is a registry. When the server starts, it will register its current server information, such as service address, communication address, etc. in the registration center in the form of alias. The other party (consumer and service provider) obtains the actual service communication address from the registry in the way of this alias, and then implements the local RPC to call RPC. The core design idea of the remote invocation framework: the registry is used to manage a dependency between each service and services (service governance concept). In any RPC remote framework, there will be a registry (storing service address related information (interface address)).

1.3 Eureka two major components

Eureka consists of two components: Eureka Server and Eureka Client.

  • Eureka Server: provides service registration service. After each micro service node is started through configuration, the information of all available service nodes will be stored in the service registry in Eureka Server, and the information of service nodes can be seen intuitively in the interface.
  • Eureka Client: access 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

2. Steps for building a stand-alone Eureka

1. Build Module

  • The name is cloud Eureka server7001

2. Change POM

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud02</artifactId>
        <groupId>com.xiao</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>


    <artifactId>cloud-eureka-server7001</artifactId>

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

        <dependency>
            <groupId>com.xiao</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>

    </dependencies>
</project>


3. Change YML

server:
  port: 7001

eureka:
  instance:
    hostname: localhost  #Instance name of eureka server
  client:
    #I don't register myself with the registry
    register-with-eureka: false
    #It means that it is the registry. Its responsibility is to maintain service instances and does not need to retrieve services
    fetch-registry: false
    service-url:
      #This address is required for setting the address query service and registration service interacting with eureka server
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

4. Main startup

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

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

5. Test results

6. Screenshot of package structure

3. Payment module settled in Eureka Server

1. Build Module

  • The payment module has been written earlier and can be used directly. The name is cloud provider payment8001.

2. Change POM

New content

	  	<!--Newly added dependencies-->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

3. Change YML

New content

# Newly added content
eureka:
  client:
    # Identify yourself to be stationed in Eureka Server
    register-with-eureka: true
    fetchRegistry: true
    service-url:
      defaultZone: http://localhost:7001/eureka

4. Main startup

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

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

5. Test results

4. Order module settled in Eureka Server

1. Build Module

  • The order module has been written earlier and can be used directly. The name is cloud-consumer-order80.

2. Change POM

New content

    	<!--Newly added dependencies-->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>


3. Change YML

New content

spring:
  application:
    name: cloud-order-service

eureka:
  client:
    register-with-eureka: true
    fetchRegistry: true
    service-url:
      defaultZone: http://localhost:7001/eureka

4. Main startup

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

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

5. Test results

5. Cluster Eureka construction

5.1 Eureka working principle

  1. Start the eureka registry first
  2. Start payment service of service provider
  3. After the payment service is started, it will register its own information (such as the service address in eureka by alias)
  4. When the consumer order service needs to call the interface, it uses the service alias to get the actual RPC remote call address from the registry.
  5. After the consumer obtains the call address, the bottom layer actually uses HttpClient technology to realize remote call.
  6. After obtaining the service address, the consumer will cache it in the local jvm. By default, the service call address is updated every 30 seconds.

5.2 description of Eureka cluster principle

  • Multiple Eureka servers register with each other, watch each other, and present an Eureka service externally, so as to achieve high availability.

5.3 steps of Eureka cluster construction

1. Preparation

Modify the corresponding mapping file in the host

The content added is

127.0.0.1  eureka7001.com
127.0.0.1  eureka7002.com

2. Build Module

  • Create a new Module named cloud Eureka server7002.

3. Change POM

  • The pom file of cloud Eureka server7002 remains unchanged, and the pom file of cloud Eureka server7002 is the same as that of cloud Eureka server7001.

4. Change YML

  • YML file of cloud Eureka server7001
server:
  port: 7001

eureka:
  instance:
    hostname: eureka7001.com    #Instance name of eureka server
  client:
    register-with-eureka: false    #I don't register myself with the registry
    fetch-registry: false   #It means that it is the registry. Its responsibility is to maintain service instances and does not need to retrieve services
    service-url:
      defaultZone: http://eureka7002.com:7002/eureka / # set the address on which the query service and registration service interact with eureka server depend
 
 
  • YML file of cloud Eureka server7002
server:
  port: 7002

eureka:
  instance:
    hostname: eureka7002.com #Instance name of eureka server
  client:
    register-with-eureka: false    #I don't register myself with the registry
    fetch-registry: false   #It means that it is the registry. Its responsibility is to maintain service instances and does not need to retrieve services
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka / # set the address on which the query service and registration service interact with eureka server depend
 
 

5. Main startup

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

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

6. Test results


5.4. Settle the payment module in Eureka Server

Modify the yml file as follows

server:
  port: 8001


spring:
  application:
    name: cloud-payment-service
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: org.gjt.mm.mysql.Driver
    url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456

eureka:
  client:
    # Identify yourself to be stationed in Eureka Server
    register-with-eureka: true
    fetchRegistry: true
      #defaultZone: http://localhost:7001/eureka Stand alone version
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #Cluster version


mybatis:
  mapperLocations: classpath:mapper/*.xml
  type-aliases-package: com.xiao.cloud.entities



5.5. Place the order module in Eureka Server

Modify the yml file as follows

server:
  port: 80


spring:
  application:
    name: cloud-order-service

eureka:
  client:
    register-with-eureka: true
    fetchRegistry: true
    service-url:
      #defaultZone: http://localhost:7001/eureka Stand alone version
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #Cluster version



5.6. Cluster building steps of payment service providers

1. Create a new Module named cloud provider payment8002

  • The only difference from cloud provider payment8001 is that the port number of the yml file is 8002.

2. Modify the controller class of the payment module

import com.xiao.cloud.entities.CommonResult;
import com.xiao.cloud.entities.Payment;
import com.xiao.cloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

@RestController
@Slf4j
public class PaymentController {

    @Autowired
    private PaymentService paymentService;

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

    @PostMapping("/payment/create")
    public CommonResult create(@RequestBody Payment payment){
        int result = paymentService.create(payment);
        log.info("*****The insertion result is:" + result);
        if(result > 0){
            return new CommonResult(200,"Insert database succeeded,The port number is:" + ServerPort,result);
        }else {
            return new CommonResult(444,"Insert database failed",null);
        }
    }

    @GetMapping("/payment/get/{id}")
    public CommonResult getPaymentById(@PathVariable("id") Long id){
        Payment payment = paymentService.getPaymentById(id);
        log.info("*****The query result is:" + payment);
        if(payment != null){
            return new CommonResult(200,"Query database succeeded,The port number is:" + ServerPort,payment);
        }else {
            return new CommonResult(444,"Failed to query the database. There is no corresponding record, id Is:" + id,null);
        }
    }
}

  • When querying, the port number is also output.
  • Except for the above modifications, other parts are the same as cloud provider payment8001.

3. Modify the URL in the controller class of the order module

public static final String URL = "http://CLOUD-PAYMENT-SERVICE";
  • Here we access it by the name of the microservice.

4. Modify the configuration class of the order module

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 ApplicationContextConfig {

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

  • An additional @ LoadBalanced annotation is added to achieve load balancing.

5. Test results

The order module is used to call the payment module for many times, and the port number of each call is different. So as to realize load balancing.

5.7. Improvement of actor micro service information

Add the following contents to the yml configuration files of cloud provider payment8001 and cloud provider payment8002

eureka:
  instance:
    instance-id: payment8001 # If it is cloud provider payment8002, it is payment8002 here
    prefer-ip-address: true
  • Modify the service name.
  • And there is ip display when accessing.

5.8. Service Discovery configuration

1. Purpose

  • We can obtain the relevant details of the service through the Discovery configuration.

2. Newly added content on Controller class

    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("/payment/discovery")
    public Object discovery(){
        List<String> services = discoveryClient.getServices();
        for (String service : services) {
            log.info("*****Services:" + service);
        }

        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        for (ServiceInstance instance : instances) {
            log.info("****Details:" + instance.getServiceId() + "\t" + instance.getHost() + "\t" + instance.getPort() + "\t" + instance.getUri());
        }
        return this.discoveryClient;
    }

3. Add a new annotation on the main startup class

@EnableDiscoveryClient

4. Test results

5.9 Eureka self protection

5.9.1 phenomena

5.9.2 contents of self-protection mechanism

  • Bottom line: when a microservice is unavailable at a certain time, Eureka will not clean it immediately, but will still save the information of the microservice.
  • It belongs to the AP branch in the CAP.
  • Self protection mechanism is a security protection measure to deal with network abnormalities.

5.9.3 why do we need a self-protection mechanism?

  • In order to prevent Eureka client from working normally, but when the network with Eureka server is disconnected, Eureka server will not immediately remove Eureka client service.

5.9.4 how to protect yourself?

Add the following contents to Eureka server yml file

eureka:
  server:
    enable-self-preservation: false
    eviction-interval-timer-in-ms: 2000
	

Add the following content to Eureka client yml file

eureka:
  instance:
  # The time interval between Eureka client sending heartbeat to server, in seconds
    lease-expiration-interval-in-seconds: 1
  #The upper limit of waiting time of Eureka server after receiving the last heartbeat, in seconds. If it times out, the service will be excluded
    lease-expiration-duration-in-seconds: 2
	

Keywords: Java Spring Cloud Microservices eureka

Added by billynastie2007 on Thu, 06 Jan 2022 03:40:13 +0200