Eureka、Ribbon、Feign简介和使用

Eureka简介

Eureka是Netflix的一个子模块,也是核心模块之一。Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移,而不需要修改服务调用的配置文件。功能类似于Dubbo的注册中心,如Zookeeper。

Spring Cloud中提供服务注册中心来管理微服务信息,解决了如下问题:

  • 微服务的ip和端口管理
    在前后台分离大型架构中,服务层被拆成了很多的微服务,前端要进行远程调用后台提供的接口就需要知道服务端的ip地址和端口,注册中心帮助我们管理这些服务器的ip和端口
  • 微服务的状态管理
    微服务会实时上报自己的状态,注册中心统一管理这些微服务的状态,将存在问题的服务踢出服务列表,客户端获取到可用的服务进行调用

Eureka实现了服务治理的功能,提供服务端和客户端,服务端是Eureka服务注册中心,客户端完成微服务向Eureka服务的注册与发现。Eureka Server和Eureke Client关系图:
在这里插入图片描述

  • Eureka Server是服务端,负责管理各微服务结点的信息和状态
  • 在微服务上部署Eureka Client程序,远程访问Eureka Server将自己注册在Eureka Server
  • 当微服务需要调用另一个微服务时从Eureka Server中获取服务调用地址,进行远程调用

搭建Eureka Server

JDK8

单机环境搭建

1 创建maven子工程(Eureka 服务端)
2 添加依赖
父工程:

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring‐cloud‐dependencies</artifactId>
	<version>Finchley.SR1</version>
	<type>pom</type>
	<scope>import</scope>
</dependency>

子工程:

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring‐cloud‐starter‐netflix‐eureka‐server</artifactId>
</dependency>

3 启动类
主要是@EnableEurekaServer注解

@EnableEurekaServer//标识这是一个Eureka服务
@SpringBootApplication
public class GovernCenterApplication {
	public static void main(String[] args) {
		SpringApplication.run(GovernCenterApplication.class, args);
	}
}

4 配置

server:
  port: 50101
eureka:
  client:
    registerWithEureka: false #服务注册,是否将自己注册到Eureka服务中
    fetchRegistry: false #服务发现,是否从Eureka中获取注册信息
    serviceUrl: #Eureka客户端与Eureka服务端的交互地址,高可用状态配置对方的地址,单机状态配置自己的地址(如果不配置则默认本机8761端口)
     defaultZone: http://localhost:50101/eureka/
  server:
    enable‐self‐preservation: false #禁用自我保护模式
    eviction‐interval‐timer‐in‐ms: 60000 #服务注册表清理间隔(单位毫秒,默认是60*1000)

参数说明:

  • registerWithEureka:服务注册,是否将自己注册到Eureka服务中
  • fetchRegistry:需要从Eureka中查找要调用的目标服务时需要设置为true
  • serviceUrl.defaultZone:Eureka客户端与Eureka服务端的交互地址,高可用状态配置对方的地址,单机状态配置自己的地址(如果不配置则默认本机8761端口)
  • enable-self-preservation:自保护机制。 Eureka Server有一种自我保护模式,Eureka Server会保护服务注册表中的信息,不注销任何服务实例,即当微服务不再上报健康状态时,不会将该服务从注册中心中移除。当它收到的心跳数重新恢复到阈值以上时,该Eureka Server节点就会自动退出自我保护模式。该值设置为true,Eureka server进入自保护模式
  • eviction-interval-timer-in-ms:清理失效结点的时间间隔,在这个时间段内如果没有收到该结点的上报则将结点从服务列表中剔除

启动Eureka Server后,可通过浏览器访问localhost:50101查看Eureka的信息:
在这里插入图片描述

高可用环境搭建

如果是单机环境,Eureka Server宕机了,那微服务之间就没法调用了。因此配置多个Eureka Server相互注册对方,微服务需要连接两台Eureka Server注册,当其中一台Eureka Server死掉也不会影响服务的注册与发现,保证系统高可用性。

这里实现在一个机子上,用两个不同的端口模拟高可用

1 配置文件

server:
  port: ${PORT:50101} #服务端口
spring:
  application:
    name: govern-center #指定服务名
