Learn spring cloud Eureka to take you from 0 to 1

1, What is a service registry

Service registry is the core component of service registration and management, which is similar to directory service. It is mainly used to store service information, such as service provider url string, routing information, etc. Service registry is one of the most basic facilities in SOA architecture.

1. Role of service registry

1. Registration of services

2 service discovery

2. Common registration centers

1 Zookeeper, Dubo's registry

2 Eureka of spring cloud

3. What problems did the service registration center solve

1. Service management

2. Dependency management of services

4. What is Eureka Registration Center

Eureka is a service discovery component developed by Netflix, which is a Rest based service. Spring cloud integrates it into its subproject to realize service registration and discovery of spring cloud, and also provides load balancing and registration

4.1 three roles of Eureka registry
  • Eureka Server

    Provide service registration and discovery through Register, Get, Renew and other interfaces.

  • Application Service(Service Provider)

    service provider

    Register your own service instance to Eureka Server

  • Application Client(Service Consumer)

    Service caller

    Get the service list through Eureka Server and consume the service

2, Eureka introduction case

1. Create project

1.1 add dependency
<?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">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.13.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.luyi</groupId>
	<artifactId>springcloud-eureka-server</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>springcloud-eureka-server</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Dalston.SR5</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka-server</artifactId>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>
1.2 modify startup class
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }
}
1.3 modify global configuration file
spring.application.name=eureka-server
#Modify server port
server.port=8761

#Whether to register yourself in Eureka server? true by default
eureka.client.registerWithEureka=false

#Whether to obtain service information from Eureka server? true by default
eureka.client.fetchRegistry=false
1.4 access Eureka server service management platform through browser

3, Building Eureka cluster

1. Create project

1.1 create project

springcloud-eureka-server-ha

1.2 modify configuration file

When building an Eureka cluster, you need to add multiple configuration files, and use the SpringBoot multi environment configuration mode to add as many configuration files as many nodes as you need in the cluster

1.3 configure cluster nodes in the configuration file

Eureka1

spring.application.name=eureka-server
#Modify server port
server.port=8761

#Set the Eureka instance name, mainly the configuration file variable
eureka.instance.hostname=eureka1

#Set the service registry address to another registry
eureka.client.serviceUrl.defaultZone=http://eureka2:8761/eureka/

Eureka2

spring.application.name=eureka-server
#Modify server port
server.port=8761

#Set the Eureka instance name, mainly the configuration file variable
eureka.instance.hostname=eureka2

#Set the service registry address to another registry
eureka.client.serviceUrl.defaultZone=http://eureka1:8761/eureka/
1.4 add logback log configuration file
<?xml version="1.0" encoding="UTF-8" ?>
 <configuration>
<!--The storage address of the definition log file is not in LogBack Using relative paths in the configuration of-->  
    <property name="LOG_HOME" value="${catalina.base}/logs/" />  
    <!-- console output  -->   
    <appender name="Stdout" class="ch.qos.logback.core.ConsoleAppender">
       <!-- Log output code -->  
        <layout class="ch.qos.logback.classic.PatternLayout">   
             <!--Format output:%d Represents the date,%thread Represents the thread name,%-5level: Level 5 character width from left%msg: Log messages,%n Newline character--> 
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n   
            </pattern>   
        </layout>   
    </appender>   
    <!-- Generate log files on a daily basis -->   
    <appender name="RollingFile"  class="ch.qos.logback.core.rolling.RollingFileAppender">   
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--Filename of log file output-->
            <FileNamePattern>${LOG_HOME}/server.%d{yyyy-MM-dd}.log</FileNamePattern>   
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>   
        <layout class="ch.qos.logback.classic.PatternLayout">  
            <!--Format output:%d Represents the date,%thread Represents the thread name,%-5level: Level 5 character width from left%msg: Log messages,%n Newline character--> 
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n   
            </pattern>   
       </layout> 
        <!--Maximum log file size-->
       <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
         <MaxFileSize>10MB</MaxFileSize>
       </triggeringPolicy>
    </appender>     

    <!-- Log output level -->
    <root level="DEBUG">   
        <appender-ref ref="Stdout" />   
        <appender-ref ref="RollingFile" />   
    </root> 



<!--Log asynchronous to database -->  
<!--     <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
        Log asynchronous to database 
        <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
           Connection pool 
           <dataSource class="com.mchange.v2.c3p0.ComboPooledDataSource">
              <driverClass>com.mysql.jdbc.Driver</driverClass>
              <url>jdbc:mysql://127.0.0.1:3306/databaseName</url>
              <user>root</user>
              <password>root</password>
            </dataSource>
        </connectionSource>
  </appender> -->

