Eureka注册中心介绍与环境搭建

一、简介

1.1、服务注册中心

1)概念:服务实现服务化管理的核心组件,是SOA架构中最基础的设施,用来存储服务信息(如服务提供者的url、路由信息等);
2)作用:服务的注册与发现;
3)案例:SpringCloud中的Eureka、Dubbo中使用的Zookeeper

1.2、Eureka介绍

1.2.1、概念

Netflix 开发的服务发现组件,本身是一个基于 REST 的服务。Spring Cloud 将它 集成在其子项目 spring-cloud-netflix 中,以实现 Spring Cloud 的服务注册于发现,同时还提供 了负载均衡、故障转移等能力;

1.2.2、三种角色

1)Eureka Server:通过 Register、Get、Renew 等接口提供服务的注册和发现;
2)Application Service (Service Provider):服务提供方,把自身的服务实例注册到 Eureka Server 中;
3)Application Client (Service Consumer):服务调用方,通过 Eureka Server 获取服务列表,消费服务;

1.3、架构图

在这里插入图片描述
Register:服务注册,把自己的 IP 和端口注册给 Eureka;
Renew:服务续约,发送心跳包,每 30 秒发送一次,告诉 Eureka 自己还在线;
Cancel:服务下线,当 provider 关闭时会向 Eureka 发送消息,把自己从服务列表中删除,防止consumer 调用到不存在的服务;
Get Registry:获取(其它)服务注册列表;
Replicate:集群中数据同步,eureka集群中的数据复制与同步;
Make Remote Call:完成服务的远程调用;

1.4、CAP 原则

Consistency:一致性
Availability:可用性
Partition tolerance:分区容错性
指在一个分布式系统中,只可同时满足二点,没法三者兼顾;

特征 说明
Consistency 数据一致性,也叫做数据原子性,系统在执行某项操作后仍然处于一致的状态。在分布式系统 中,更新操作执行成功后所有的用户都应该读到最新的值, 这样的系统被认为是具有强一致性的。等同于所有节点访问 同一份最新的数据副本
Availablity 每一个操作总是能够在一定的时间内返回结果,这里需 要注意的是"一定时间内"和"返回结果"。一定时间内指的是, 在可以容忍的范围内返回结果,结果可以是成功或者是失败
Partition-torlerance 在网络分区的情况下,被分隔的节点仍能正常对外提供 服务(分布式集群,数据被分布存储在不同的服务器上,无论 什么情况,服务器都能正常被访问)

1.5、ZK与Eureka对比

对比项 Zookeeper Eureka
CAP CP AP
Dubbo 集成 支持 -
Spring Cloud 集成 支持 支持
kv 服务 支持 - ZK 支持数 据存储,eureka 不支持
使用接口(多语言能力) 提供客户端 http 多语言 ZK 的跨语 言支持比较弱
watch 支持 支持 什么是 Watch 支持? 就是客户单 监听服务端的 变化情况。 zk 通过订阅监 听来实现 eureka 通过轮 询的方式来实现
集群监控 - 支持 metrics, 运维者可以收 集并报警这些 度量信息达到监控目的

二、单机服务

2.1、引入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">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.bjsxt</groupId>
	<artifactId>springcloud-eureka-server</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>springcloud-eureka-server</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.13.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<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>

2.2、配置修改

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

#是否将自己注册到 Eureka-Server中,默认的为true
eureka.client.registerWithEureka=false
#是否从Eureka-Server中获取服务注册信息,默认为true
eureka.client.fetchRegistry=false

2.3、开启注册

启动类中新增@EnableEurekaServer注解

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

2.4、效果查看

访问地址http://localhost:8761/
在这里插入图片描述

三、集群服务

pom依赖同单机服务

3.1、多配置文件

application-eureka1.properties

spring.application.name=eureka-server
server.port=8761
#设置 eureka 实例名称,与配置文件的变量为主
eureka.instance.hostname=eureka1
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://eureka2:8761/eureka/

application-eureka2.properties

spring.application.name=eureka-server
server.port=8761
#设置 eureka 实例名称,与配置文件的变量为主
eureka.instance.hostname=eureka2
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://eureka1:8761/eureka/

3.2、集成日志

logback.xml