eureka:
  client:
    registerWithEureka: true #服务注册,是否将自己注册到Eureka服务中
    fetchRegistry: true #服务发现,是否从Eureka中获取注册信息
    serviceUrl: #Eureka客户端与Eureka服务端的交互地址,高可用状态配置对方的地址,单机状态配置自己(如果不配置则默认本机8761端口)
     defaultZone:  ${EUREKA_SERVER:http://eureka02:50102/eureka/}
  server:
    enable‐self‐preservation: false #是否开启自我保护模式
    eviction‐interval‐timer‐in‐ms: 60000 #服务注册表清理间隔(单位毫秒,默认是60*1000)
  instance:
    hostname: ${EUREKA_DOMAIN:eureka01}

2 IDEA配置
-DPORT=50101 -DEUREKA_SERVER=http://eureka02:50102/eureka/ -DEUREKA_DOMAIN=eureka01
在这里插入图片描述
-DPORT=50102 -DEUREKA_SERVER=http://eureka01:50101/eureka/ -DEUREKA_DOMAIN=eureka02
在这里插入图片描述
分别启动eureka01和eureka02,浏览器访问http://localhost:50101/
在这里插入图片描述
浏览器访问http://localhost:50102/
在这里插入图片描述

服务注册

将微服务注册到Eureka Server中

1 在微服务中添加依赖(作为Eureka Client)

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

2 配置yml

server:
  port: 3000
spring:
  application:
    name: service-manage
eureka:
  client:
    registerWithEureka: true #服务注册开关
    fetchRegistry: true #服务发现开关
    serviceUrl: #Eureka客户端与Eureka服务端进行交互的地址,多个中间用逗号分隔
      defaultZone: ${EUREKA_SERVER:http://localhost:50101/eureka/,http://localhost:50102/eureka/}
  instance:
    prefer-ip-address:  true  #将自己的ip地址注册到Eureka服务中
    ip-address: ${IP_ADDRESS:127.0.0.1}
    instance-id: ${spring.application.name}:${server.port} #指定实例id

3 在微服务启动类上添加注解@EnableEurekaClient,表示它是一个Eureka的客户端
4 刷新Eureka Server
在这里插入图片描述
截止这里,已经搭建了Eureka Server高可用环境以及微服务(Eureka Client)向Eureka Server的注册功能。

客户端负载均衡器Ribbon

远程调用即微服务之间相互调用的工作流程为(微服务A调用微服务B):

  1. A、B微服务将自己注册到注册中心
  2. A从注册中心获取B的服务地址
  3. A远程调用B

第二步中,B服务可能部署在多个节点上,因此还需要用到客户端负载均衡器

简介和配置

Ribbon是一个基于HTTP、TCP的客户端负载均衡器。消费方从服务注册中心获知有哪些地址可用,然后再从这些地址中选择一个合适的服务器。客户端负载均衡与服务端负载均衡的区别在于客户端要维护一份服务列表,Ribbon从Eureka Server获取服务列表,Ribbon根据负载均衡算法(如轮询)直接请求到具体的微服务。

使用Ribbon(微服务A调用微服务B)
1 在这个地方,设置两个微服务B,类似上面高可用性Eureka的设置
B01

server:
  port: ${PORT:3000} #服务端口

B02

server:
  port: ${PORT:3001} #服务端口

在这里插入图片描述
2 微服务A和微服务B注册到Eureka Server中
3 在微服务A中添加ribbon依赖
因为要远程调用,选择使用okhttp提供的RestTemplate

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring‐cloud‐starter‐ribbon</artifactId>
</dependency>
<dependency>
	<groupId>com.squareup.okhttp3</groupId>
	<artifactId>okhttp</artifactId>
</dependency>

4 配置微服务A

ribbon:
	MaxAutoRetries: 2 #最大重试次数,当Eureka中可以找到服务,但是服务连不上时将会重试
	MaxAutoRetriesNextServer: 3 #切换实例的重试次数
	OkToRetryOnAllOperations: false #对所有操作请求都进行重试,如果是get则可以,如果是post,put等操作没有实现幂等的情况下是很危险的,所以设置为false
	ConnectTimeout: 5000 #请求连接的超时时间
	ReadTimeout: 6000 #请求处理的超时时间

5 启动B01和B02服务
6 在A服务器的启动类中定义RestTemplate,并使用@LoadBalanced注解

@Bean
@LoadBalanced
public RestTemplate restTemplate() {
	return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
}

7 测试

//负载均衡调用
@Test
public void testRibbon() {
	//服务id
	String serviceId = "SERVICE‐MANAGE";
	for(int i=0;i<3;i++){
		//通过服务id调用
		返回值 = restTemplate.getForEntity("调用B服务的接口url", 返回值类型(XX.class);
		返回值2 = 返回值.getBody();
	}
}

三次调用B服务的接口,会轮询地调用B01和B0服务。

Ribbon核心组件IRule

IRule:根据特点算法从服务列表中选取一个要访问的服务,即Ribbon的负载均衡算法。
负载均衡算法:

  • RoundRobinRule:轮询(默认算法)
  • RandomRule:随机
  • AvailabilityFilteringRule:会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务、并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问
  • WeightedResponseTimeRule:根据平均响应时间计算所有服务的权重,响应时间越快,权重越大,被选中的概率越高,刚启动时,如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够,会切换到WeightedResponseTimeRule
  • RetryRule:先按照RoundRobinRule的策略获取服务,如果某个服务获取失败次数达到阈值,则后续请求不会再访问该方法
  • BestAvailableRule:会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
  • ZoneAvoidanceRule:复合判断server所在区域的性能和server的可用性选择服务器

在A服务器的启动类中添加方法,指定轮询算法:

@Bean
public IRule myRule() {
	return new RandomRule();
}

Feign

简介和配置

Feign是一个声明式Web Service客户端,使用Feign能让编写Web Service客户端更加简单,它的使用方法是定义一个接口,然后在上面添加注解,同时也支持JAX-RS标准的注解。Feign也支持可拔插式的编码器和解码器。Spring Cloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡。

1 在A服务中添加依赖

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring‐cloud‐starter‐openfeign</artifactId>
</dependency>
<dependency>
	<groupId>com.netflix.feign</groupId>
	<artifactId>feign‐okhttp</artifactId>
</dependency>

2 定义Feign接口

@FeignClient(value = "SERVICE-MANAGE") //指定远程调用的服务名
public interface ServerAClient {
    //根据页面id查询页面信息,远程调用cms请求数据
    @GetMapping("远程调用的uri")
    public 返回值类型 find(参数);
}

3 启动类添加@EnableFeignClients注解,启动类启动的时候会扫描带@FeignClient注解的接口,并生成此接口的代理
对象
4 测试

@SpringBootTest
@RunWith(SpringRunner.class)
public class TestFeign {
    @Autowired
    ServerAClient serverAClient ; //接口代理对象,由Feign生成代理对象

    @Test
    public void testRibbon(){
        //发起远程调用
        返回值类型 返回值= serverAClient.find(测试);
    }
}

这样,就能在A服务中调用B服务的接口,不需要注入RestTemplate

Feign工作原理原理

  • 启动类添加@EnableFeignClients注解,Spring会扫描标记了@FeignClient注解的接口,并生成此接口的代理
    对象
  • @FeignClient指定了B服务名称,Feign会从注册中心获取B服务列表,并通过负载均衡算法进行服务调用
  • 在接口方法中使用注解@GetMapping或者其他注解,指定调用的url,Feign将根据url进行远程调用

服务熔断Hystrix

多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其它的微服务,这就是“扇出”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的资源,进而引起系统崩溃,这就是“雪崩效应”。

Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,徐国依赖不可避免的会调用失败,比如超时、异常等,Hystrix能保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。

“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。

熔断机制是应对雪崩效应的一种微服务链路保护机制。当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回响应想。当检测到该节点微服务调用响应正常后恢复调用链路。在SpringCloud框架里,熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5s内20次调用失败就会启动熔断机制。

服务熔断配置
在微服务上引入依赖:

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

在微服务方法上加上注解:

@RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET)
//一旦调用服务方法失败并抛出了错误信息后,会自动调用@HystrixCommand标注好的fallbackMethod调用类中的指定方法
@HystrixCommand(fallbackMethod = "processHystrix_Get")
public String get(@PathVariable("id") Long id)
{
	//调用业务方法

	if (XXX) {
		throw new RuntimeException("null");
	}

	return "xxx";
}
public String processHystrix_Get(@PathVariable("id") Long id)
{
	return "没有没有对应的信息";
}

在启动类上加上注解@EnableCircuitBreaker

Eureka和Zookeeper比较

【注:本节内容来自尚硅谷周阳老师,有几个小细节我进行了改动】

著名的CAP理论提出,一个分布式系统不可能同时满足C(一致性)、A(可用性)和P(分区容错性)。由于分区容错性在分布式系统中必须要保证,因此只能在A和C之间进行权衡(A和C无法同时满足)。
Eureka和Zookeeper重要区别就是Zookeeper保证的是CP、Eureka保证的是AP。

Zookeeper保证CP

当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接down调不可用,也就是说,服务注册功能对可用性的要求要高于一致性。但是Zookeeper会出现服务直接down调不可用的情况,Zookeeper使用了主从结构(部署多个注册服务中心,主节点称为Leader,从节点称为Follower),当Leader因为网络故障与其他节点失去联系时,剩余节点会重写进行Leader选举。问题在于,选举Leader的时间太长,30~120s,且选举期间整个Zookeeper集群是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因网络问题是的Zookeeper集群失去Leader节点是较大概率会发生的,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。【但是Zookeeper使用主从结构,保证了数据的一致性】

Eureka保证AP

Eureka在设计时优先保证可用性。Eureka各个节点是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。Eureka的客户端在向某个Eureka注册时,如果发现连接失败,则会自动切换至其他节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性)只不过查询到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了故障,此时会出现以下几种情况:

  • Eureka不再从注册列表中移除因为长时间没有收到心跳而应该过期的服务
  • Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点上(即保证当前节点依然可用)
  • 网络稳定时,当前实例新的注册信息会被同步到其他节点中

因此,Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像Zookeeper那样使整个注册服务瘫痪。

发布了243 篇原创文章 · 获赞 87 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/IT_10/article/details/104026137
今日推荐