</configuration>
1.5 Eureka cluster deployment

Deployment environment: jdk1.8

  1. Package project

  2. Upload the jar package to the / usr/local/eureka folder

1.6 writing startup script
#!/bin/bash
 
cd `dirname $0`
 
CUR_SHELL_DIR=`pwd`
CUR_SHELL_NAME=`basename ${BASH_SOURCE}`
 
JAR_NAME="entry name"
JAR_PATH=$CUR_SHELL_DIR/$JAR_NAME
 
#JAVA_MEM_OPTS=" -server -Xms1024m -Xmx1024m -XX:PermSize=128m"
JAVA_MEM_OPTS=""
 
SPRING_PROFILES_ACTIV="-Dspring.profiles.active=Profile variable name"
#SPRING_PROFILES_ACTIV=""
LOG_DIR=$CUR_SHELL_DIR/logs
LOG_PATH=$LOG_DIR/${JAR_NAME%..log
 
echo_help()
{
    echo -e "syntax: sh $CUR_SHELL_NAME start|stop"
}
 
if [ -z $1 ];then
    echo_help
    exit 1
fi
 
if [ ! -d "$LOG_DIR" ];then
    mkdir "$LOG_DIR"
fi
 
if [ ! -f "$LOG_PATH" ];then
    touch "$LOG_DIR"
fi
 
if [ "$1" == "start" ];then
 
    # check server
    PIDS=`ps --no-heading -C java -f --width 1000 | grep $JAR_NAME | awk '{print $2}'`
    if [ -n "$PIDS" ]; then
        echo -e "ERROR: The $JAR_NAME already started and the PID is ${PIDS}."
        exit 1
    fi
 
    echo "Starting the $JAR_NAME..."
 
    # start
    nohup java $JAVA_MEM_OPTS -jar $SPRING_PROFILES_ACTIV $JAR_PATH >> $LOG_PATH 2>&1 &
 
    COUNT=0
    while [ $COUNT -lt 1 ]; do
        sleep 1
        COUNT=`ps  --no-heading -C java -f --width 1000 | grep "$JAR_NAME" | awk '{print $2}' | wc -l`
        if [ $COUNT -gt 0 ]; then
            break
        fi
    done
    PIDS=`ps  --no-heading -C java -f --width 1000 | grep "$JAR_NAME" | awk '{print $2}'`
    echo "${JAR_NAME} Started and the PID is ${PIDS}."
    echo "You can check the log file in ${LOG_PATH} for details."
 
elif [ "$1" == "stop" ];then
 
    PIDS=`ps --no-heading -C java -f --width 1000 | grep $JAR_NAME | awk '{print $2}'`
    if [ -z "$PIDS" ]; then
        echo "ERROR:The $JAR_NAME does not started!"
        exit 1
    fi
 
    echo -e "Stopping the $JAR_NAME..."
 
    for PID in $PIDS; do
        kill $PID > /dev/null 2>&1
    done
 
    COUNT=0
    while [ $COUNT -lt 1 ]; do
        sleep 1
        COUNT=1
        for PID in $PIDS ; do
            PID_EXIST=`ps --no-heading -p $PID`
            if [ -n "$PID_EXIST" ]; then
                COUNT=0
                break
            fi
        done
    done
 
    echo -e "${JAR_NAME} Stopped and the PID is ${PIDS}."
else
    echo_help
    exit 1
fi

add permission

chmod -R 755 server.sh

1.7 modify the hosts file of linux

vi /etc/hosts

192.168.234.130 eureka1
192.168.234.131 eureka2
1.8 launch of eureka registry
./server.sh start	#start-up
./server.sh stop	#Stop it

4, Build Provider service in highly available Eureka registry

1. Create project

springcloud-eureka-provider

1.1 add dependency
<?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">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.13.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.luyi</groupId>
	<artifactId>springcloud-eureka-provider</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>springcloud-eureka-provider</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Dalston.SR5</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>
1.2 modify startup class
//Represents Eureka's client
@EnableEurekaClient
@SpringBootApplication
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }
}
1.3 modifying the provider's configuration file
spring.application.name=eureka-provider
server.port=9090