<?xml version="1.0" encoding="UTF-8" ?>
 <configuration>
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->  
    <property name="LOG_HOME" value="${catalina.base}/logs/" />  
    <!-- 控制台输出 -->   
    <appender name="Stdout" class="ch.qos.logback.core.ConsoleAppender">
       <!-- 日志输出编码 -->  
        <layout class="ch.qos.logback.classic.PatternLayout">   
             <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--> 
            <pattern>%d{
    
    yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{
    
    50} - %msg%n   
            </pattern>   
        </layout>   
    </appender>   
    <!-- 按照每天生成日志文件 -->   
    <appender name="RollingFile"  class="ch.qos.logback.core.rolling.RollingFileAppender">   
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${
    
    LOG_HOME}/server.%d{
    
    yyyy-MM-dd}.log</FileNamePattern>   
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>   
        <layout class="ch.qos.logback.classic.PatternLayout">  
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--> 
            <pattern>%d{
    
    yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{
    
    50} - %msg%n   
            </pattern>   
       </layout> 
        <!--日志文件最大的大小-->
       <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
         <MaxFileSize>10MB</MaxFileSize>
       </triggeringPolicy>
    </appender>     

    <!-- 日志输出级别 -->
    <root level="DEBUG">   
        <appender-ref ref="Stdout" />   
        <appender-ref ref="RollingFile" />   
    </root> 


<!--日志异步到数据库 -->  
<!--     <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
        日志异步到数据库 
        <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
           连接池 
           <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>

3.3、打包上传至Linux环境

1)install打包
2)rz命令,将springcloud-eureka-server-ha-0.0.1-SNAPSHOT.jar上传至 /usr/local/eureka目录下(两台机192.168.48.128、192.168.48.129)

[root@localhost eureka]# pwd
/usr/local/eureka
[root@localhost eureka]# ll
总用量 39116
-rw-r--r--. 1 root root 40054481 814 23:24 springcloud-eureka-server-ha-0.0.1-SNAPSHOT.jar

3.4、修改host文件

128与129两台机器都需要修改

[root@localhost eureka]# vim /etc/hosts
[root@localhost eureka]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.48.128 eureka1
192.168.48.129 eureka2

3.5、编写启动脚本

上传server.sh到部署包同级目录

#!/bin/bash
 
cd `dirname $0`
 
CUR_SHELL_DIR=`pwd`
CUR_SHELL_NAME=`basename ${
      
      BASH_SOURCE}`
 
JAR_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=配置文件变量名称"
#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

脚本授权

chmod -R 755 server.sh

