[Spring Cloud Netflix] 02--Eureka registration and discovery

Keywords: Spring Spring Cloud eureka

1, Preparatory work

1. Create configuration center

Create a moudle for spring boot


Select Eureka Server

Modify pom.xml file

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud1</artifactId>
        <groupId>com.drhj</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.drhj</groupId>
    <artifactId>sp05-eureka</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>sp05-eureka</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <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-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.yml configuration

Because at present, it is only for a single server. It does not register with itself or pull from itself. So turn off self-protection mode

spring:
  application:
    name: eureka-server
server:
  port: 2001
#Turn off self-protection mode
#host name
#For a single server, do not register with yourself or pull from yourself
eureka:
  server:
    enable-self-preservation: false
  instance:
    hostname: eureka1
  client:
    register-with-eureka: false
    fetch-registry: false

  • eureka cluster servers are distinguished by hostname
  • eureka.server.enable-self-preservation
    eureka's self-protection status: does the rate of heartbeat failure exceed 85% within 15 minutes? If it exceeds, Eureka Server will protect the current instance registration information and prompt a warning. Once in the protection mode, Eureka Server will try to protect the information in its service registry and will not delete the data in the service registry. That is, no micro services will be logged off
  • eureka.client.register-with-eureka=false
    Do not register with yourself
  • eureka.client.fetch-registry=false
    Do not pull registration information from itself
  • eureka.instance.lease-expiration-duration-in-seconds
    After the last heartbeat, how long is the interval between determining that the microservice is unavailable? 90 by default

Add @ EnableEurekaServer

Add in startup class

package com.drhj.sp05;

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

@EnableEurekaServer
@SpringBootApplication
public class Sp05EurekaApplication {

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

}

Start test
localhost:2001

There is no service registration at present

Modify the hosts file and add eureka domain name mapping

If you want to access through a special domain name, such as eureka, you can modify the hosts file,
Location: C:\Windows\System32\drivers\etc\hosts
Please open it as an administrator and use Notepad to open it.
add mapping

Start test

supplement

eureka's four operating mechanisms
1. When the client starts, it will repeatedly connect to the registry and try to register until the registration is successful
2. The client sends heartbeat data every 30s. If the server fails to receive the heartbeat of a service for three consecutive times, its registration information will be deleted
3. The client pulls the registry every 30s and refreshes the local registry cache
4. Self protection mode
Within 15 minutes, 85% of servers have abnormal heartbeat
Due to network interruption, 85% of servers have abnormal heartbeat within 15 minutes and automatically enter the protection mode
In self-protection mode, all registration information will not be deleted
Automatically exit the protection mode after network recovery
During development and debugging, the protection mode can be turned off to avoid affecting debugging

2. Registration services

Add dependencies in pom.xml

Add eureka client dependencies in the pom.xml of itemservice userservice orderservice respectively

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

Add settings in application.yml

Add settings in application.yml of itemservice userservice orderservice and specify the access address

eureka:
  client:
    service-url:
      # eureka servers in different locations can be purchased from cloud service providers
      # Your own server can only write defaultZone
      defaultZone: http://eureka1:2001/eureka

3. Registration test

1) Start three services
2) Start registry
3) Visit eureka1:2001

Error reported in service item

Error reported in registry

The above two phenomena are normal. Because we do not configure the cluster, port 8761 is started by default. If this port is occupied, an error will be reported, but our test will not be affected.

2, eureka and service provider high availability


High availability means that a service is opened with multiple ports (multiple services), and then selected from these services when calling the service.

1. Set high availability for service providers

Here, set item service high availability for goods and services
Set two servers and specify port 80018002 respectively


Then copy the previous copy


Start the two services respectively to view the registry

Two services appear

2.eureka high availability

Add profile profiles for both servers

application-eureka1.yml

eureka:
  instance:
    hostname: eureka1
  client:
    register-with-eureka: true  #The configuration of the profile overrides the public configuration
    fetch-registry: true        #The configuration of the profile overrides the public configuration
    service-url: 
      defaultZone: http://Eureka2: register with eureka2 when Eureka #eureka1 starts in 2002 / 2002

application-eureka2.yml

eureka:
  instance:
    hostname: eureka2
  client:
    register-with-eureka: true  #The configuration of the profile overrides the public configuration
    fetch-registry: true        #The configuration of the profile overrides the public configuration
    service-url: 
      defaultZone: http://Eureka1: register with eureka1 at #eureka2 startup in 2001 / Eureka

Configure startup parameters -- spring.profiles.active and -- server.port

Set eureka1 startup parameters
–spring.profiles.active=eureka1 --server.port=2001

Set eureka2 startup parameters
–spring.profiles.active=eureka2 --server.port=2002
Copy previous

Start separately and view

3, Feign remote call

Feign integrates Ribbon, which realizes load balancing and retry by default

1. Business requirements

In order service, you can call item service and user service

2.Feign dependency

Add the following dependencies in the pom.xml file

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

3. Write Feign interface of itemservice

package com.drhj.sp04.feign;

