RestTemplate+Ribbon和Feign结合Hystrix调用Eureka注册中心的服务

   Eureka注册中心的服务,有2中调用方式,RestTemplate+Ribbon和Feign。

   首先,我们有一个Eureka注册中心集群(2台机器),这2台机器相互注册,机器上的服务相互同步,保证服务的高可用。

然后有一个服务提供方集群(2台机器),将服务注册到Eureka注册中心集群。

   1.eurekaServer模块,是注册中心集群,分8771,8772端口,分別启动。

#客户端默认连接8761这个端口,如果不指定,则默认启动是8080端口,则客户端也得改为8080端口。
server:
  port: 8771

spring:
    application:
      name: eurekaserver
    profiles: node1
eureka:
  instance:
    hostname: node1
#    preferIpAddress: true //集群是,不要加这个。
  server:
      enableSelfPreservation: false  #关闭自我保护机制,将停掉的服务移除
      eviction-interval-timer-in-ms: 1000 #每1秒清除一次
  client:
    #自身是否注册到eureka服务器
#    registerWithEureka: true
#    是否从eureka服务器获取注册信息
#    fetchRegistry: true
    #8771这个机器上的服务同步到8772,注册中心上的服务信息是相互同步的
    serviceUrl:
      defaultZone: http://node2:8772/eureka/

---
server:
  port: 8772

spring:
    application:
      name: eurekaserver
    profiles: node2
eureka:
  instance:
    hostname: node2
#    preferIpAddress: true
  server:
        enableSelfPreservation: false  #关闭自我保护机制,将停掉的服务移除
        eviction-interval-timer-in-ms: 1000 #每5秒清除一次
  client:
    #自身是否注册到eureka服务器serviceUrl
#    registerWithEureka: true
#    是否从eureka服务器获取注册信息
#    fetchRegistry: true
    #8772这个机器上的服务同步到8771,注册中心上的服务信息是相互同步的
    serviceUrl:
      defaultZone: http://node1:8771/eureka/

   添加依赖:

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

   启动类加注解:

   @EnableEurekaServer

   在模块根目录,运行mvn clean package,进入target目录,分别启动不同配置项的项目。

  2.serviceProvider模块,服务提供方,是服务提供者集群,分8762,8763端口,分別启动。


#默认注册地址
#eureka:
#  client:
#    serviceUrl:
#      defaultZone: http://localhost:8761/eureka/

#management:
#  contextPath: /eurekaclient1

#传给注册中心的实例信息
eureka:
  instance:
    hostname: localhost
#    preferIpAddress: true
    #心跳时间,客户端注册服务元数据注册中心
    leaseRenewalIntervalInSeconds: 1
    leaseExpirationDurationInSeconds: 1
    homePageUrlPath: ${server.servletPath}
    statusPageUrlPath: ${server.servletPath}/info
    healthCheckUrlPath: ${server.servletPath}/health
    #对应"metadata":{"instanceId":"eurekaclient:56929cfd113d3fe33d3d3df34715d780"
    metadataMap:
          instanceId: ${spring.application.name}:${random.value}
  client:
#      fetchRegistry: true #从注册中心获取最新服务,更新本地缓存
#      healthcheck:
#              enabled: true
      serviceUrl:
        defaultZone: http://node1:8771/eureka/,http://node2:8772/eureka/


server:
  port: 8762
#  servletPath: /
spring:
  application:
    name: serviceProvider
  profiles: serviceProvider-1

---
eureka:
  instance:
    hostname: localhost
#    preferIpAddress: true
    #心跳时间,客户端注册服务元数据注册中心
    leaseRenewalIntervalInSeconds: 1
    leaseExpirationDurationInSeconds: 1
    homePageUrlPath: ${server.servletPath}
    statusPageUrlPath: ${server.servletPath}/info
    healthCheckUrlPath: ${server.servletPath}/health
    #对应"metadata":{"instanceId":"eurekaclient:56929cfd113d3fe33d3d3df34715d780"
    metadataMap:
          instanceId: ${spring.application.name}:${random.value}
  client:
#      fetchRegistry: true #从注册中心获取最新服务,更新本地缓存
#      healthcheck:
#              enabled: true
      serviceUrl:
        defaultZone: http://node1:8771/eureka/,http://node2:8772/eureka/


server:
  port: 8763
#  servletPath: /
spring:
  application:
    name: serviceProvider
  profiles: serviceProvider-2


   添加依赖:

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <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>

   启动类加注解:

   @EnableEurekaClient

 跟上面一样的,打包,分别启动2个端口配置项的项目。

 3.服务消费方

   3.1  RestTemplate+Ribbon,serviceConsumerByRibbon模块

         启动类:

@SpringBootApplication
@EnableDiscoveryClient  //发现服务和注册服务
@EnableHystrix  //断路器,对服务的延迟和容错进行兜底处理
@EnableHystrixDashboard //断路器仪表盘,对方法进行监控
@RestController
public class RibbonApplication {
    public static void main(String[] args) {
        SpringApplication.run(RibbonApplication.class, args);
    }

