【微服务】- eurka构建与使用

目录

  • 1.eureka基础知识

    • 什么是服务治理
    • 什么是服务注册与发现
  • Eureka包含两个组件: Eureka Server和Eureka Client
    • 1.Eureka Server提供服务注册服务
    • 2.EurekaClient通过注册中心进行访问
    • 用例项目的构架
  • 2.单机eureka的构建
  • 注册一个简单的Eureka单机配置
    • 1.建一个空工程工程
    • 2.添加依赖
    • 3.配置yml文件
    • 4.写主启动类
    • 5.运行
  • 把服务注册到eureka上
    • 1.先在服务pom文件中添加eureka的client依赖
    • 2.在yml文件中注册eureka
    • 3.在服务的主启动类上添加以下注解
  • 3.Eureka集群构建
    • 问题:微服务RPC远程服务调用最核心的是什么
    • 1.搭建eureka集群

      • 建项目,改配置
      • 把其他服务添加人eureka集群
    • 2.搭建服务集群
      • 通过eureka来实现多个微服务之间的调用
      • }
  • 4.完善actuator信息
    • 主机名称服务名称的修改

      • 如何配置
      • 访问ip地址的显示
  • 5.服务发现DisCovery
    • 如何使用
  • 6.eureka自我保护
    • 概述
    • 自我保护机制产生原因
    • 关闭自我保护机制
  • 7.eureka停更

1.eureka基础知识

什么是服务治理

Spring Cloud封装了Neflix公司开发的Eureka模块来实现服务治理

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

什么是服务注册与发现

Eureka采用了CS的设计架构,Eureka Server作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用Eureka的客户端连接到Eureka Server并维持心跳连接。这样系统的维护人员就可以通过Eureka Server 来监控系统中各个微服务是否正常运行。

在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器的信息比如服务地址通讯地址等以别名方式注册到注册中心上。另一方(消费者|服务提供者) ,以该别名的方式去注册中心上获取到实际的服务通讯地址,然后再实现本地RPC调用RPC远程调用框架核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系(服务治理概念)。在任何rpc远程框架中,都会有一个注册中心(存放服务地址相关信息(接口地址))

Eureka包含两个组件: Eureka Server和Eureka Client

1.Eureka Server提供服务注册服务

各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。

2.EurekaClient通过注册中心进行访问

是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、 使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将 会从服务注册表中把这个服务节点移除(默认90秒)

用例项目的构架

2.单机eureka的构建

注册一个简单的Eureka单机配置

1.建一个空工程工程

cloud-server-eureka7001

2.添加依赖

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

    <!--    引入自定义的api通用包,可以使用Payment支付Entity    -->
    <dependency>
        <groupId>wf.springcloud</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>1.0-SNAPSHOT</version>
        <scope>compile</scope>
    </dependency>

    <!-- boot web actuator -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <!--  一般通用配置  -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
    </dependency>
    <!--  热部署      -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <!--   单元测试     -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

</dependencies>

3.配置yml文件

server:
  port: 7001

eureka:
  instance:
#    hostname: eureka7001.com   #eureka服务端的实例名称
    hostname: localhost   #eureka服务端的实例名称
  client:
    register-with-eureka: false   #false表示不向注册中心注册自己
    fetch-registry: false   #false表示自己端就是注册中心
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/   #单机
#      defaultZone: http://eureka7001.com:7001/eureka/   #单机
#      defaultZone: http://eureka7002.com:7002/eureka/  #集群

4.写主启动类

