Spring Cloud系列(三) Netflix Eureka注册中心


序号名称链接
1 Spring Cloud 系列(二) 配置中心-Confighttps://blog.csdn.net/qq_38130094/article/details/91456800
2Spring Cloud系列(三) Netflix Eureka注册中心https://blog.csdn.net/qq_38130094/article/details/93992709
3Spring Cloud 系列(四) Netflix ribbon负载均衡https://blog.csdn.net/qq_38130094/article/details/97240915
4Spring Cloud 系列(五) Netflix Hystrixhttps://blog.csdn.net/qq_38130094/article/details/97626558

1. 服务治理简介

什么是服务发现 : 程序如何通过一个标志来获取服务列表,并且这个服务列表是能够随着服务的状态而动态变更。

先介绍两种服务模式:

  • 客户端模式:eureka,consule
  • 服务端模式:zookeeper 

1.1 客户端模式

  调用端调用微服务时,首先到服务注册中心获取服务列表,然后再根据调用端本地的负载均衡策略,进行服务调用。

 

1.2 服务端模式

调用端直接向服务注册中心发起请求,服务注册中心再通过自身负载均衡策略,对微服务进行调用。调用端自身节点不需要维护服务发现逻辑。

两者区别在于,客户端是否保存服务列表信息

1.3 两者对比

客户端模式:

1. 只需要周期性获取列表,在调用服务时可以直接调用少了一个链路。但需要在每个客户端维护获取列表的逻辑;

2. 可用性高,即使注册中心出现故障也能正常工作;

3. 服务上下线对调用方有影响,会出现短暂调用失败

服务端模式:

1. 简单,不需要在客户端维护服务获取列表的逻辑;

2. 可用性由路由器中间件决定,路由中间件故障则所有服务不可用。同时,由于所有调度以及存储都有中间件服务器完成,中间件服务器可能会面临负载过高;

3. 服务上下线调用方无感知;


2. 基于SpringCloud Netflix Eureka 实现注册中心

Eureka由两个组件组成:

  • Eureka Server(注册中心)
  • Eureka Client (服务注册)

基于1.51版本实现

1: application.properties配置文件

#eurake 注册中心实例名
spring.application.name=eurake-server
#eureka注册中心端口
server.port=9090

##关闭Actuator 验证开关
management.sercurity.enable=false

#一个单机的eureka服务,无需注册其他机器,也无需获取服务列表
#不向注册中心获取服务列表
eureka.client.fetch-registry=false
#不注册到注册中心上
eureka.client.register-with-eureka=false

#不设置会给一个默认的,http://localhost:8761/eureka无效地址
#配置注册中心地址
eureka.client.service-url.defaultZone=http://localhost:9090/eureka

服务端配置详解

参数名说明默认值
preferIpAddress是否优先使用IP地址作为主机名的标识false
leaseRenewalIntervalInSecondsEureka客户端向服务端发送心跳的时间间隔,单位为秒30
leaseExpirationDurationInSecondsEureka服务端在收到最后一次心跳之后等待的时间上限,单位为秒90
nonSecurePort非安全的通信端口80
securePort安全的通信端口443
nonSecurePortEnabled是否启用非安全的通信端口true
securePortEnabled是否启用安全的通信端口false
appname服务名spring.application.name/unknown
hostname主机名不配置时取操作系统主机名
instanceId实例ID 
statusPageUrlPath客户端应用实例状态URL/info

 

2 pom.xml文件

    <parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.20.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	
	<properties>
		<java.version>1.8</java.version>
		<spring-cloud.version>Edgware.SR5</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
		</dependency>
		
	</dependencies>

 

3启动类

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

@SpringBootApplication
//eureka Server端配置注解
@EnableEurekaServer
public class SpringCloudEurekaServerDemoApplication {

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

}

3 Eureka 客户端

3.1 客户端--生产者

1:application.properties 配置文件

## Eureka服务提供者实例名
spring.application.name=eureka-provider
## Eureka服务提供者端口
server.port=8070

## 关闭Actuator验证开关
management.security.enabled=false

## 配置 注册中心的 地址
eureka.client.service-url.defaultZone=http://localhost:9090/eureka/

## 修改实例的ID组成(自定义示例名称)
#eureka.instance.instance-id=${spring.application.name}:${server.port}
## 修改Eureka是在在Eureka管理端statusPageUrlPath
#eureka.instance.status-page-url-path=/health

