Spring Cloud 组件 —— feign

feign 作为一个声明式的 Http Client 开源项目。在微服务领域,相比于传统的 apache httpclient 与在 spring 中较为活跃的 RestTemplate 更面向服务化,更易于使用。底层封装了 Jersey 与 CXF 分别用于 REsT 与 SOAP 的服务(对应有 JAX-RS 与 JAX-WS  API),当然也可以配置换成其它类似的实现,比如 OkHttp 、Ribbon 或者 Apache HC 等。

feign 基本用法及注解的使用看官方文档。下面介绍下 Spring Cloud 中的封装及实现细节(Spring Cloud 文档):

 

一、 基本用法 

现有服务提供方:需要调用它的 createUser 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@RestController
@RequestMapping("/users")
public class UserController {
 
    @Autowired
    private UserService userService;
 
    @RequestMapping(value = "/current", method = RequestMethod.GET)
    public Principal getUser(Principal principal) {
        return principal;
    }
 
    @PreAuthorize("#oauth2.hasScope('server')")
    @RequestMapping(method = RequestMethod.POST)
    public void createUser(@Valid @RequestBody User user) {
        userService.create(user);
    }
}

使用 feign 构建消费服务方,遵循以下步骤:

引入 maven 依赖

1
2
3
4
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

1. 启用:使用  @EnableFeignClients 注解启动 feign 模块基础功能(扫描 feign client包,使用默认或指定的相关配置等等)

1
2
3
4
5
6
7
8
9
@SpringBootApplication
@EnableFeignClients
public class Application {
 
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
 
}

2. 声明:使用 @FeignClient("app-name") 创建声明式的 HC:很简单配置下 service 名称/url 与 发出请求的路径就好了。

1
2
3
4
5
6
7
@FeignClient(name = "auth-service")
public interface AuthServiceClient {
 
    @RequestMapping(method = RequestMethod.POST, value = "/users", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    void createUser(User user);
 
}

3. 调用:上面的代码,相对于服务提供方,它是客户端服务消费方。相对于服务消费方自身,它上升到一个 service,因此我们可以在 service 层或 controller 层调用它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
@Service
public class AccountServiceImpl implements AccountService {
 
    private final Logger log = LoggerFactory.getLogger(getClass());
     
    @Autowired
    private AuthServiceClient authClient;
 
    @Autowired
    private AccountRepository repository;
 
    /**
     * {@inheritDoc}
     */
    @Override
    public Account create(User user) {
 
        Account existing = repository.findByName(user.getUsername());
        Assert.isNull(existing, "account already exists: " + user.getUsername());
 
        // 调用feign HC服务
        authClient.createUser(user);
 
        Saving saving = new Saving();
        saving.setAmount(new BigDecimal(0));
        saving.setCurrency(Currency.getDefault());
        saving.setInterest(new BigDecimal(0));
        saving.setDeposit(false);
        saving.setCapitalization(false);
 
        Account account = new Account();
        account.setName(user.getUsername());
        account.setLastSeen(new Date());
        account.setSaving(saving);
 
        repository.save(account);
 
        log.info("new account has been created: " + account.getName());
 
        return account;
    }
 
...

  

 二、feign 的相关配置(比如日志、hytrix  等)

配置方式有 3种:

1. 使用 JavaConfig 方式

配置类(这里建议不要加 @Configuration 注解,否则将变成全局配置)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class FileConf {
 
    private final ObjectFactory<HttpMessageConverters> messageConverters;
 
    @Autowired
    public FileConf(ObjectFactory<HttpMessageConverters> messageConverters) {
        this.messageConverters = messageConverters;
    }
 
    @Bean
    public Encoder feignFormEncoder() {
        return new SpringFormEncoder(new SpringEncoder(messageConverters));
    }
}

调用端

1
2
3
4
5
6
7
8
9
10
11
12
@FeignClient(value = "service-thirdparty", configuration = FileConf.class)
@RequestMapping(value = "/storage")
public interface StorageClient {
    /**
     * 上传图片
     */
    @RequestMapping(
            value = "/imageUpload",
            method = RequestMethod.POST,
            consumes = MULTIPART_FORM_DATA_VALUE)
    BusinessResult uploadImage(@RequestParam(value = "bucket") String bucket,
                               @RequestPart(value = "file", required = false) MultipartFile file);

 

2. 使用 application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# To disable Hystrix in Feign
feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
        loggerLevel: basic
  hystrix:
    enabled: false
 
# To set thread isolation to SEMAPHORE
hystrix:
  command:
    default:
      execution:
        isolation:
          strategy: SEMAPHORE
 
logging.level.project.user.UserClient: DEBUG

  

注意事项:

① 如果 @Configuration的 JavaConfig 与 properties 配置同时存在,那么后者会覆盖前者。通过设定 feign.client.default-to-properties to false. 改变优先权。

② 只有开启 DEBUG级别的日志, feign 的log功能才会生效。

③ 如果 classpath 引入了 hytrix(如下),并且配置启用 hytrix(比如  feign.hystrix.enabled=true),那么默认会启用 circuit breaker 。

1
2
3
4
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

在 Spring Cloud Dalston 及之后的版本中,circuit breaker 是可选操作。需要使用 @EnableCircuitBreaker 手动开启。

1
2
3
4
@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker
public class Application {

 

扩展:使用断路器功能 

声明:

1
2
3
4
5
6
7
@FeignClient(name = "statistics-service", fallback = StatisticsServiceClientFallback.class)
public interface StatisticsServiceClient {
 
    @RequestMapping(method = RequestMethod.PUT, value = "/statistics/{accountName}", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    void updateStatistics(@PathVariable("accountName") String accountName, Account account);
 
}

定义 hytrix:

1
2
3
4
5
6
7
8
@Component
public class StatisticsServiceClientFallback implements StatisticsServiceClient {
    private static final Logger LOGGER = LoggerFactory.getLogger(StatisticsServiceClientFallback.class);
    @Override
    public void updateStatistics(String accountName, Account account) {
        LOGGER.error("Error during update statistics for account: {}", accountName);
    }
}

  

233

参考资料


https://github.com/sqshq/PiggyMetrics (完整示例)

posted on   Lemo_wd  阅读(749)  评论(0编辑  收藏  举报

编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示