@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7001 {

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

5.运行

出现以下界面说明配置成功

把服务注册到eureka上

1.先在服务pom文件中添加eureka的client依赖

我在父工程已经添加了依赖的版本号,所以此处没有版本号。
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2.在yml文件中注册eureka

eureka:
  client:
    register-with-eureka: true   #是否将自己注册到注册中心,集群必须设置为true配合ribbon
    fetch-registry: true    #是否从服务端抓取已有的注册信息
    service-url:
      defaultZone: http://localhost:7001/eureka #eureka服务器中配置的地址#,http://eureka7002.com:7002/eureka

须注意,如果没有给服务的application命名,那么就需要在yml文件中添加如下配置

spring:
  application:
    name: cloud-order-service

3.在服务的主启动类上添加以下注解

@SpringBootApplication
@EnableEurekaClient
public class OrderMain80 {

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

然后启动eureka服务器,在启动服务就可以在eureka页面看到服务以注册

3.Eureka集群构建

问题:微服务RPC远程服务调用最核心的是什么

高可用,试想你的注册中心只有一个only one,它出故障了那就呵呵(~一)" 了,会导致整个为服务环境不可用,

所以解决办法:搭建Eureka注册中心集群,实现负载均衡+故障容错。

1.搭建eureka集群

因为是在一台机器上模拟集群所以如果想搭好集群先改hosts文件

C:\Windows\System32\drivers\etc目录下修改hosts文件,添加

127.0.0.1       eureka7001.com
127.0.0.1       eureka7002.com
127.0.0.1       eureka7003.com

建项目,改配置

新建cloud-server-eureka7002项目,添加与cloud-server-eureka7001相同的依赖,此处省略。

添加yml文件。

server:
  port: 7002

eureka:
  instance:
    hostname: eureka7002.com   #eureka服务端的实例名称
#    hostname: localhost   #eureka服务端的实例名称
  client:
    register-with-eureka: false   #false表示不向注册中心注册自己
    fetch-registry: false   #false表示自己端就是注册中心
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/   #把7002注册给7001

erueka集群的产生就是多个eureka服务间的相互注册。

同时修改7001的yml文件,把7001注册给7002.

添加启动类,

@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7002 {

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

然后启动两个eureka服务就可发现其集群已经建立。

把其他服务添加人eureka集群

只需要修改yml文件中eureka相关配置即可

eureka:
  client:
    register-with-eureka: true   #是否将自己注册到注册中心,集群必须设置为true配合ribbon
    fetch-registry: true    #是否从服务端抓取已有的注册信息
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka ,http://eureka7002.com:7002/eureka

启动服务。出现以下即可说明成功

2.搭建服务集群

写两个相同的服务,

两个服务功能相同都是简单的查询数据库。然后有一个调用者80来调用8081和8082实现微服务间的调用。8081和8082两个服务之间除了启动类名称不一样其他都相同,简单来说就是把8081进行复制,复制出8082,然后使用 @Value("${server.port}")

@RestController
@Slf4j
public class PaymentController {

    @Resource
    private PaymentService paymentService;

    @Value("${server.port}")
    private String serverport;

    @PostMapping(value = "/payment/creat")
    public CommonResult creat(@RequestBody Payment payment){
        int result = paymentService.creat(payment);

        log.info("插入结果:" + payment);
        if (result > 0){
            return new CommonResult(200,"插入数据成功! port:" + serverport,payment);
        }else {
            return new CommonResult(444,"插入数据失败!",null);
        }
    }

    @GetMapping(value = "/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
        Payment result = paymentService.getPaymentById(id);
        log.info("查询结果:" + result);
        if (result != null){
            return new CommonResult<Payment>(200,"查询成功! port:" + serverport,result);
        }else {
            return new CommonResult<Payment>(444,"查询失败!",null);
        }
    }

}

获取服务端口号,然后在返回在输出。

启动全部服务,出现

两个端口都存在即表示构建成功。

通过eureka来实现多个微服务之间的调用

上面说过8081和8082是服务的提供者,而80是服务的消费者。所以在80服务的controller中

@RestController
@Slf4j
public class OrderController {

    //抛弃之前直接对其他访问的访问,使用eureka中注册的Application来实现多个微服务间的访问
    private final String path = "http://CLOUD-PAYMENT-SERVICE";
    //    private final String path = "http://localhost:8081";
    @Resource
    private RestTemplate template;

    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult getPaymentById(@PathVariable("id") Long id){
        log.info("order执行查询");
        return template.getForObject(path + "/payment/get/"+id,CommonResult.class);
    }

    @GetMapping("/consumer/payment/creat")
    public CommonResult<Payment> creat(Payment payment){
        log.info("order执行插入");
        return template.postForObject(path+"/payment/creat",payment,CommonResult.class);
    }

}

一个小问题

此时如果直接访问会出现错误

因为调用服务提供者集群时存在多个服务eureka不知道该调用哪一个服务,使用此处要使用负载均衡来平衡多个服务间的调用。

在RestTemplate 的bean中添加@LoadBalanced来实现调用集群的有序

@Configuration
public class ApplicationConfig {

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

然后重新启动所以服务,通过80端口访问时出现服务提供者端口号重复变化就说明调用集群成功

第一个访问

第二次访问

第三次访问

轮询调用两个访问,成功

4.完善actuator信息

主机名称服务名称的修改

此时我们的主机名称和服务名称都是暴露出来的,不好我们可以通过一个配置,来让此处显示我们想要显示的名称

如何配置

在yml文件的eureka相关配置添加instance:即可

eureka:
  client:
    register-with-eureka: true   #是否将自己注册到注册中心,集群必须设置为true配合ribbon
    fetch-registry: true    #是否从服务端抓取已有的注册信息
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka ,http://eureka7002.com:7002/eureka
  instance:
    instance-id: payment8081

此时服务名称就被修改了

访问ip地址的显示

在yml文件的eureka相关配置添加instance:即可

eureka:
  client:
    register-with-eureka: true   #是否将自己注册到注册中心,集群必须设置为true配合ribbon
    fetch-registry: true    #是否从服务端抓取已有的注册信息
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka ,http://eureka7002.com:7002/eureka
  instance:
    instance-id: payment8081
    prefer-ip-address: true

修改并重启访问后

5.服务发现DisCovery

作用:对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息

如何使用

服务8081的controller添加(篇幅原因我只把需要添加的部分写了出来,其他如get方法等都面响)

@RestController
@Slf4j
public class PaymentController {
    @Resource
    private DiscoveryClient discoveryClient;

    @GetMapping("/payment/discovery")
    public Object getDisCovery(){
        List<String> services = discoveryClient.getServices();
        for (String service : services) {
            log.info("---server :" + service);
        }
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        for (ServiceInstance instance : instances) {
            log.info(instance.getServiceId() +"\t"+ instance.getHost() +"\t"+ instance.getPort() +"\t"+ instance.getUri());
        }
        return discoveryClient;
    }
}

服务对应地址

可以看到对应信息,添加日志

2020-03-31 22:16:24.249  INFO 12068 --- [nio-8081-exec-4] w.s.controller.PaymentController         : ---server :cloud-payment-service
2020-03-31 22:16:24.249  INFO 12068 --- [nio-8081-exec-4] w.s.controller.PaymentController         : ---server :cloud-order-service
2020-03-31 22:16:24.251  INFO 12068 --- [nio-8081-exec-4] w.s.controller.PaymentController         : CLOUD-PAYMENT-SERVICE	192.168.211.1	8081	http://192.168.211.1:8081
2020-03-31 22:16:24.251  INFO 12068 --- [nio-8081-exec-4] w.s.controller.PaymentController         : CLOUD-PAYMENT-SERVICE	192.168.211.1	8082	http://192.168.211.1:8082

DisCovery可以查看注册服务的具体信息,为了是在eureka中还是其他中间件注册。

6.eureka自我保护

概述

保护模式主要用于一组客户端和Eureka Server之间存在网络分区场景下的保护。一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务。

如果在Eureka Server的首页看到以下这段提示,则说明Eureka进入了保护模式:

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不会立刻清理,依旧会对该微服务的信息进行保存

属于cap中的ap

自我保护机制产生原因

  • 为什么会产生Eureka自我保护机制?

为了防止EurekaClient可以正常运行,但是与EurekaServer网络不通情况下,EurekaServer不会立刻将EurekaClient服务 剔除

  • 什么是自我保护模式?

默认情况下,如果EurekaServer在一 定时间内没有接收到某个微服务实例的心跳,eurekaServer将会注销该实例 (默认90秒) 。但是当网络分区故障发生(延时、卡顿、拥挤)时,微服务与EurekaServer之间无法正常通信,以上行为可能变得非常危险了——因为微服务本身其实是健康的,此时本不应该注销这个微服务。Eureka通过“自我保护模式”来解决这个问题一一当EurekaServer节点在短时间内丢失过多客户端时(可能发生了网络分区故障), 那么这个节点就会进入自我保护模式。

在自我保护模式中,Eureka Server会保护服务注册表中的信息,不再注销任何服务实例。

它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。一句话讲解:好死不如赖活着

综上,自我保护模式是-种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留)也不盲目注销任何健康的微服务。使用自我保护模式,可以让Eureka集群更加的健壮、 稳定。

关闭自我保护机制

服务端配置

server :
#关闭自我保护机制,保证不可用服务被及时踢除
enable-self-preservation: false
eviction- interval -timer-in-ms: 2000

enable-self-preservation: true自我保护机制,eureka默认为true。

eviction- interval -timer-in-ms: 2000服务的默认心跳时间90s此处改为2s。调小是为了更好的观察到现象。

客户端配置

instance :
#Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
lease-renewal - interval - in- seconds : 1
#Eureka服务端在收到最后一次心跳后等待时间上限, 单位为秒默认是90秒),超时将剔除服务
lease - expir ation - durat ion- in- seconds: 2

启动服务端

说明自我保护机制已经关闭

开启eureka客户端

注册成功,关闭客户端,刷新服务端

可以看到服务信息被删除了。

7.eureka停更

eureka在2.0以后不再更新,故如果要使用服务中心不推荐使用eureka,使用zookeeper或阿里的Nacos会比较好一些。

原文地址:https://www.cnblogs.com/wf614/p/12609732.html

时间: 2024-08-01 11:26:31

【微服务】- eurka构建与使用的相关文章

使用Spring Boot构建微服务(文末福利)

本文主要内容 学习微服务的关键特征 了解微服务是如何适应云架构的 将业务领域分解成一组微服务 使用Spring Boot实现简单的微服务 掌握基于微服务架构构建应用程序的视角 学习什么时候不应该使用微服务 软件开发的历史充斥着大型开发项目崩溃的故事,这些项目可能投资了数百万美元.集中了行业里众多的顶尖人才.消耗了开发人员成千上万的工时,但从未给客户交付任何有价值的东西,最终由于其复杂性和负担而轰然倒塌. 这些庞大的项目倾向于遵循大型传统的瀑布开发方法,坚持在项目开始时界定应用的所有需求和设计.这

译:基于Spring Cloud Stream构建和测试 message-driven 微服务

原文链接:https://piotrminkowski.wordpress.com/2018/06/15/building-and-testing-message-driven-microservices-using-spring-cloud-stream/ 作者: Piotr Mińkowski 译者: helloworldtang img Spring Boot和Spring Cloud为您提供了一个利用不同的通信方式快速构建微服务的解决方案.您可以基于Spring Cloud Netfli

15年资深架构师详解:一个大型互联网公司的微服务转型实践

微服务是一个比较大的话题,基于我的过往经历,本文将以 Netflix 为例,分享一个大型互联网公司如何从一个 Monolithic 的 APP 成功转型到微服务.文章主要涉及微服务的产生历史,应用场景,与单片服务区别,微服务带来的技术.企业组织结构等方面挑战,以及如何合理地选择单片服务构架和微服务构架等内容. 微服务的产生历史 如下图,是微服务在 Google 的搜索结果: 自 2014 年以来,微服务开始被关注,搜索的人越来越多,并在 2016 年左右达到顶峰.从地域来看,很多国家都在关注,如

微服务业务开发三个难题-拆分、事务、查询(上)

微服务架构变得越来越流行了.它是模块化的一种方法.它把一整块应用拆分成一个个服务.它让团队在开发大型复杂的应用时更快地交付出高质量的软件.团队成员们可以轻松地接受到新技术,因为他们可以使用最新且推荐的技术栈来实现各自的服务.微服务架构也通过让每个服务都被部署在最佳状态的硬件上而改善了应用的扩展性. 但微服务不是万能的.特别是在 领域模型.事务以及查询这几个地方,似乎总是不能适应拆分.或者说这几块也是微服务需要专门处理的地方,相对于过去的单体架构. 在这篇文章中,我会描述一种开发微服务的方法,这个

springCloud(1):微服务简介

一.什么是微服务 微服务架构风格是一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制(通常用HTTP资源API). 二.微服务架构特性 1.每个微服务可独立运行在自己的进程里 2.一系列独立运行的微服务共同构建起整个系统 3.每个服务为独立的业务开发,一个微服务只关注某个特定的功能,如:订单管理 4.微服务之间通过一些轻量级的通信机制进行通信,例如:通过RESTful API进行调用 5.可以使用不同的语言与数据存储技术 6.全自动的部署机制

【架构】微服务实战:从发布到架构——上篇

微服务实战:从发布到架构——上篇  MaxLeap2016-03-23 10:42 “微服务”是当前软件架构领域非常热门的词汇,能找到很多关于微服务的定义.准则,以及如何从微服务中获益的文章,在企业的实践中去应用“微服务”的资源却很少.本篇文章中,会介绍微服务架构(Microservices Architecture)的基础概念,以及如何在实践中具体应用. 单体架构(Monolithic Architecture ) 企业级的应用一般都会面临各种各样的业务需求,而常见的方式是把大量功能堆积到同一

微服务框架Lagom介绍之一

背景 Lagom是JAVA系下响应式 微服务框架,在阅读本文之前请先阅读微服务架构设计,Lagom与其他微服务框架相比,与众不同的特性包括: 目前,大多数已有的微服务框架关注于简化单个微服务的构建--这是比较容易的一部分内容.Lagom将其扩展到了微服务所构成的系统,这是大型的系统--也是较为困难的一部分内容,因为在这里我们会面临到分布式系统的复杂性. 通信默认是异步的--基于消息和流--但是,如果需要的话,也考虑到了使用其他的方案,如同步的REST. 持久化默认是基于事件的--使用事件溯源Ev

微服务的鉴定与思考

微服务有且仅有一种非常专项的功能,通过远程API来提供系统其余功能.举个例子:试想一下仓库的管理系统,这样的系统中微服务可能提供的一些功能有: 接收库存 计算新的库存该存到什么地方 计算在仓库内将库存运往正确放置点的路线 为仓库员工分配运送路线 接收订单 计算仓库内指定一组订单的拣货路线 为仓库员工分配拣货路线 以上这些功能(可能还会有更多)都是由单个微服务实现的.每个微服务都有单独的运行线程,并且可以独立于其他微服务进行部署.同样每个微服务都有自己的专用数据库,尽管每个微服务都会与其他微服务协

[服务器架构]微服务的深入思考

微服务有且仅有一种非常专项的功能,通过远程API来提供系统其余功能.举个例子:试想一下仓库的管理系统,这样的系统中微服务可能提供的一些功能有: 接收库存 计算新的库存该存到什么地方 计算在仓库内将库存运往正确放置点的路线 为仓库员工分配运送路线 接收订单 计算仓库内指定一组订单的拣货路线 为仓库员工分配拣货路线 以上这些功能(可能还会有更多)都是由单个微服务实现的.每个微服务都有单独的运行线程,并且可以独立于其他微服务进行部署.同样每个微服务都有自己的专用数据库,尽管每个微服务都会与其他微服务协

微服务架构探讨及甲骨文中间件微服务技术解决方案

https://mp.weixin.qq.com/s/IWR_wIh2D-RmPuslR_JnXg 微服务架构探讨及甲骨文中间件微服务技术解决方案 2017-04-12 胡平 甲骨文开发者社区 随着传统企业受到互联网+的冲击,越来越多的企业都在面临业务转型,如何更好地贴近客户以获取更高的客户满意度,如何在企业内部加速供给侧改革,实现更好的供需平衡都是企业在业务转型中需要思考的问题.企业业务转型,离不开底层IT架构的支撑,所以最近很多很火的技术理念不断被大家所谈及,包括微服务架构.DevOps开发