美文网首页Spring cloud
spring cloud(三)Eureka高可用性+Feign声

spring cloud(三)Eureka高可用性+Feign声

作者: 码农成神 | 来源:发表于2018-12-03 22:41 被阅读27次

    目录

    一、 配置Eureka高可用性介绍

    Eureka服务器没有后端存储,但是注册表中的服务实例必须发送心跳包以保持注册更新,因此可以在内存中完成。Eureka客户端还具有服务注册表缓存,当客户端获取注册表中的服务实例时,会从自己的缓存中获取,客户端的缓存会定时更新,所以当Eureka服务挂了之后,并不会导致客户端找不到需要请求的服务实例。但是当Eureka服务器挂掉之后,原来注册表中的服务发生故障或者更新,这时就会出现危险的情况。我们怎么保证Eureka服务器的高可用性呢?

    Eureka服务器同时也是一个客户端,默认配置下,需要提供一个serviceUrl来同步注册信息,如果不提供这个配置,就会在日志文件中出现大量的错我提示。我们之前通过再Eureka服务器(eureka_server项目)配置eureka.client.registerWithEureka=false,和eureka.client.fetchRegistry=false,关闭了Eureka服务器之间的同步消息,所以上文中介绍的Eureka是以独立模式运行的。为了提高可用性我们需要配置多个Eureka服务器,并让它们之间互相同步注册信息,当其中一个挂掉之后,Eureka客户端会自动切换到另外的Eureka服务器。

    二、配置Eureka并行模式(Peer Awareness)

    1. 修改之间的Eureka服务eureka_server的application.yml

    通过spring boot的profiles机制,定义多个profiles,多个profiles用---分割。当运行服务时可以通过在命令行传参的方式指定使用哪个具体的profiles作为配置。这样我们就可以使用同一个jar文件运行多个不同的服务。下面看application.yml的示例。

    spring:
      application:
        name: eureka-server
    ---
    server:
      port: 8761
    eureka:
      client:
        service-url:
          defaultZone: http://peer2:8762/eureka/
      instance:
        hostname: peer1
    spring:
      profiles: peer1
    ---
    server:
      port: 8762
    eureka:
      client:
        fetch-registry: false
        register-with-eureka: false
        service-url:
          defaultZone: http://peer1:8761/eureka/
      instance:
        hostname: peer2
    spring:
      profiles: peer2
    

    当我们指定profiles为peer1时,我们使用8761运行服务,并将serviceUrl设为peer2,当profiles为peer2时我们使用8762端口运行服务,并接serviceUrl设为peer1。这里需要注意的是,peer1,peer2均为hostname,因为服务都跑在自己的电脑上,所以我在hosts文件里做了如下的映射

    127.0.0.1 peer1 peer2
    

    2. 修改客户端的application.yml

    分别在consume_server和product_server项目的application.yml中,修改serviceUrl增加新的Eureka服务器的地址,示例如下:

    eureka:
      client:
        service-url:
          defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/
    

    3. 运行多个Eureka服务

    方式一: 通过maven打包生成jar之后运行命令java -jar eureka_server-1.0-SNAPSHOT.jar --spring.profiles.active=peer1 && java -jar eureka_server-1.0-SNAPSHOT.jar --spring.profiles.active=peer2
    方式二: 我本人在使用idea作为开发工具,在开发环境下可以通过如下步骤配置多个服务启动器

    1. 点击EditConfigutations


      EditConfigutations
    2. 配置多个SpringBoot启动类


      启动类1
      启动类2

    4. 运行consume_server和product_server并验证是否配置成功

    peer1服务
    peer2服务 访问成功

    到此多实例Eureka服务器完成。一切正常。

    5. 关掉peer1的服务测试是否一切运行正常

    关掉peer1服务
    peer1服务状态
    peer2服务状态
    服务正常访问

    我们可以看到其中一个Eureka挂掉之后,另一个Eureka服务器可以继续为Eureka客户端提供服务。

    6.关掉所有Eureka服务器测试Eureka客户端是否可以通过客户端缓存继续访问原来的服务

    关掉所有Eureka服务
    依旧服务正常
    Eureka客户端报错

    我们可以看到,即使关掉全部的Eureka服务器,Eureka客户端依旧可以依靠自身缓存的注册表继续提供正确的服务。当然如果客户端依赖的服务也停止了,客户端缓存的注册表此时是不会更新的,这时服务就会出错。

    三、配置Feign声明式Rest访问

    还记得上篇文章中我们为了访问服务拼接字符串的操作吗?这时如果涉及的参数非常多手动拼接字符串就会变的异常繁琐。接下来介绍Feign,它可以让我们从拼接字符串的操作中解放出来具体怎么操作,接着看吧。

    1. 在cosume_server项目的pom文件中新增feign的依赖

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

    2. 在启动类新增@ EnableFeignClients注解

    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients
    public class ConsumeApplication {
    
        @Bean
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    
        public static void main(String[] args) {
            SpringApplication.run(ConsumeApplication.class, args);
        }
    }
    

    3. 配置feignclient,并将原先的拼接字符串的请求方式替换为Feign的形式

    先看代码:

    package com.yshmsoft.controller;
    
    import com.yshmsoft.entity.User;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class UserController {
    
        @Autowired
        ProductServerClient productServerClient;
    
        @FeignClient("product-server")
        static interface ProductServerClient {
            @GetMapping("/{id}")
            public User findUserById(@PathVariable("id") Long id);
        }
    
        @GetMapping("/user/{id}")
        User getUserById(@PathVariable Long id) {
            User user = productServerClient.findUserById(id);
            return  user;
        }
    
    }
    

    为了简单起见我以静态内部类的形式定义了Feign客户端ProductServerClient。接下来我一步一步说这些代码都干了什么。

    • @FeignClient注解用来声明此接口为Feign客户端。
    • @FeignClient传入的值为vipaddress也就是我们定义服务的时候提供的spring.application.name=product-server这个地方定义的应用名。
    • @GetMapping spring cloud为我们提供了spring mvc式的feign注解,这个@GetMapping意思就是发送一个get请求,然后请求路径为/{id},这个id就是注解标注的方法里面由@PathVariable("id")标注的参数。
    • 以上都明白之后我们用@Autowired将@FeignClient标注的接口注入到我们的UserController中然后调用productServerClient.findUserById(id)方法,发送请求取得User对象。
      综上当调用了findUserById方法实际上就是发送了一个get请求hostname和port,通过@FeignClient("product-server")传入的值去调用Eureka的client获取。请求的路径为@GetMapping(/{id})注解中的参数,而路径变量id由实际调用findUserById方法时由该方法的参数id去替换。注意@PathVariable("id")中的id在这里不能省略,省略会报错。

    这篇文章我们介绍了如何配置Eureka高可用,如何配置Feign声明式Rest客户端简化请求。接下来,我们需要更详细的了解一下Eureka的配置和Feign的配置,敬请期待。

    相关文章

      网友评论

        本文标题:spring cloud(三)Eureka高可用性+Feign声

        本文链接:https://www.haomeiwen.com/subject/fueucqtx.html