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
-
Package project
-
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