客户端配置文件详解

参数名说明默认值
serviceUrl.defaultZone指定注册中心http://localhost:8761/eureka
enabled启用Eureka客户端TRUE
registryFetchIntervalSecondsEureka服务端获取注册信息的间隔时间,单位为秒30
instanceInfoReplicationIntervalSeconds更新示例信息的变化到Eureka服务端的间隔时间,单位为秒30
initialInstanceInfoReplicationIntervalSeconds初始化实例信息到Eureka服务端的间隔时间,单位为秒40
eurekaServiceUrlPollIntervalSeconds轮询Eureka服务端地址更改的时间间隔,单位为秒300
eurekaServerReadTimeoutSeconds读取Eureka Server信息的超时时间,单位为秒8
eurekaServerConnectTimeoutSeconds 5
eurekaServerTotalConnectionsEureka客户端到所有Eureka服务端的连接总数200
eurekaServerTotalConnectionsPerHostEureka客户端到每个Eureka服务端主机的连接总数50
eurekaConnectionIdleTimeoutSecondsEureka服务端连接的空闲关闭时间,单位为秒30
heartbeatExecutorThreadPoolSize心跳连接池的初始化线程数2
heartbeatExecutorExponentialBackOffBound心跳超时重试延迟时间的最大乘数值10
cacheRefreshExecutorThreadPoolSize缓存刷新线程池的初始化线程数2
cacheRefreshExecutorExponentialBackOffBound缓存刷新重试延迟时间的最大乘数值10
useDnsForFetchingServiceUrls使用DNS来获取Eureka服务端的ServiceURLFALSE
registerWithEureka是否要将自身的实例信息注册到Eureka服务端TRUE
preferSameZoneEureka是否偏好使用处于相同ZoneEureka服务端TRUE
fetchRegistry是否从Eureka服务端获取注册信息 TRUE

2:pom.xml文件


	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.20.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	
	<properties>
		<java.version>1.8</java.version>
		<spring-cloud.version>Edgware.SR5</spring-cloud.version>
	</properties>

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

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

3:启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
//客户端启动注解
@EnableDiscoveryClient
public class SpringCloudEurekaProviderDemoApplication {

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

}

3.1 测试类:ProductController


import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
public class ProductController {

    // 定义一个库存集合
    private static final Map<String, Integer> productMap = new HashMap<String, Integer>();

    /***
     * 修改库存
     * @param productName
     * @param num
     * @return
     */
    @GetMapping("/updateProduct")
    public String updateProducter(String productName, Integer num){
        if(productName != null && !productName.isEmpty()){
            productMap.put(productName, (productMap.get(productName) == null ? 0: productMap.get(productName))-num);
            System.out.println("修改库存:productName-"+productName+", num-"+num);
        }
        return "修改库存成功, "+productName+" 剩下 "+productMap.get(productName);
    }
}

3.2 客户端--消费者

1:application.properties

## Eureka服务消费者实例名
spring.application.name=eureka-consumer
## Eureka服务消费者端口
server.port=8080

## 关闭Actuator验证开关
management.security.enabled=false

## 配置 注册中心的 地址
eureka.client.service-url.defaultZone=http://localhost:9090/eureka/

2:pom.xml文件


	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.20.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	
	<properties>
		<java.version>1.8</java.version>
		<spring-cloud.version>Edgware.SR5</spring-cloud.version>
	</properties>

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

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

3.1:启动类:SpringCloudEurekaConsumerDemoApplication


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableDiscoveryClient
public class SpringCloudEurekaConsumerDemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringCloudEurekaConsumerDemoApplication.class, args);
	}
    //eureka负载均衡
	@Bean
	@LoadBalanced
	public RestTemplate restTemplate(){
		return new RestTemplate();
	}
}

3.2OrderController

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;


@RestController
public class OrderController {

    private static final List<OrderInfo> list = new ArrayList<OrderInfo>();

    @Autowired
    private RestTemplate restTemplate;

    /***
     * 下单接口 --  调用服务提供者provider /updateProduct 接口
     * @param productName
     * @param num
     * @return
     */
    @GetMapping("/order")
    public String order(String productName, Integer num){

        if(productName != null && !productName.isEmpty()){

            list.add(new OrderInfo(productName, num));

            // 调用服务提供者
            String result = restTemplate.getForObject("http://eureka-provider/updateProduct?productName=" + productName + "&num=" + num, String.class);
           System.out.println(result);
            return result;
        }
        return null;
    }
}

