SpringCloud(三)服务消费

常见问题

EnableEurekaClient与EnableDiscoveryClient的区别

选用的注册中心是eureka,那么就推荐@EnableEurekaClient,如果是其他的注册中心,那么推荐使用@EnableDiscoveryClient。这个和“Slf4j与Log4j”的道理一样,Log4j可以直接用,也可以通过Slf4j调用Log4j。@EnableDiscoveryClient是通用注解,适用范围更广。

异常:com.netflix.client.ClientException: Load balancer does not have available server for client

如果出现异常:com.netflix.client.ClientException: Load balancer does not have available server for client。

可以关闭wifi后重试,也可以尝试重启Client,或者是适当增加Feign的超时时间。

(一般是因为Maven依赖不够,导致的注册失败问题,如果和我的配置相同,那么,很可能是因为默认的超时时间过短)

正文

前面的文章,我们已经实现了服务中心,并且注册了第一个服务,这里,我们开始调用我们的服务。

相当于Spring中的@Resource注解,Cloud中用的是Feign,下面开始尝试使用它。

 

最直接的调用方式,办法就是写 “服务名” 和 “地址” (如下),这种做法不符合系统架构的设计,不可能调用一个接口写一个这样的代码,

但是或许能成为以后解决问题的一种办法,这里也做个笔记。

@FeignClient(name = "client-a", url = "xxxxx")
public interface PassportServiceApi {
}

 

源码

工程目录(单纯的服务消费,内容太少,索性把服务降级的一些内容加进来)。

 

 

 Maven依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.13.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>cn.seaboot</groupId>
    <artifactId>feign</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>feign</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR5</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <!--hystrix 仪表盘-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</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-netflix-hystrix-dashboard</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</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>

</project>

程序入口

@EnableHystrixDashboard:Hystrix 仪表盘注解;

@EnableDiscoveryClient:把Feign工程也注册成一个Client,A调用B,B调用C,C回头还可能调用A,我们的服务,在调用别人的时候偶,显然也可能被其它系统调用;

@EnableFeignClients:Feign调用其他服务所必需的注解。

package cn.seaboot.feign;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;

@EnableHystrixDashboard
@EnableFeignClients
@SpringBootApplication
@EnableDiscoveryClient
public class FeignApplication {

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

  /**
   * Hystrix仪表盘配置
   */
  @Bean
  public ServletRegistrationBean getServlet() {
    HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
    ServletRegistrationBean<HystrixMetricsStreamServlet> registrationBean = new ServletRegistrationBean<>(streamServlet);
    registrationBean.setLoadOnStartup(1);
    //仪表盘url是可配置的
    registrationBean.addUrlMappings("/hystrix.stream");
    registrationBean.setName("HystrixMetricsStreamServlet");
    registrationBean.setName("HystrixMetricsStreamServlet");
    return registrationBean;
  }
}

Yml配置

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
server:
  port: 8765
spring:
  application:
    name: service-feign

feign:
  #适当的增加超时时间
  client:
    config:
      default:
        connect-timeout: 10000
        read-timeout: 20000
      client-a:
        connect-timeout: 10000
        read-timeout: 20000
  #开启熔断
  hystrix:
    enabled: true

FeignClient

@FeignClient,通过这个注解,说明你要调用的是哪个服务。

name(或者value):指定要调用的服务;

fallback:指定服务降级之后的一些应对信息;

@HystrixCommand:可以根据各种业务需求,定制自己的服务降级策略

package cn.seaboot.feign.services;


import cn.seaboot.feign.def.HelloServiceHystric;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * @author Mr.css
 * @date 2020-03-05
 */
@FeignClient(value = "client-a", fallback = HelloServiceHystric.class)
public interface HelloService {

  /**
   * 这里正常执行,关闭client后,降级服务后返回:sorry hi
   */
  @RequestMapping(value = "/hi", method = RequestMethod.GET)
  String sayHi(@RequestParam(value = "name") String name);


  /**
   * 命令执行超时时间,默认1000ms,这里指定3000
   * client中Thread.sleep(5000); 连接必定超时,降级服务后返回:sorry hello
   */
  @HystrixCommand(commandKey="hello",commandProperties={
      @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="3000")
  })
  @RequestMapping(value = "/hello", method = RequestMethod.GET)
  String sayHello(@RequestParam(value = "name") String name);
}

服务降级

需要继承实现Service的接口,如果网络不通或是其它原因,则直接调用这些实现类。

package cn.seaboot.feign.def;

import cn.seaboot.feign.services.HelloService;
import org.springframework.stereotype.Component;

/**
 * 降级服务
 * @author Mr.css
 * @date 2020-03-05
 */
@Component
public class HelloServiceHystric implements HelloService {
  @Override
  public String sayHi(String name) {
    return "sorry hi";
  }

  @Override
  public String sayHello(String name) {
    return "sorry hello";
  }
}

Controller

与常规代码一致,重点在Service层。

package cn.seaboot.feign.ctrl;

import cn.seaboot.feign.services.HelloService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @author Mr.css
 * @date 2020-03-05
 */
@RestController
public class HiController {

  @Resource
  HelloService helloService;

  @GetMapping(value = "/hi")
  public String sayHi(@RequestParam String name) {
    return helloService.sayHi( name );
  }

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

结果

hi接口正常使用,如果client关闭,就会出现服务降级后的数据

http://localhost:8765/hi?name=forezp

hello接口因为肯定会超时,必定出现服务降级之后的数据

 

http://localhost:8765/hello?name=forezp

 

 

访问下列地址,可以使用Hystrix的管理界面

http://localhost:8765/hystrix

 

 

 

 

 

 

在上面的管理页面中,填入http://localhost:8765/hystrix.stream,点击按钮,即可跳转下列页面

 

posted on 2020-03-25 21:27  疯狂的妞妞  阅读(311)  评论(0编辑  收藏  举报

导航