Spring Cloud Eureka 详述(一)(下)

本文涉及的产品
传统型负载均衡 CLB,每月750个小时 15LCU
应用型负载均衡 ALB,每月750个小时 15LCU
EMR Serverless StarRocks,5000CU*H 48000GB*H
简介: Spring cloud eureka是Spring cloud netfilx中的一部分,它基于Netflix Eureka做了二次封装,主要职责完成Eureka 中的服务治理功能

注册服务提供者

在完成了上述搭建之后,接下来我们尝试将一个既有的SpringBoot应用加入Eureka服务治理体系去。

使用上一小节的快速入门工程进行改造,将其作为一个微服务应用向服务注册中心发布注册自己

pom.xml配置如下:

<parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>1.3.7.RELEASE</version>
       <relativePath/> <!-- lookup parent from repository -->
   </parent>
   <properties>
       <java.version>1.8</java.version>
   </properties>
   <dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-eureka</artifactId>
       </dependency>
   </dependencies>
   <dependencyManagement>
       <dependencies>
           <dependency>
               <groupId>org.springframework.cloud</groupId>
               <artifactId>spring-cloud-dependencies</artifactId>
               <version>Brixton.SR5</version>
               <type>pom</type>
               <scope>import</scope>
           </dependency>
       </dependencies>
   </dependencyManagement>
    <build>
       <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
           </plugin>
       </plugins>
   </build>
  • 配置完pom.xml,我们需要在启动类上加入@EnableDiscoverClient注解,用于开启eureka-client客户端
  • application.properties中加入如下内容

# 这个名字就是Eureka注册中新的实例名称

spring.application.name=server-provider

# 向注册中心注册自己

eureka.client.service-url.defaultZone=http://localhost:1111/eureka/

  • 配置完上面两个之后,在package文件夹下新建HelloController类,具体代码如下
@RestController
 public class HelloController {
     private final Logger log = LoggerFactory.getLogger(HelloController.class);
     @Resource
     private DiscoveryClient discoveryClient;
     @RequestMapping(value = "hello", method = RequestMethod.GET)
     public String hello(){
         ServiceInstance instance = discoveryClient.getLocalServiceInstance();
         log.info("instance.host = " + instance.getHost() + " instance.service = " +  instance.getServiceId()
                 + " instance.port = " + instance.getPort());
         return "Hello World";
    }
}
  • 启动服务提供者,启动完成后,会出现如下表示启动成功。

9.jpg

访问http://localhost:1111/ ,主页上显示eureka-provider注册到了注册中心

10.jpg


此处的Status 中的内容也就包括上面配置的spring.application.name=server-provider

  • 在主页访问 http://localhost:8080/hello ,发现页面上 输出了Hello World,控制台打印出来了

c.s.provider.controller.HelloController : instance.host=macliuinstance.service=server-providerinstance.port=8080

  • 注意事项
  1. 上面注册到注册中心的图,你会发现这样一行红色的文字

EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.

这是Eureka的一种自我保护机制,Eureka Server在运行期间,会统计心跳失败的比例在15分钟之内是否低于85%,如果出现低于的情况(在单机调试的时候很容易满足,实际在生产环境上通常是由于网络不稳定导致),Eureka Server会将当前的实例注册信息保护起来,同时提示这个警告。

Eureka server和client之间每隔30秒会进行一次心跳通信,告诉server,client还活着

  1. 把上面的server-provider服务停止之后,会出现如下状态

11.jpg

这个表示server-provider 已经标记为下线,也就是 DOWN 状态,再次重新上线后,发现Status又变为了UP状态。

  1. 把上面的配置文件中自我保护功能关闭后,出现如下状态

12.jpg

高可用配置中心

在微服务架构这样的分布式环境中,需要充分考虑到发生故障的情况,所以在生产环境中必须对各个组件进行高可用部署,对于微服务是如此,对于注册中心也一样。