#Set the address of service registration center and register with all registration centers
eureka.client.serviceUrl.defaultZone=http://eureka1:8761/eureka/,http://eureka2:8761/eureka/
1.4 modify the host file of Windows

C:\Windows\System32\drivers\etc

192.168.234.130 eureka1
192.168.234.131 eureka2

1.5 write service interface
@RestController
public class UserController {

    @RequestMapping("/user")
    public List<User> getUsers(){
        List<User> users = new ArrayList<>();
        users.add(new User(1, "zhangsan", 20));
        users.add(new User(2, "lisi", 22));
        users.add(new User(3, "wangwu", 30));
        return users;
    }
}
1.6 create entity
/**
 * Author: LuYi
 * Date: 2019/11/6 12:30
 * Description: describe
 */
public class User {

    private Integer userid;
    private String username;
    private Integer userage;

    public User() {
    }

    public User(Integer userid, String username, Integer userage) {
        this.userid = userid;
        this.username = username;
        this.userage = userage;
    }

    public Integer getUserid() {
        return userid;
    }

    public void setUserid(Integer userid) {
        this.userid = userid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Integer getUserage() {
        return userage;
    }

    public void setUserage(Integer userage) {
        this.userage = userage;
    }
}

5, Building Consumer service in highly available Eureka registry

Consumers and producers of services need to register with Eureka registry

1. Create project

1.1 configuration file of consumer
spring.application.name=eureka-consumer
server.port=9091

#Set the address of service registration center and register with all registration centers
eureka.client.serviceUrl.defaultZone=http://eureka1:8761/eureka/,http://eureka2:8761/eureka/
1.2 complete Service call in Service
@Service
public class UserService {

    @Autowired
    private LoadBalancerClient loadBalancerClient;  //ribbon: load balancer

    public List<User> getUsers(){

        //Select the name of the called service
            //ServiceInstance: encapsulates the basic information of the service, such as ip and port number
        ServiceInstance si = loadBalancerClient.choose("eureka-provider");
        //url of splicing access service
        StringBuffer sb = new StringBuffer();

        //http://localhost:9090/user
        sb.append("http://").append(si.getHost()).append(":").append(si.getPort()).append("/user");

        //SpringMVC RestTemplate
        RestTemplate restTemplate = new RestTemplate();
        ParameterizedTypeReference<List<User>> type = new ParameterizedTypeReference<List<User>>() {
        };

        //ResponseEntity: encapsulates the return value information
        ResponseEntity<List<User>> entity = restTemplate.exchange(sb.toString(), HttpMethod.GET, null, type);
        return entity.getBody();
    }
}
1.3 create Controller
@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("/consumer")
    public List<User> getUsers(){
        return userService.getUsers();
    }
}

6, Principle of Eureka registry architecture

1.Eureka architecture

  • Register: register your own IP and port number to Eureka
  • Renew (service renewal): Send a heartbeat packet every 30s to tell Eureka that he is still alive
  • Cancel: when the provider is shut down, it will send a message to Eureka to remove itself from the service list. Prevent Consumer from calling to a non-existent service
  • Get registry: get a list of other services
  • Replicate: data replication and synchronization in Eureka cluster
  • Make Remote Call: completing a service remote call

7, Based on the distributed CAP theorem, the difference between Eureka and Zookeeper is analyzed

1. What is CAP principle

CAP principle, also known as CAP theorem, refers to Consistency, Availability and Partition tolerance in distributed system, which can't be obtained at the same time, but can only be selected from three.

CAP was proposed by Eric Brewer at the 2000 PODC conference. This conjecture was proved to be true two years later, which is called CAP theorem that we are familiar with

2. The difference between zookeeper and Eureka

8, Eureka's elegant stop

1. Under what circumstances, Eureka will turn on self-protection

1.1 self protection conditions

Generally, after the microservice is registered in Eureka, it will send heartbeat packets every 30s, and delete the service that does not send heartbeat packets in 90s on a regular basis.

1.2 there are two conditions that can cause Eureka Server to fail to receive heartbeat of microservice
  • The reasons of micro service itself

  • The reason of the network between microservice and Eureka

    If it is because of the microservice failure, it will not lead to the situation that the heartbeat package cannot be received in large quantities, but will only cause some failures, while the network failure will lead to the situation that the heartbeat package cannot be received in large quantities.

    Considering this difference, Eureka sets a threshold value. If the heartbeat packet cannot be received on a large scale in a short period of time, it will be judged as a network failure, so Eureka will not delete the expired heartbeat service

  • What is the threshold

    Judge whether it is lower than 85% within 15 minutes

    During the operation of Eureka Server, it will judge whether the heartbeat failure rate reaches 85% within 15 minutes

    This algorithm is called Eureka Server's self-protection mode.

