分布式注册中心SpringCloud Eureka

服务治理SpringCloud Eureka

 

什么是服务治理

       在传统rpc远程调用中,服务与服务依赖关系,管理比较复杂,所以需要使用服务治理,管理服务与服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。

 

服务注册与发现

        在服务注册与发现中,有一个注册中心,当服务器启动的时候,会把当前自己服务器的信息 比如 服务地址通讯地址等以别名方式注册到注册中心上。

 另一方(消费者|服务提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,然后在实现本地rpc调用远程。

 

搭建注册中心

Maven依赖信息  

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.0.1.RELEASE</version>

</parent>

<!-- 管理依赖 -->

<dependencyManagement>

<dependencies>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-dependencies</artifactId>

<version>Finchley.M7</version>

<type>pom</type>

<scope>import</scope>

</dependency>

</dependencies>

</dependencyManagement>

<dependencies>

<!--SpringCloud eureka-server -->

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>

</dependency>

</dependencies>

<!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->

<repositories>

<repository>

<id>spring-milestones</id>

<name>Spring Milestones</name>

<url>https://repo.spring.io/libs-milestone</url>

<snapshots>

<enabled>false</enabled>

</snapshots>

</repository>

</repositories>

application.yml

###服务端口号

server:

  port: 8100

###eureka 基本信息配置

eureka:

  instance:

    ###注册到eurekaip地址

    hostname: 127.0.0.1

  client:

    serviceUrl:

      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

###因为自己是为注册中心,不需要自己注册自己

    register-with-eureka: false

###因为自己是为注册中心,不需要检索服务

    fetch-registry: false

 

启动Eureka服务

@EnableEurekaServer

@SpringBootApplication

public class AppEureka {

 

public static void main(String[] args) {

SpringApplication.run(AppEureka.class, args);

}

 

}

@EnableEurekaServer作用:开启eurekaServer

 

注册服务提供者

项目案例:实现会员服务(提供者)springcloud-2.0-member调用订单服务(消费者)springcloud-2.0-order

 

Maven依赖信息

 

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.0.1.RELEASE</version>

</parent>

<!-- 管理依赖 -->

<dependencyManagement>

<dependencies>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-dependencies</artifactId>

<version>Finchley.M7</version>

<type>pom</type>

<scope>import</scope>

</dependency>

</dependencies>

</dependencyManagement>

<dependencies>

<!-- SpringBoot整合Web组件 -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

<!-- SpringBoot整合eureka客户端 -->

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>

</dependency>

</dependencies>

<!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->

<repositories>

<repository>

<id>spring-milestones</id>

<name>Spring Milestones</name>

<url>https://repo.spring.io/libs-milestone</url>

<snapshots>

<enabled>false</enabled>

</snapshots>

</repository>

</repositories>

 

application.yml

###服务启动端口号

server:

  port: 8000

###服务名称(服务注册到eureka名称)  

spring:

    application:

        name: app-itmayiedu-member

###服务注册到eureka地址

eureka:

  client:

    service-url:

           defaultZone: http://localhost:8100/eureka

 

           

###因为该应用为注册中心,不会注册自己

    register-with-eureka: true

###是否需要从eureka上获取注册信息

    fetch-registry: true

 

 

 

服务接口

@RestController

public class MemberController {

 

@RequestMapping("/getMember")

public String getMember() {

return "this is getMember";

}

}

 

 

启动会员服务

@SpringBootApplication

@EnableEurekaClient

public class AppMember {

 

public static void main(String[] args) {

SpringApplication.run(AppMember.class, args);

}

 

}

 

可以看到会员服务成功注册到eureka服务上

 

 

服务消费者  

 

Maven依赖信息

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.0.1.RELEASE</version>

</parent>

<!-- 管理依赖 -->

<dependencyManagement>

<dependencies>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-dependencies</artifactId>

<version>Finchley.M7</version>

<type>pom</type>

<scope>import</scope>

</dependency>

</dependencies>

</dependencyManagement>

<dependencies>

<!-- SpringBoot整合Web组件 -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

<!-- SpringBoot整合eureka客户端 -->

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>

</dependency>

 

</dependencies>

<!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->

<repositories>

<repository>

<id>spring-milestones</id>

<name>Spring Milestones</name>

<url>https://repo.spring.io/libs-milestone</url>

<snapshots>

<enabled>false</enabled>

</snapshots>

</repository>

</repositories>

 

Application.yml配置

###服务启动端口号

server:

  port: 8001

###服务名称(服务注册到eureka名称)  

spring:

    application:

        name: app-itmayiedu-order

###服务注册到eureka地址

eureka:

  client:

    service-url:

           defaultZone: http://localhost:8100/eureka

 

           

###因为该应用为注册中心,不会注册自己

    register-with-eureka: true

###是否需要从eureka上获取注册信息

    fetch-registry: true

 

使用rest方式调用服务

@RestController

public class OrderController {

@Autowired

private RestTemplate restTemplate;

 

@RequestMapping("/getorder")

public String getOrder() {

// order 使用rpc 远程调用技术 调用 会员服务

String memberUrl = "http://app-itmayiedu-member/getMember";

String result = restTemplate.getForObject(memberUrl, String.class);

System.out.println("会员服务调用订单服务,result:" + result);

return result;

}

 

}

 

启动消费者服务

@SpringBootApplication

@EnableEurekaClient

public class AppOrder {

 

public static void main(String[] args) {

SpringApplication.run(AppOrder.class, args);

}

 

@Bean

@LoadBalanced

RestTemplate restTemplate() {

return new RestTemplate();

}

 

}

 

 

@LoadBalanced就能让这个RestTemplate在请求时拥有客户端负载均衡的能力

 

高可用注册中心

 

在微服务中,注册中心非常核心,可以实现服务治理,如果一旦注册出现故障的时候,可能会导致整个微服务无法访问,在这时候就需要对注册中心实现高可用集群模式。

 

Eureka高可用原理

默认情况下Eureka是让服务注册中心,不注册自己

###因为该应用为注册中心,不会注册自己

    register-with-eureka: true

###不需要去注册中心上检索服务

    fetch-registry: true

Eureka高可用实际上将自己作为服务向其他服务注册中心注册自己,这样就可以形成一组相互注册的服务注册中心,从而实现服务清单的互相同步,达到高可用效果。

 

 

Eureka集群环境搭建

 

Eureka01配置

###服务端口号

server:

  port: 8100

###eureka 基本信息配置

spring: 

 application: 

  name: eureka-server

eureka:

  instance:

    ###注册到eurekaip地址

    hostname: 127.0.0.1

  client:

    serviceUrl:

      defaultZone: http://127.0.0.1:8200/eureka/

    register-with-eureka: true

    fetch-registry: true

 

Eureka02配置

 

###服务端口号

server:

  port: 8200

###eureka 基本信息配置

spring: 

 application: 

  name: eureka-server

eureka:

  instance:

    ###注册到eurekaip地址

    hostname: 127.0.0.1

  client:

    serviceUrl:

      defaultZone: http://127.0.0.1:8100/eureka/

    register-with-eureka: true

    fetch-registry: true

 

 

客户端集成Eureka集群

 

server:

  port: 8000

spring:

  application:

    name: app-itmayiedu-member

#eureka:

#  client:

#    service-url:

#      defaultZone: http://localhost:8100/eureka

###集群地址

eureka:

  client:

    service-url:

           defaultZone: http://localhost:8100/eureka,http://localhost:8200/eureka    

    register-with-eureka: true

    fetch-registry: true

Maven配置

 

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.0.1.RELEASE</version>

</parent>

<!-- 管理依赖 -->

<dependencyManagement>

<dependencies>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-dependencies</artifactId>

<version>Finchley.M7</version>

<type>pom</type>

<scope>import</scope>

</dependency>

</dependencies>

</dependencyManagement>

<dependencies>

<!--SpringCloud eureka-server -->

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>

</dependency>

</dependencies>

<!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->

<repositories>

<repository>

<id>spring-milestones</id>

<name>Spring Milestones</name>

<url>https://repo.spring.io/libs-milestone</url>

<snapshots>

<enabled>false</enabled>

</snapshots>

</repository>

</repositories>

 

Eureka详解

服务消费者模式

获取服务

    消费者启动的时候,使用服务别名,会发送一个rest请求到服务注册中心获取对应的服务信息,让后会缓存到本地jvm客户端中,同时客户端每隔30秒从服务器上更新一次。可以通过 fetch-inte vall-seconds=30参数进行修以通过eureka.client .registry该参数默认值为30, 单位为秒。

 

服务下线

    在系统运行过程中必然会面临关闭或重启服务的某个实例的情况,在服务关闭期有我们自然不希望客户端会继续调用关闭了的实例。所以在客户端程序中,当服务实例过正常的关闭操作时,它会触发一个服务下线的REST请求给Eureka Server, 告诉服务日中心:“我要下线了”。服务端在接收到请求之后,将该服务状态置为下线(DOWN),井该下线事件传播出去。

 

服务注册模式

 失效剔除

      有些时候,我们的服务实例并不一定会正常下线,可能由于内存溢出、网络故障气因使得服务不能正常工作,而服务注册中心并未收到“服务下线”的请求。为了从服务表中将这些无法提供服务的实例剔除,Eureka Server 在启动的时候会创建一个定时任多默认每隔一一段时间(默认为60秒)将当前清单中超时(默认为90秒)没有续约的服务除出去

 自我保护

      默认情况下,EurekaClient会定时向EurekaServer端发送心跳,如果EurekaServer在一定时间内没有收到EurekaClient发送的心跳,便会把该实例从注册服务列表中剔除(默认是90秒),但是在短时间内丢失大量的实例心跳,这时候EurekaServer会开启自我保护机制,Eureka不会踢出该服务。

 

产生的原因:

    在开发测试时,需要频繁地重启微服务实例,但是我们很少会把eureka server一起重启(因为在开发过程中不会修改eureka注册中心),当一分钟内收到的心跳数大量减少时,会触发该保护机制。可以在eureka管理界面看到Renews threshold和Renews(last min),当后者(最后一分钟收到的心跳数)小于前者(心跳阈值)的时候,触发保护机制,会出现红色的警告:

 

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

      从警告中可以看到,eureka认为虽然收不到实例的心跳,但它认为实例还是健康的,eureka会保护这些实例,不会把它们从注册表中删掉。

      该保护机制的目的是避免网络连接故障,在发生网络故障时,微服务和注册中心之间无法正常通信,但服务本身是健康的,不应该注销该服务,如果eureka因网络故障而把微服务误删了,那即使网络恢复了,该微服务也不会重新注册到eureka server了,因为只有在微服务启动的时候才会发起注册请求,后面只会发送心跳和服务列表请求,这样的话,该实例虽然是运行着,但永远不会被其它服务所感知。所以,eureka server在短时间内丢失过多的客户端心跳时,会进入自我保护模式,该模式下,eureka会保护注册表中的信息,不在注销任何微服务,当网络故障恢复后,eureka会自动退出保护模式。自我保护模式可以让集群更加健壮。

      但是我们在开发测试阶段,需要频繁地重启发布,如果触发了保护机制,则旧的服务实例没有被删除,这时请求有可能跑到旧的实例中,而该实例已经关闭了,这就导致请求错误,影响开发测试。所以,在开发测试阶段,我们可以把自我保护模式关闭,只需在eureka server配置文件中加上如下配置即可:

    但在生产环境,不会频繁重启,所以,一定要把自我保护机制打开,否则网络一旦终端,就无法恢复。

    当然关于自我保护还有很多个性化配置,这里不详细说明。

    注意考虑网络不可达情况下:调用接口幂等、重试、补偿等。

 

 

关闭服务保护

Eureka服务器端配置

###服务端口号

server:

  port: 8100

##定义服务名称

spring:

  application:

    name: app-itmayiedu-eureka

eureka:

  instance:

    ###注册中心ip地址

    hostname: 127.0.0.1

  client:

    serviceUrl:

    ##注册地址

      defaultZone: http://${eureka.instance.hostname}:8100/eureka/

    ####因为自己是注册中心,是否需要将自己注册给自己的注册中心(集群的时候是需要是为true)

    register-with-eureka: false

    ###因为自己是注册中心, 不需要去检索服务信息

    fetch-registry: false

  server:

    # 测试时关闭自我保护机制,保证不可用服务及时踢出

    enable-self-preservation: false

    eviction-interval-timer-in-ms: 2000

 

 

核心配置

  server:

    # 测试时关闭自我保护机制,保证不可用服务及时踢出

    enable-self-preservation: false

    ##剔除失效服务间隔

    eviction-interval-timer-in-ms: 2000

 

Eureka客户端配置

###订单服务的端口号

server:

  port: 8001

###服务别名----服务注册到注册中心名称

spring:

  application:

    name: app-itmayiedu-order

eureka:

  client:

    service-url:

    ##### 当前会员服务注册到eureka服务地址

#      defaultZone: http://localhost:8100/eureka,http://localhost:9100/eureka

       defaultZone: http://localhost:8100/eureka

    ### 需要将我的服务注册到eureka上

    register-with-eureka: true

    ####需要检索服务

    fetch-registry: true

    registry-fetch-interval-seconds: 30

# 心跳检测检测与续约时间

# 测试时将值设置设置小些,保证服务关闭后注册中心能及时踢出服务

  instance:

###Eureka客户端向服务端发送心跳的时间间隔,单位为秒(客户端告诉服务端自己会按照该规则)  

    lease-renewal-interval-in-seconds: 1

####Eureka服务端在收到最后一次心跳之后等待的时间上限,单位为秒,超过则剔除(客户端告诉服务端按照此规则等待自己)

    lease-expiration-duration-in-seconds: 2    

 

核心配置

# 心跳检测检测与续约时间

# 测试时将值设置设置小些,保证服务关闭后注册中心能及时踢出服务

  instance:

###Eureka客户端向服务端发送心跳的时间间隔,单位为秒(客户端告诉服务端自己会按照该规则)  

    lease-renewal-interval-in-seconds: 1

####Eureka服务端在收到最后一次心跳之后等待的时间上限,单位为秒,超过则剔除(客户端告诉服务端按照此规则等待自己)

    lease-expiration-duration-in-seconds: 2    

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值