Eureka Server的设计就充分考虑了高可用问题,在Eureka的服务治理体系中,所有的节点既是服务提供方,也是服务的消费者,服务注册中心也不例外,不同的注册中心在向其他注册中心提供节点列表的时候,也在向其他注册中心获取节点列表。

高可用的配置中心就是向其他注册中心注册自己,同时把服务列表提供给其他注册中心,从而达到注册中心列表同步,达到高可用的效果。通过下面两个配置来实现

eureka.client.register-with-eureka=true

eureka.client.fetch-registry=true

下面就在单节点的基础之上创建一下高可用的配置中心(双节点注册中心)

  • 首先,创建两个配置文件,分别是application-peer1.propertiesapplication-peer2.properties,内容分别如下
  • application-peer1.properties
spring.application.name=eureka-server
server.port=1111
eureka.instance.hostname=peer1
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.client.service-url.defaultZone=http://peer2:1112/eureka/
  • application-peer2.properties
spring.application.name=eureka-server
server.port=1112
eureka.instance.hostname=peer2
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.client.service-url.defaultZone=http://peer1:1111/eureka/


  • 在本地修改配置文件/etc/hosts ,Windows下面是C:\Winows\System32\drivers\etc\hosts。
    添加如下内容
127.0.0.1 peerl
127.0.0.1 peer2
  • 如下:

13.jpg


  • 首先在idea 或者eclipse 使用mvn clean 和 mvn install命令,会直接打包,这里注意,一定要在pom.xml中配置如下,否则使用java -jar会报没有主清单属性的错误。
<build>
       <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
           </plugin>
       </plugins>
</build>
  • 打包完成后,切换到eureka-server项目,再切换到target目录下,此时有mvn install 的jar包,使用java -jar eureka-server-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer1java -jar eureka-server-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer2 两个命令,启动两个例程。起来过后分别访问 http://localhost:peer1/eureka/http://localhost:peer2/eureka/ 主页,发现对应的注册中心分别注册进去了,而且分片也处于可用分片状态。

14.jpg15.jpg


到现在为止,我们已经让两个注册中心分别注册各自的服务了,还记得上面还有一个server-provider服务吗?我们也让server-provider分别注册到这两个注册中心。

server-provider中修改对应的配置文件

eureka.client.service-url.defaultZone=http://peer1:1111/eureka, http://peer2:1112/eureka/

启动程序,发现http://localhost:1111/http://localhost:1112/ 中都注册了server-provider服务

16.jpg


访问http://localhost:8080/hello,你会发现页面上显示出来hello world,断开其中的任意一个注册中心,hello world也能够显示出来。也就是说,server-provider 分别对两个注册中心分别注册了各自的服务,由两个注册中心以轮询的方式提供服务。断开其中一个注册中心,还有另外一个注册中心可以提供服务,这也是Eureka 高可用的体现。


注意事项

  1. 如果application-peer1.propertiesapplication-peer2.properties中的eureka.instance.hostname与 本地hosts文件中的名称不一致的话,那么注册中心启动后,会使分片处于不可用的状态, spring.application.name 表示的是实例的名称,也就是如下的地方

  2. server-provider注册进来的时候,高可用配置的注册中心会以轮询的方式提供服务,每次提供服务是哪个注册中心是不可预知的。
  3. 如我们不想使用主机名来定义注册中心的地址,也可以使用IP地址的形式, 但是需要在配置文件中增加配置参数eureka.instance.prefer-ip-address=true, 该值默认为false。

服务发现与消费

通过上述的内容介绍与实践,我们已经搭建起来微服务架构中的核心组件— 服务注册中心(包括单节点模式和高可用模式)。并用server-provider注册双节点,在页面上发起一个url请求时,注册中心找到server-provider,并有两个节点以轮询的方式提供服务。

下面就来构建一个消费者,它主要完成两个目标:发现服务消费服务。其中,服务发现的任务由Eureka客户端完成,消费服务的任务由Ribbon来完成。

先来熟悉一下什么是Ribbon:Ribbon是客户端负载均衡器,可以让您对HTTP和TCP客户端的行为进行控制。 Feign已经使用了Ribbon,如果你使用了@FeignClient,那么Ribbon也适用。

