SpringCloud学习笔记(四)——声明式服务调用feign

简介

前面我们分别通过Spring Cloud Ribbon和Spring Cloud Hystrix实现了客户端负载均衡和服务容错,而Spring Cloud Feign不但整合了这两者的功能,而且还提供了一种比Ribbon更简单的服务调用方式 ——— 声明式服务调用。在Spring Cloud Feign中编写服务调用代码非常简单,几乎可以直接将服务提供者的代码复制过来,改为接口即可,下面通过例子来演示这个特性。

Feign使用

新建一个SpringBoot应用,pom文件引入openfeign依赖。

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

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

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

在Spring Boot的入口类中加入@EnableFeignClients和@EnableDiscoveryClient注解,用于开启Spring Cloud Feign和服务注册与发现:

@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication
public class FeigndemoApplication {

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

}

在前面几节中,我们曾在服务提供者Eureka-Client中定义了一个UserController,代码如下所示:

@RestController
@RequestMapping("user")
public class UserController {
    private Logger log = LoggerFactory.getLogger(this.getClass());

    @GetMapping("/{id:\\d+}")
    public User get(@PathVariable Long id) {
        log.info("获取用户id为 " + id + "的信息");
        return new User(id, "mrbird", "123456");
    }

    @GetMapping
    public List<User> get() {
        List<User> list = new ArrayList<>();
        list.add(new User(1L, "mrbird", "123456"));
        list.add(new User(2L, "scott", "123456"));
        log.info("获取用户信息 " + list);
        return list;
    }

    @PostMapping
    public void add(@RequestBody User user) {
        log.info("新增用户成功 " + user);
    }

    @PutMapping
    public void update(@RequestBody User user) {
        log.info("更新用户成功 " + user);
    }

    @DeleteMapping("/{id:\\d+}")
    public void delete(@PathVariable Long id) {
        log.info("删除用户成功 " + id);
    }
}

在Spring Cloud Ribbon中访问这些服务需要通过RestTemplate对象来实现,并且参数绑定的过程也比较繁琐。Spring Cloud Feign对这个步骤进行了进一步的封装,在Feign Consumer中调用这些服务只需要定义一个UserService接口,然后将UserController中的代码复制过并将方法体去掉即可,如:

@FeignClient("Server-Provider")
public interface UserService {

    @GetMapping("user/{id}")
    public User get(@PathVariable("id") Long id);

    @GetMapping("user")
    public List<User> get();

    @PostMapping("user")
    public void add(@RequestBody User user);

    @PutMapping("user")
    public void update(@RequestBody User user);

    @DeleteMapping("user/{id}")
    public void delete(@PathVariable("id") Long id);
}

在开发中,一个一个服务尽量对应一个接口,如果定义了多个相同名称的FeignClient,服务在启动时会报错,报错信息如下:xx.FeignClientSpecification’, defined in null, could not be registered.在application.yaml中配置可以避免报错,但尽量定义在一个接口中

spring:
  main:
    allow-bean-definition-overriding: true

在UserService中,我们通过@FeignClient(“Server-Provider”)注解来获取我们需要的服务,其中Server-Provider不区分大小写。需要注意的是,在定义各参数绑定时,@RequestParam、@RequestHeader等可 以指定参数名称的注解,它们的value千万不能少。在SpringMVC 程序中,这些注解会根据参数名来作为默认值,但是在Feign中绑定参数必须通过value属性来指明具体的参数名,不然会抛出illegalStateException异常,value 属性不能为空。

接下来我们在Feign Consumer中定义一个TestController,来调用UserService中定义的服务:

@RestController
public class TestController {

    @Autowired
    private UserService userService;

    @GetMapping("user/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.get(id);
    }

    @GetMapping("user")
    public List<User> getUsers() {
        return userService.get();
    }

    @PostMapping("user")
    public void addUser() {
        User user = new User(1L, "mrbird", "123456");
        userService.add(user);
    }

    @PutMapping("user")
    public void updateUser() {
        User user = new User(1L, "mrbird", "123456");
        userService.update(user);
    }

    @DeleteMapping("user/{id}")
    public void deleteUser(@PathVariable Long id) {
        userService.delete(id);
    }
}

最后配置application.properties/yml文件

server.port=8088

spring.application.name=Feign-Consumer

eureka.client.service-url.defaultZone=http://localhost:8085/eureka, http://localhost:8087/eureka

feign.hystrix.enabled=true

配置

Ribbon相关配置

Spring Cloud Feign内部的客户端负载均衡是通过Ribbon来实现的,所以在Spring Cloud Feign中配置Ribbon,和之前在Spring Cloud Ribbon客户端负载均衡中介绍的Spring Cloud Ribbon配置一样,这里不再赘述。

Hystrix相关配置

要在Spring Cloud Feign中开启Hystrix,可以在yml中添加如下配置:

feign:
  hystrix:
    enabled: true

在Spring Cloud Feign中配置服务降级和在Spring Cloud Hystrix中配置服务降级区别很大,下面具体来看下怎么在Feign-Consumer中配置服务降级。

定义一个用于处理服务降级方法的类UserServiceFallback,并且实现上面定义的UserService接口:

@Component
public class UserServiceFallback implements UserService {
    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Override
    public User get(Long id) {
        return new User(-1L, "default", "123456");
    }

    @Override
    public List<User> get() {
        return null;
    }

    @Override
    public void add(User user) {
        log.info("test fallback");
    }

    @Override
    public void update(User user) {
        log.info("test fallback");
    }

    @Override
    public void delete(Long id) {
        log.info("test fallback");
    }
}

在UserService的中通过@FeignClient注解的fallback属性来指定对应的服务降级实现类:

@FeignClient(value = "Server-Provider", fallback = UserServiceFallback.class)
public interface UserService {
    ...
}

其余Feign配置

  1. 请求压缩
    Spring Cloud Feign支持对请求与响应进行GZIP压缩,以减少通信过程中的性能损耗:
feign:
  compression:
    request:
      enabled: true
    response:
      enabled: true

同时,我们还能对请求压缩做一些更细致的设置,比如下面的配置内容指定了压缩的请求数据类型,并设置了请求压缩的大小下限,只有超过这个大小的请求才会对其进行压缩:

feign:
  compression:
    request:
      enabled: true
      mime-types: text/xml,application/xml,application/json
      min-request-size: 2048
  1. 日志配置
    Feign提供了日志打印的功能,Feign的日志级别分为四种:

NONE: 不记录任何信息。
BASIC: 仅记录请求方法、URL以及响应状态码和执行时间。
HEADERS: 除了记录BASIC级别的信息之外,还会记录请求和响应的头信息。
FULL: 记录所有请求与响应的明细,包括头信息、请求体、元数据等。

日志级别默认为NONE,要改变级别可以在入口类中定义一个日志配置Bean:

@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication
public class DemoApplication {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

然后在yml中配置Feign客户端的日志级别为debug,Feign日志记录仅响应debug级别:

logging:
  level:
    com:
      example:
        demo:
          service:
            UserService: debug

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值