2. Why to protect yourself

  • Because it is better to keep * * good data and * * bad data * * at the same time than to delete all data. If the network fault enters self-protection, when the fault is repaired, it will automatically exit self-protection mode
  • The load balancing strategy of microservice will automatically eliminate the dead microservice nodes

3. How to turn off self-protection

Modify Eureka Server configuration file

#Turn off self-protection: true to turn on, false to turn off
eureka.server.enable-self-preservation=false
#Cleaning interval (unit: ms, default is 60 * 1000)
eureka.server.eviction-interval-timer-in-ms=60000

4. How to stop wearing gracefully

4.1 do not need to configure shutdown self-protection in Eureka Server
4.2 add the actor.jar package to the service
4.3 modify configuration file
#Start shutdown
endpoints.shutdown.enabled=true
#Disable password authentication
endpoints.shutdown.sensitive=false
4.4 send a URL request to shut down the service
public class HttpClientUtil {

	public static String doGet(String url, Map<String, String> param) {

		// Create Httpclient object
		CloseableHttpClient httpclient = HttpClients.createDefault();

		String resultString = "";
		CloseableHttpResponse response = null;
		try {
			// Create uri
			URIBuilder builder = new URIBuilder(url);
			if (param != null) {
				for (String key : param.keySet()) {
					builder.addParameter(key, param.get(key));
				}
			}
			URI uri = builder.build();

			// Create http GET request
			HttpGet httpGet = new HttpGet(uri);

			// Execution request
			response = httpclient.execute(httpGet);
			// Judge whether the return status is 200
			if (response.getStatusLine().getStatusCode() == 200) {
				resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (response != null) {
					response.close();
				}
				httpclient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return resultString;
	}

	public static String doGet(String url) {
		return doGet(url, null);
	}

	public static String doPost(String url, Map<String, String> param) {
		// Create Httpclient object
		CloseableHttpClient httpClient = HttpClients.createDefault();
		CloseableHttpResponse response = null;
		String resultString = "";
		try {
			// Create Http Post request
			HttpPost httpPost = new HttpPost(url);
			// Create parameter list
			if (param != null) {
				List<NameValuePair> paramList = new ArrayList<>();
				for (String key : param.keySet()) {
					paramList.add(new BasicNameValuePair(key, param.get(key)));
				}
				// Simulated form
				UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList,"utf-8");
				httpPost.setEntity(entity);
			}
			// Execute http request
			response = httpClient.execute(httpPost);
			resultString = EntityUtils.toString(response.getEntity(), "utf-8");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				response.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		return resultString;
	}

	public static String doPost(String url) {
		return doPost(url, null);
	}
	
	public static String doPostJson(String url, String json) {
		// Create Httpclient object
		CloseableHttpClient httpClient = HttpClients.createDefault();
		CloseableHttpResponse response = null;
		String resultString = "";
		try {
			// Create Http Post request
			HttpPost httpPost = new HttpPost(url);
			// Create request content
			StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
			httpPost.setEntity(entity);
			// Execute http request
			response = httpClient.execute(httpPost);
			resultString = EntityUtils.toString(response.getEntity(), "utf-8");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				response.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		return resultString;
	}
	
	public static void main(String[] args) {
		String url ="http://127.0.0.1:9090/shutdown";
		//The url must be sent in doPost mode
		HttpClientUtil.doPost(url);
	}
}

9, How to strengthen the safety certification of Eureka Registration Center

1. Add security package to EurekaServer

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2. Modify Eureka Server configuration file

#Open the security authentication of http basic
security.basic.enabled=true
security.user.name=user
security.user.password=123456

3. Modify the url to access the cluster node

eureka.client.serviceUrl.defaultZone=http://user:123456@eureka2:8761/eureka/

4. Modify the configuration file and the user name and password to access the registry

spring.application.name=eureka-provider
server.port=9090

#Set the address of service registration center and register with all registration centers
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/

#Start shutdown
endpoints.shutdown.enabled=true
#Disable password authentication
endpoints.shutdown.sensitive=false

Published 11 original articles, praised 0, visited 94
Private letter follow

Keywords: Spring Maven Java Apache

Added by barbs75 on Mon, 24 Feb 2020 15:58:18 +0200