Ribbon可以在通过客户端中配置的ribbonServerList服务端列表去轮询访问以达到负载均衡的效果。当ribbonEureka联合使用时,Ribbon的服务实例清单RibbonServerList会被DiscoveryEnabledNIWSServerList重写,扩展成从Eureka注册中心中获取服务端列表。同时它也会用NIWSDiscoveryPing来取代Ping,它将职责委托给Eureka来确定服务端是否启动,我们目前不细致探讨Ribbon的细节问题。

下面通过一个简单的实例,看看Eureka的服务治理体系下如何实现服务的发现与消费。

  • 首先,先做一些准备工作,启动之前实现的服务注册中心eureka-server以及server-provider服务,为了实现ribbon的负载均衡功能,我们通过java -jar命令行的方式来启动两个不同端口的server-provider
  • 启动一个eureka-server即可
  • 使用java -jar service-provider-0.0.1-SNAPSHOT.jar --server.port=8081java -jar service-provider-0.0.1-SNAPSHOT.jar --server.port=8082 来启动两个server-provider 进程
  • 启动完成后,可见注册中心注册了两个server-provider 实例

17.jpg

  • 新创建一个SpringBoot 工程,命名为ribbon-consumer,相较于之前pom.xml,我们新增了spring-cloud-starter-ribbon
<parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>1.3.7.RELEASE</version>
       <relativePath/> <!-- lookup parent from repository -->
   </parent>
   <properties>
       <java.version>1.8</java.version>
   </properties>
   <dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-eureka</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-ribbon</artifactId>
       </dependency>
   </dependencies>
   <dependencyManagement>
       <dependencies>
           <dependency>
               <groupId>org.springframework.cloud</groupId>
               <artifactId>spring-cloud-dependencies</artifactId>
               <version>Brixton.SR5</version>
               <type>pom</type>
               <scope>import</scope>
           </dependency>
       </dependencies>
   </dependencyManagement>
   <build>
       <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
           </plugin>
       </plugins>
   </build>
  • 创建完pom.xml,在ribbon-consumer 启动类加上@EnableDiscoveryClient注解,让该注解注册为Eureka客户端,以获得服务发现的能力,同时,创建RestTemplate对象,加上@LoadBalance注解开启负载均衡。
@EnableDiscoveryClient
 @SpringBootApplication
 public class RibbonConsumerApplication {
     @Bean
     @LoadBalanced
     RestTemplate restTemplate(){
         return new RestTemplate();
    }
     public static void main(String[] args) {
         SpringApplication.run(RibbonConsumerApplication.class, args);
    }
}
  • 在src目录下新建一个RibbonController类,注入@RestTemplate,构造一个方法来调用server-provider中的/hello 方法。代码如下
@RestController
   public class RibbonController {
       @Autowired
       RestTemplate restTemplate;
       @RequestMapping(value = "/ribbon-consumer",method = RequestMethod.GET)
       public String helloConsumer(){
           return restTemplate.getForEntity("http://server-provider/hello",String.class).getBody();
      }
  }

在helloConsumer方法上面采用Restful 风格的编码方式,这个方法远程调用了server-provider中的hello方法,在这里不像是http://ip:端口号这种书写方式,而是直接采用 服务名/方法名来直接调用方法,因为你不知道具体的方法在哪个ip的机器上,需要由Eureka进行调用,这样消费者就不用关心由谁提供了服务,只要提供了服务即可,这也是面向对象方法的一种体现,同时也能很好的解耦。

  • application.properties 配置如下

spring.application.name=ribbon-consumer

server.port=9000


eureka.client.service-url.defaultZone=http://localhost:1111/eureka/

因为ribbon-consumer需要由客户端来主动调用方法,所以需要提供实例名称,端口号,并在注册中心注册ribbon-consumer服务

  • 启动服务,访问Eureka主页发现Ribbon-consumer的服务也注册进来了。

