SpringCloud(三):Feign声明式服务调用

/ SpringCloud / 0 条评论 / 492人围观

Feign(基于https协议)不仅有Ribbon的负载均衡功能,也有Hystrix的熔断功能,并且比Ribbon调用接口的方式更加简便明了,所以不再介绍Ribbon。

远程调用

  1. 首先准备好Provider和Consumer以及一个注册中心。
  2. 被调用方无需做任何改变,调用方则需要在启动类上加@EnableFeignClients,来表明它是一个服务的消费者。
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class StoryConsumerApplication {

	public static void main(String[] args) {
		SpringApplication.run(StoryConsumerApplication.class, args);
	}
}
  1. 在不低于启动类的目录任意位置下创建接口,并加注解@FeignClient(value = "Server-Provider"),其中value代表远程生产者的服务名称(也就是配置文件中的spring.application.name)。
/**
 * description
 *
 * @author 70KG
 * @date 2018/10/26
 */
@FeignClient(value = "Server-Provider")
public interface IFeignService {

    /**
     * Description: 测试feign通讯
     * Author:70KG
     * Return void
     * Date 2018/10/26 15:08
     */
    @RequestMapping(value = "/getInfomations")
    String getInfoByFeign(@RequestParam(value = "param") String param);

//    @RequestMapping(value = "/saveAnswerToRedis")
//    void saveAnswerToRedis(@RequestBody(required = false) TwoPhaseDTO twophasedto);
}
  1. 编写Controller,注入接口即可。
/**
 * description
 *
 * @author 70KG
 * @date 2018/10/26
 */

@RestController
public class TestController {

    @Autowired
    private IFeignService feignService;

    @RequestMapping("/getInfo")
    public String testFeign() {
        return feignService.getInfoByFeign("world");
    }

}
  1. 启动三个服务,地址栏输入消费者(消费者端口及路径)定义好的方法(https://localhost:8081/getInfo),返回helloworld,ok成功。

负载均衡

将Provider原封不动的复制一份,但服务名字一定要一致,改一个端口号,启动服务即可,默认的负载策略是轮询。

服务熔断降级

说白了,熔断器就类似于常用的保险丝,当电压过大的时候,会把保险丝烧掉,从而断电,而熔断器也是一样,请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务. 断路器保持在开路状态一段时间后(默认5秒), 自动切换到半开路状态(HALF-OPEN). 这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN)。

Fallback相当于是降级操作. 对于查询操作, 我们可以实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值. fallback方法的返回值一般是设置的默认值或者来自缓存。

编写FallBack类

此类实现Feign接口,其中返回值是我们自己定义好的,如下:

/**
 * @author 70KG
 * @Title: FeignServiceImpl
 * @Description: 熔断器
 * @date 2018/10/27下午8:33
 * @From www.nmyswls.com
 */
@Component
public class FeignServiceImpl implements IFeignService {

    @Override
    public String getInfoByFeign(String param) {
        return "I'm sorry,provider is down!";
    }
}

接口注解

/**
 * description
 *
 * @author 70KG
 * @date 2018/10/26
 */
@FeignClient(value = "Server-Provider", fallback = FeignServiceImpl.class)
public interface IFeignService {

    /**
     * Description: 测试feign通讯
     * Author:70KG
     * Return void
     * Date 2018/10/26 15:08
     */
    @RequestMapping(value = "/getInfomations")
    String getInfoByFeign(@RequestParam(value = "param") String param);

//    @RequestMapping(value = "/saveAnswerToRedis")
//    void saveAnswerToRedis(@RequestBody(required = false) TwoPhaseDTO twophasedto);

}

配置文件

feign:
  hystrix:
    enabled: true

熔断仅写在调用方就可以了。

测试

  1. 注册中心,生产者,消费者均启动
  2. 正常消费者调用生产者提供的接口,成功没问题
  3. 将生产者服务停掉,再次发起调用请求,会进入到我们事先定义好的降级处理,这里说一下,feign的超时时间默认是1秒,一般都需要在配置文件中更改超时时间
  4. 当生产者真因为某种特殊情况某个接口不通,那么消费者会每隔30秒向服务端发起调用请求,看一下是否有效,如果一直不通,生产者会抛出UnsatisfiedDependencyException异常信息。
  5. 还有一点点小的疑问,没有搞清楚,后续再研究一下。