3.3实体类

public class OrderInfo implements Serializable {
    private String productName;
    private Integer num;

    public OrderInfo(String productName, Integer num) {
        this.productName = productName;
        this.num = num;
    }

    public OrderInfo() {

    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public Integer getNum() {
        return num;
    }

    public void setNum(Integer num) {
        this.num = num;
    }
}

4 测试使用

4.1依次启动 三个工程:服务端,客户端-生产者,客户端-消费者,

4.2 调用消费者接口  :http://127.0.0.1:8080/order?productName=商品名称&num=12

5. eureka高可用

eureka服务端高可用

修改配置文件

#eureka注册中心端口
server.port=9091

#向注册中心获取服务列表
eureka.client.fetch-registry=true
#注册到注册中心上
eureka.client.register-with-eureka=true
#配置另外一台注册中心地址
eureka.client.service-url.defaultZone=http://localhost:9092/eureka

另外一台eureka的配置文件

#eureka注册中心端口
server.port=9092

#向注册中心获取服务列表
eureka.client.fetch-registry=true
#注册到注册中心上
eureka.client.register-with-eureka=true
#配置另外一台注册中心地址,
eureka.client.service-url.defaultZone=http://localhost:9091/eureka

客户端配置高可用

其他客户端服务注册到服务注册中心只需修改注册地址即可:多个地址用逗号隔开

#配置注册中心地址
eureka.client.service-url.defaultZone=http://localhost:9091/eureka,http://localhost:9092/eureka

6. Eureka深入简介:

注意:有关eureka 2.0的现有开源工作已停止。在2.x分支上作为现有工作资料库的一部分发布的代码库和工件被视为使用后果自负。Eureka 1.x是Netflix服务发现系统的核心部分,仍然是一个活跃的项目

参考地址:https://github.com/Netflix/eureka/wiki      推荐一个spring cloud的论坛链接:http://springcloud.cn/

6.1 eureka架构图

6.2 Eureka核心功能点

  1. 服务注册(register):Eureka Client会通过发送REST请求的方式向Eureka Server注册自己的服务,提供自身的元数 据,比如ip地址、端口、运行状况指标的url、主页地址等信息。Eureka Server接收到注册请求后,就会把这些元数 据信息存储在一个双层的Map中。
  2. 服务续约(renew):在服务注册后,Eureka Client会维护一个心跳来持续通知Eureka Server,说明服务一直处于可 用状态,防止被剔除。Eureka Client在默认的情况下会每隔30秒(eureka.instance.leaseRenewallIntervalInSeconds)发送一次心跳来进行服务续约
  3. 服务同步(replicate):Eureka Server之间会互相进行注册,构建Eureka Server集群,不同Eureka Server之间会进 行服务同步,用来保证服务信息的一致性
  4. 获取服务(get registry):服务消费者(Eureka Client)在启动的时候,会发送一个REST请求给Eureka Server,获 取上面注册的服务清单,并且缓存在Eureka Client本地,默认缓存30秒 (eureka.client.registryFetchIntervalSeconds)。同时,为了性能考虑,Eureka Server也会维护一份只读的服务清 单缓存,该缓存每隔30秒更新一次。
  5. 服务调用:服务消费者在获取到服务清单后,就可以根据清单中的服务列表信息,查找到其他服务的地址,从而进行 远程调用。Eureka有Region和Zone的概念,一个Region可以包含多个Zone,在进行服务调用时,优先访问处于同 一个Zone中的服务提供者
  6. 服务下线(cancel):当Eureka Client需要关闭或重启时,就不希望在这个时间段内再有请求进来,所以,就需要提前 先发送REST请求给Eureka Server,告诉Eureka Server自己要下线了,Eureka Server在收到请求后,就会把该服务 状态置为下线(DOWN),并把该下线事件传播出去
  7. 服务剔除(evict):有时候,服务实例可能会因为网络故障等原因导致不能提供服务,而此时该实例也没有发送请求给 Eureka Server来进行服务下线,所以,还需要有服务剔除的机制。Eureka Server在启动的时候会创建一个定时任 务,每隔一段时间(默认60秒),从当前服务清单中把超时没有续约(默认90秒, eureka.instance.leaseExpirationDurationInSeconds)的服务剔除。

6.3 eureka服务端代码流程

6.4 客户端代码继承关系:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值