将脚本中的\r替换成空白(在Windows下每一行结尾是\n\r,而Linux下则是\n,直接启动会提示多出\r

sed -i 's/\r$//' server.sh

3.6、启动注册中心

./server.sh start

[root@localhost eureka]# ./server.sh start
Starting the springcloud-eureka-server-ha-0.0.1-SNAPSHOT.jar...
springcloud-eureka-server-ha-0.0.1-SNAPSHOT.jar Started and the PID is 4010.
You can check the log file in /usr/local/eureka/logs/springcloud-eureka-server-ha-0.0.1-SNAPSHOT.jar for details.

3.7、开防火墙

[root@localhost eureka]# firewall-cmd --zone=public --add-port=8761/tcp --permanent
success
[root@localhost eureka]# firewall-cmd --reload
success

3.8、查看效果

分别访问 http://192.168.48.128:8761/http://192.168.48.129:8761/,可见服务eureka1eureka2相互注册成功
在这里插入图片描述

四、provider与consumer服务搭建

4.1、provider

4.1.1、pom依赖

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

4.1.2、配置文件

spring.application.name=eureka-provider
server.port=9090
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://192.168.48.128:8761/eureka/,http://192.168.48.129:8761/eureka/

4.1.3、Controller

@RestController
public class UserController {
    
    

	@RequestMapping("/provider")
	public List<User> getUsers(){
    
    
		List<User> list = new ArrayList<>();
		list.add(new User(1,"zhangsan",20));
		list.add(new User(2,"lisi",22));
		list.add(new User(3,"wangwu",20));
		return list;
	}
}

4.1.4、pojo

public class User {
    
    

	private int userid;
	private String username;
	private int userage;
	
	public User(int userid, String username, int userage) {
    
    
		super();
		this.userid = userid;
		this.username = username;
		this.userage = userage;
	}
	public User() {
    
    
		super();
	}
	//getter setter...
}

4.1.5、启动类注解

@EnableEurekaClient

4.2、consumer

4.1.1、配置文件

spring.application.name=eureka-consumer
server.port=9091
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://192.168.48.128:8761/eureka/,http://192.168.48.129:8761/eureka/

4.1.2、Controller

@RestController
public class UserController {
    
    

	@Autowired
	private UserService userService;

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

4.1.3、pojo

public class User {
    
    

	private int userid;
	private String username;
	private int userage;
	
	public User(int userid, String username, int userage) {
    
    
		super();
		this.userid = userid;
		this.username = username;
		this.userage = userage;
	}
	public User() {
    
    
		super();
	}
	// getter setter
}

4.1.4、UserService

使用ribbon负载均衡器进行服务调用

@Service
public class UserService {
    
    

	@Autowired
	private LoadBalancerClient loadBalancerClient;//ribbon负载均衡器

	public List<User> getUsers(){
    
    
		//选择调用的服务的名称
		//ServiceInstance 封装了服务的基本信息,如 IP,端口
		ServiceInstance si = this.loadBalancerClient.choose("eureka-provider");
		//拼接访问服务的URL
		StringBuffer sb = new StringBuffer();
		//http://localhost:9090/user
		sb.append("http://").append(si.getHost()).append(":").append(si.getPort()).append("/provider");

		//springMVC RestTemplate
		RestTemplate rt = new RestTemplate();
		ParameterizedTypeReference<List<User>> type = new ParameterizedTypeReference<List<User>>() {
    
    };

		//ResponseEntity:封装了返回值信息
		ResponseEntity<List<User>> response = rt.exchange(sb.toString(), HttpMethod.GET, null, type);
		List<User> list =response.getBody();
		return list;
	}
}

4.1.5、启动类注解

@EnableEurekaClient

4.3、效果查看

1)启动两个服务,并注册到Eureka中心
在这里插入图片描述

2)通过访问consumer,调用provider中的服务
在这里插入图片描述

五、安全认证

5.1、eureka服务端引入pom

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

5.2、eureka服务端增加用户配置信息

#开启 http basic 的安全认证
security.basic.enabled=true
security.user.name=admin
security.user.password=123456

5.3、eureka服务端修改注册中心url配置

加上用户名和密码

#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://admin:123456@eureka1:8761/eureka/

5.4、重新打包后访问eureka服务端

需要输入用户名和密码,说明安全认证已经生效了
在这里插入图片描述

5.5、provider与consumer配置修改

eureka.client.serviceUrl.defaultZone=http://admin:123456@192.168.48.128:8761/eureka/,http://admin:123456@192.168.48.129:8761/eureka/

六、自我保护

6.1、自我保护介绍

6.1.1、触发条件

一般情况下,微服务在 Eureka 上注册后,会每 30 秒发送心跳包,Eureka 通过心跳来 判断服务时候健康,同时会定期删除超过 90 秒没有发送心跳服务;

6.1.2、收不到微服务的心跳情况

1)是微服务自身的原因
2)微服务与 Eureka 之间的网络故障

6.1.3、触发保护阈值

15 分钟之内是否低于 85%;
如果在15分钟内超过85%的客户端节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,Eureka Server自动进入自我保护机制;

6.1.4、为什么需要自我保护

1)因为同时保留"好数据"与"坏数据"总比丢掉任何数据要更好,当网络故障恢复后, 这个 Eureka 节点会退出"自我保护模式";
2)Eureka 还有客户端缓存功能(也就是微服务的缓存功能)。即便 Eureka 集群中所有节点 都宕机失效,微服务的 Provider 和 Consumer都能正常通信;
3)微服务的负载均衡策略会自动剔除死亡的微服务节点;

6.2、关闭自我保护

#关闭自我保护:true 为开启自我保护,false 为关闭自我保护
eureka.server.enableSelfPreservation=false 
#清理间隔(单位:毫秒,默认是 60*1000) 
eureka.server.eviction.interval-timer-in-ms=60000

猜你喜欢

转载自blog.csdn.net/shaixinxin/article/details/108014357
今日推荐