    @Bean
    @LoadBalanced  //必须要加上,它不仅进行负载均衡,默认是轮询调用,还要从注册中心获取服务列表地址
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

    @Autowired
    HelloService helloService;

    @RequestMapping(value = "/hello")
    public String hello(@RequestParam String name) {
        return helloService.hello1(name);
    }
}

   断路器处理类:

@Service
public class HelloService {

    @Autowired
    RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "helloError") //断路器命令
    public String hello1(String name) {
        return restTemplate.getForObject("http://serviceProvider/hello?name=" + name, String.class); //对服务进行动态调用。
    }

    public String helloError(String name) { //服务调用失败的默认处理。
        return "hello," + name + ",error!";
    }
}
   application.yml
   
eureka:
  client:
    serviceUrl:
        defaultZone: http://node1:8771/eureka/,http://node2:8772/eureka/  //注册中心集群
server:
  port: 8764
spring:
  application:
    name: serviceConsumerByRibbon

 添加依赖
  

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

        <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.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
        </dependency>

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

 场景1:服务提供方未启动或者启动了,但服务还没有注册到注册中心,发起调用,断路器做了默认处理

   


       

    场景2:不同端口的服务提供方启动了,我们不停刷新页面。

    


   

可以发现,他们默认是轮询方式调用服务提供方。

场景3:手动停止端口8762的服务提供方,刷新页面,由于注册中心上的服务还没及时更新清除,调用失败,断路器默认处理



过一会,在刷新,就可以正常访问8763的服务了。


断路器监控:输入地址:http://localhost:8764/hystrix,进入页面后,输入http://localhost:8764/hystrix.stream。



PS1:搜狗浏览器可能回出现如下问题,用谷歌就没问题。


PS2.当RestTemplate实例化时,如果没有加@LoadBalanced注解,也会访问失败。因为它获取不到服务地址列表。


3.2 Feign,serviceConsumerByFeign模块

      Feign是只带Ribbon负载均衡特性的。这里我们不用默认的轮询方式,改为按响应时间的权重方式。

  启动类:

@SpringBootApplication
@EnableDiscoveryClient
//改注解包含断路器功能,不包含断路器仪表盘功能
@EnableFeignClients
@RestController
//以下2个注解,是启用仪表盘功能
@EnableHystrixDashboard
//@EnableCircuitBreaker //和下面注解一样,都可以用
@EnableHystrix
public class FeignApplication {

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

    @Autowired
    private HelloService helloService;

    @Bean
    public IRule weightedResponseTimeRule() {
        return new WeightedResponseTimeRule();//这里必须要配置实例化,和配置文件类型对应
    }

    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String hello(@RequestParam String name) {
        return helloService.hello(name);
    }
}

application.yml:

eureka:
  client:
    serviceUrl:
        defaultZone: http://node1:8771/eureka/,http://node2:8772/eureka/ //注册中心集群
server:
  port: 8765
spring:
  application:
    name: serviceConsumerByFeign

feign:
   hystrix:
      enabled: true  //必须要手动打开断路器

serviceprovider: #服务名
  ribbon:
  #按响应时间的权重分配请求,时间越短,权重越大,分配到请求的几率越大
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule

断路器配置:

@FeignClient(value = "serviceProvider",fallback = HelloServiceImpl.class) 
public interface HelloService {
    @RequestMapping(value = "/hello",method = RequestMethod.GET)
    String hello(@RequestParam(value = "name") String name);
}

serviceProvider为服务名,HelloServiceImpl实现了HelloService接口,对应的方法是断路器方法。

 依赖除了上面要添加的外,还要加上:

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

测试场景与上面一样,只不过这里用的是按响应时间权重方式来请求服务。



跟上面一样,进入断路器监控页面:


4.hystrixTurbine断路器聚合监控

  断路器聚合监控也就是将多个应用的断路器监控统一起来监控。

  启动类:

@SpringBootApplication
@EnableHystrixDashboard
@EnableTurbine
public class TurbineApplication {
    public static void main(String[] args) {
        SpringApplication.run(TurbineApplication.class, args);
    }

}

application.yml:

eureka:
  client:
    serviceUrl:
        defaultZone: http://node1:8771/eureka/,http://node2:8772/eureka/
server:
  port: 8001
spring:
  application:
    name: hystrixTurbine


turbine:
  aggregator:
    clusterConfig: default
  clusterNameExpression: new String("default")
  # 要监控的应用名,也是注册到注册中心的服务名
  appConfig: serviceConsumerByFeign,serviceConsumerByRibbon

添加依赖:

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

访问地址:localhost:8001/hystrix,进入页面后,输入:localhost:8001/turbine.stream。

就这么进去,是看不到任何监控信息的。一直显示loading。我们需要分别访问serviceConsumerByFeign,serviceConsumerByRibbon这2个应用的服务才行。



注意:这里spring cloud依赖的版本是Dalston.RC1,不同版本可能有些区别和问题。

源码地址:https://github.com/bawcwchen/ribbonFeignDemo.git

猜你喜欢

转载自blog.csdn.net/bawcwchen/article/details/80557509