18.jpg

  • 通过在url 请求地址 http://localhost:9000/ribbon-consumer发起GET请求,成功返回了Hello World,此时,我们在控制台看到了如下的信息

INFO29397--- [nio-9000-exec-1] c.n.l.DynamicServerListLoadBalancer     : DynamicServerListLoadBalancerforclientserver-providerinitialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=server-provider,currentlistofServers=[macliu:8082, macliu:8081],Loadbalancerstats=Zonestats: {defaultzone=[Zone:defaultzone;Instancecount:2;Activeconnectionscount: 0;Circuitbreakertrippedcount: 0;Activeconnectionsperserver: 0.0;]

},Serverstats: [[Server:macliu:8082;Zone:defaultZone;TotalRequests:0;Successiveconnectionfailure:0;Totalblackoutseconds:0;Lastconnectionmade:ThuJan0108:00:00CST1970;Firstconnectionmade: ThuJan0108:00:00CST1970;ActiveConnections:0;totalfailurecountinlast (1000) msecs:0;averageresptime:0.0;90percentileresptime:0.0;95percentileresptime:0.0;minresptime:0.0;maxresptime:0.0;stddevresptime:0.0]

, [Server:macliu:8081;Zone:defaultZone;TotalRequests:0;Successiveconnectionfailure:0;Totalblackoutseconds:0;Lastconnectionmade:ThuJan0108:00:00CST1970;Firstconnectionmade: ThuJan0108:00:00CST1970;ActiveConnections:0;totalfailurecountinlast (1000) msecs:0;averageresptime:0.0;90percentileresptime:0.0;95percentileresptime:0.0;minresptime:0.0;maxresptime:0.0;stddevresptime:0.0]

]}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@3dc2c2eb

再尝试刷新几次url,因为我们实在后台启动的程序,在终端会看到如下的信息

INFO28929--- [nio-8082-exec-3] c.s.provider.controller.HelloController : instance.host=macliuinstance.service=server-providerinstance.port=8082

因为开了两个终端,一个是8081端口,一个是8082端口,多刷新几次页面后,会发现终端在循环输出上面的信息,来判断使用ribbon 实现了负载均衡。

相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
4月前
|
监控 负载均衡 Java
深入理解Spring Cloud中的服务网关
深入理解Spring Cloud中的服务网关
|
1月前
|
负载均衡 算法 Nacos
SpringCloud 微服务nacos和eureka
SpringCloud 微服务nacos和eureka
59 0
|
2月前
|
负载均衡 Java Nacos
SpringCloud基础1——远程调用、Eureka,Nacos注册中心、Ribbon负载均衡
微服务介绍、SpringCloud、服务拆分和远程调用、Eureka注册中心、Ribbon负载均衡、Nacos注册中心
SpringCloud基础1——远程调用、Eureka,Nacos注册中心、Ribbon负载均衡
|
4月前
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
Spring Cloud Alibaba 发布了 Scheduling 任务调度模块 [#3732]提供了一套开源、轻量级、高可用的定时任务解决方案,帮助您快速开发微服务体系下的分布式定时任务。
14933 31
|
3月前
|
负载均衡 监控 Java
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
|
4月前
|
负载均衡 Java Spring
Spring cloud gateway 如何在路由时进行负载均衡
Spring cloud gateway 如何在路由时进行负载均衡
489 15
|
4月前
|
Java Spring
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
111 3
|
3月前
|
缓存 Java Maven
SpringCloud基于Eureka的服务治理架构搭建与测试:从服务提供者到消费者的完整流程
Spring Cloud微服务框架中的Eureka是一个用于服务发现和注册的基础组件,它基于RESTful风格,为微服务架构提供了关键的服务注册与发现功能。以下是对Eureka的详细解析和搭建举例。
|
4月前
|
消息中间件 Java 开发者
Spring Cloud微服务框架:构建高可用、分布式系统的现代架构
Spring Cloud是一个开源的微服务框架,旨在帮助开发者快速构建在分布式系统环境中运行的服务。它提供了一系列工具,用于在分布式系统中配置、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态等领域的支持。
183 5