import cn.drhj.sp01.pojo.Item;
import cn.drhj.web.util.JsonResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.List;

/*
Configure three:
 - Which service is called
 - Which road force
 - What parameters are submitted to the path
 */
@FeignClient(name = "item-service")
public interface ItemClient {
    @GetMapping("/{orderId}")
    JsonResult<List<Item>> getItems(@PathVariable String orderId);
    @PostMapping("/decreaseNumber")
    JsonResult<?> decreaseNumber(@RequestBody List<Item> items);
}

4. Write the Feign interface of userservice

package com.drhj.sp04.feign;

import cn.drhj.sp01.pojo.User;
import cn.drhj.web.util.JsonResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(name = "user-service")
public interface UserClient {
    @GetMapping("/{userId}")
    JsonResult<User> getUser(@PathVariable("userId") Integer id);
    @GetMapping("/{userId}/score")    // 8/score?score=1000
    JsonResult<?> addScore(@PathVariable Integer userId,@RequestParam("score") Integer score);

}

5. Modify OrderServiceImpl

Add use of remote calls

package com.drhj.sp04.service;

import cn.drhj.sp01.pojo.Item;
import cn.drhj.sp01.pojo.Order;
import cn.drhj.sp01.pojo.User;
import cn.drhj.sp01.service.OrderService;
import cn.drhj.web.util.JsonResult;
import com.drhj.sp04.feign.ItemClient;
import com.drhj.sp04.feign.UserClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private ItemClient itemClient;
    @Autowired
    private UserClient userClient;
    //Get order based on order id
    @Override
    public Order getOrder(String orderId) {
        log.info("Get orders, orderId = " + orderId);
        Order order = new Order();
        order.setId(orderId);
        //Call the user remotely to obtain user information
        JsonResult<List<Item>> items = itemClient.getItems(orderId);
        //Remotely call the product to get the product list
//        order.setItems();
        JsonResult<User> user = userClient.getUser(8);
        order.setUser(user.getData());
        order.setItems(items.getData());
        return order;
    }
    //Add order
    @Override
    public void addOrder(Order order) {
        log.info("Add order: " + order);
        //Remote call of goods to reduce inventory
        itemClient.decreaseNumber(order.getItems());
        //Remote call users to increase points
        userClient.addScore(order.getUser().getId(),1000);
    }
}

6. Add comments to the startup class

7. Test

Use this URL to refresh several times

Use the URL to refresh several times to see the background messages of the two itemservice services
8001 port:

8002 port:

Thus, load balancing is realized

4, Ribbon's retry

1. Introduction

Retry refers to sending a request to the server again when the request to access the server fails. If a server fails to retry, the server can be replaced

2. Mechanism

If the remote call fails, you can automatically initiate a retry call

  • abnormal
  • Server downtime
  • Background service blocking timeout

3. Parameters

  • MaxAutoRetries - number of retries for a single server. The default is 0
  • MaxAutoRetriesNextServer - the number of server changes is 1 by default
  • ReadTimeout - timeout to wait for a response. The default is 1000
  • OkToRetryOnAllOperations - whether to retry all types of requests. By default, only GET requests are retried
  • ConnectTimeOut - the waiting timeout for establishing a connection with the background server. The default is 1000

4. Test

1) Add the configuration in application.yml in the order service. The configuration is set in the order service because the request is sent to the item service through the request of the order service

ribbon:
  MaxAutoRetries: 1
  MaxAutoRetriesNextServer: 2

Set the number of retries for a single server to 1. If the retries are not successful, replace the server and the number of times to replace the server is 2
2) Add random blocking code to the controller in itemservice to block artificially

package com.drhj.sp02.controller;

import cn.drhj.sp01.pojo.Item;
import cn.drhj.sp01.service.ItemService;
import cn.drhj.web.util.JsonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Random;

@RestController
@Slf4j
public class ItemController {
    @Autowired
    private ItemService itemService;
    //Get the order item list according to the order id
    @GetMapping("/{orderId}")
    public JsonResult<List<Item>> getItems(@PathVariable String orderId) throws InterruptedException {
        List<Item> items = itemService.getItems(orderId);
        //Random blocking, 90% probability of executing blocking code
        if (Math.random() < 0.9) {
            //Pause [0.5000) ms
            int t = new Random().nextInt(5000);
            System.out.println("Pause:" + t);
            Thread.sleep(t);
        }
        return JsonResult.ok().data(items);
    }
    //reduce stock
    //@RequestBody receives the request protocol body data completely
    @PostMapping("/decreaseNumber")
    public JsonResult<?> decreaseNumber(@RequestBody List<Item> items) {
        itemService.decreaseNumber(items);
        return JsonResult.ok().msg("Inventory reduction successful");
    }
    @GetMapping("/favicon.ico")
    public void ico() {
    }
}

3) Restart the two services of item and the order service
Continue visit http://localhost:8201/1
View item background
8001 port

8002 port

A retry occurred
Note that this is the result of multiple refreshes, which may not be intuitive, but it can be seen that a retry did occur.

Posted by kutte on Tue, 19 Oct 2021 11:25:20 -0700