使用Fegin实现微服务间的通信

发布时间:2023-05-19

一、Fegin简介

在微服务架构中,服务拆分成许多小而独立的服务,每个服务提供一个简单、明确的接口。当应用需要与其他服务通信时,就可以使用HTTP或RPC进行通信。不过,手动构建和维护这些通信接口是一个非常繁琐的过程。Feign是一个声明性、模板化的HTTP客户端,使编写Web服务客户端变得更加容易。使用Feign,只需要创建一个接口并注解它,即可进行通信。

二、使用Fegin进行微服务间HTTP通信

一旦选定了微服务架构,微服务之间的通信就成为了一个问题。因为不同的微服务通常运行在不同的进程中,它们必须通过网络进行通信。在HTTP中,客户端和服务之间的通信通常使用RESTful API,很多人使用Spring的RestTemplate。Feign是声明式的,它优化了客户端和服务之间的通信。 要使用Feign,需要先添加Spring Cloud的Feign依赖:

<dependency>
  <groupid>
   org.springframework.cloud
  </groupid>
  <artifactid>
   spring-cloud-starter-openfeign
  </artifactid>
</dependency>

接着,需要在主程序中添加@EnableFeignClients注解使Feign可用:

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class DemoApplication {
  public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
  }
}

接下来,只需要创建一个接口并注解它,即可进行通信。以下示例展示了如何使用Feign从http://localhost:8080/greeting处获取问候语。

@FeignClient(name = "greeting-service", url = "http://localhost:8080")
public interface GreetingClient {
  @GetMapping("/greeting")
  Greeting greeting();
}

在上面的示例中,Feign客户端GreetingClient在Spring应用程序中被声明为一个bean。@FeignClient注解指定了这个客户端与哪个服务进行通信,其中name属性指定了服务名称,url属性指定了服务的URL。greeting方法将使用HTTP GET请求访问/greeting路径,并将响应转换为一个Greeting对象。

三、使用Fegin进行微服务间RPC通信

在微服务架构中,除了HTTP通信外,还有一种常用的通信方式就是RPC。RPC是远程过程调用的缩写,是一种通信协议,用于在客户端和服务器之间创建网络连接并传递数据。Spring Cloud使用了Netflix公司的开源库Feign,它允许开发人员使用Java类型定义接口,并使用注释进行配置,以便在微服务之间进行RPC通信。 和HTTP通信一样,首先需要添加Spring Cloud的Feign依赖。然后,需要配置Feign访问服务列表,如下所示:

spring.application.name=user-service
eureka.client.service-url.default-zone=http://localhost:8761/eureka/

接下来,就可以创建一个接口,像HTTP通信一样使用Feign进行RPC通信。以下示例展示了如何使用Feign从greeting-service组件获取问候语:

@FeignClient("greeting-service")
public interface GreetingService {
  @GetMapping(value = "/greeting")
  String greeting();
}

上面的代码中,@FeignClient注解指定了通过Feign客户端访问greeting-service组件。然后,只需要声明一个接口方法来使用Feign客户端的功能。在这种情况下,我们声明了一个名称为greeting的方法,该方法将访问/greeting路径并返回字符串响应。 Feign将使用Ribbon来实现负载平衡。如果存在多个greeting-service组件,Feign将使用负载平衡算法选择其中一个进行通信。

四、使用Fegin的自定义配置

Feign允许使用自定义配置来控制客户端的行为。这些配置可以用来修改底层HTTP客户端的行为。 以下示例演示了如何使用自定义配置来修改连接和读取超时时间:

@Configuration
public class FeignConfiguration {
  @Value("${feign.connectTimeout:5000}")
  private int connectTimeout;
  @Value("${feign.readTimeout:5000}")
  private int readTimeout;
  @Bean
  public Request.Options options() {
    return new Request.Options(connectTimeout, readTimeout);
  }
}

在上面的示例中,@Configuration注解表示这是一个配置类,它包含了连接超时时间和读取超时时间的属性。然后,@Bean注解表示方法将返回一个Request.Options对象。通过使用@Value注解和默认值,可以避免在没有设置属性值时出现异常。 接下来,需要使用@Import注解将Feign配置导入Spring应用程序。将上面的自定义配置添加到应用程序中:

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@Import(FeignConfiguration.class)
public class DemoApplication {
  public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
  }
}

五、使用Fegin的拦截器

Feign允许开发人员使用拦截器来自定义客户端的行为。拦截器允许开发人员修改输入和输出,以及对请求和响应进行处理。 以下示例演示了如何使用Feign拦截器来添加身份验证:

public class AuthInterceptor implements RequestInterceptor {
  private final String username;
  private final String password;
  public AuthInterceptor(String username, String password) {
    this.username = username;
    this.password = password;
  }
  @Override
  public void apply(RequestTemplate template) {
    String auth = username + ":" + password;
    byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("US-ASCII")));
    String authHeader = "Basic " + new String(encodedAuth);
    template.header("Authorization", authHeader);
  }
}

在上面的示例中,AuthInterceptor类实现了RequestInterceptor接口,并实现了apply()方法来添加身份验证标头。该类需要使用usernamepassword参数进行实例化。 接下来,需要在Feign客户端上使用@FeignClient注解来添加拦截器。以下示例演示了如何使用AuthInterceptor进行身份验证:

@Configuration
public class FeignConfiguration {
  @Value("${feign.username}")
  private String username;
  @Value("${feign.password}")
  private String password;
  @Bean
  public AuthInterceptor authInterceptor() {
    return new AuthInterceptor(username, password);
  }
  @Bean
  public RequestInterceptor requestInterceptor() {
    return new UserContextInterceptor();
  }
}

在上面的示例中,使用@Configuration注解表示这是一个配置类。然后,使用@Value注解添加了usernamepassword属性。然后,使用@Bean注解将authInterceptorrequestInterceptor添加到Feign客户端上。

六、小结

本文演示了如何使用Feign进行微服务间的通信。只需要声明一个接口并注解它,就可以方便地进行HTTP和RPC通信。同时,Feign允许您使用自定义配置和拦截器来控制客户端的行为。