基于Feign的远程服务调用
Feign介绍
服务消费方基于rest方式请求服务提供方的服务时,一种直接的方式就是自己拼接url,拼接参数然后实现服务调用,但每次服务调用都需要这样拼接,代码量复杂且不易维护,此时Feign诞生。
Feign 是一种声明式Web服务客户端,底层封装了对Rest技术的应用,通过Feign可以简化服务消费方对远程服务提供方法的调用实现。
Feign基础
1.在服务消费方,添加项目依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.在启动类上添加@EnableFeignClients注解
@EnableFeignClients
@SpringBootApplication
public class ConsumerApplication {…}
3.定义Http请求API,基于此API借助OpenFeign访问远端服务
@FeignClient描述的接口底层会为其创建实现类。
@FeignClient(name="sca-provider")//sca-provider为服务提供者名称
interface RemoteProviderService{
@GetMapping("/provider/echo/{string}")//前提是远端需要有这个服务
public String echoMessage(@PathVariable("string") String string);
}
4.创建FeignConsumerController中并添加feign访问
@RestController
@RequestMapping("/consumer/ ")
public class FeignConsumerController {
@Autowired
private RemoteProviderService remoteProviderService;
/**基于feign方式的服务调用*/
@GetMapping("/echo/{msg}")
public String doFeignEcho(@PathVariable String msg){
//基于feign方式进行远端服务调用(前提是服务必须存在)
return remoteProviderService.echoMessage(msg);
}
}
5.启动消费者服务,在浏览器中直接通过feign客户端进行访问
Feign配置进阶实践
一个服务提供方通常会提供很多资源服务,服务消费方基于同一个服务提供方写了很多服务调用接口,此时假如没有指定contextId,服务
启动就会失败,例如假如在服务消费方再添加一个如下接口,消费方启动时就会启动失败
@FeignClient(name="sca-provider")
public interface RemoteOtherService {
@GetMapping("/doSomeThing")
public String doSomeThing();
}
启动异常:
The bean ‘optimization-user.FeignClientSpecification’, defined in null, could not be registered. A bean with that name has already been defined in null and overriding is disabled.
contextId 作为Bean唯一标识
需要为远程调用服务接口指定一个contextId,作为远程调用服务的唯一标识即可
@FeignClient(name="sca-provider",contextId="remoteProviderService")//sca-provider为服务提供者名称
interface RemoteProviderService{
@GetMapping("/provider/echo/{string}")//前提是远端需要有这个服务
public String echoMessage(@PathVariable("string") String string);
}
添加容错方案
当我们在进行远程服务调用时,假如调用的服务突然不可用了或者调用过程超时了,怎么办呢?一般服务消费端会给出具体的容错方案
1.定义FallbackFactory接口的实现
package com.cy.service.factory;
/**
* 基于此对象处理RemoteProviderService接口调用时出现的服务中断,超时等问题
*/
@Component
public class ProviderFallbackFactory
implements FallbackFactory<RemoteProviderService> {
/**
* 此方法会在RemoteProviderService接口服务调用时,出现了异常后执行.
* @param throwable 用于接收异常
*/
@Override
public RemoteProviderService create(Throwable throwable) {
return (msg)->{
return "服务维护中,稍等片刻再访问";
};
}
}
2.在Feign访问接口中应用FallbackFactory对象
@FeignClient(name = "sca-provider", contextId = "remoteProviderService",
fallbackFactory = ProviderFallbackFactory.class)//sca-provider为nacos中的服务名
public interface RemoteProviderService {
@GetMapping("/provider/echo/{msg}")
public String echoMsg(@PathVariable String msg);
}
3.在配置文件application.yml中添加如下配置,启动feign方式调用时的服务中断处理机制
feign:
hystrix:
enabled: true #默认值为false
Feign 调用过程分析(了解)
Feign应用过程分析(底层逻辑先了解):
1)通过 @EnableFeignCleints 注解告诉springcloud,启动 Feign Starter 组件。
2) Feign Starter 在项目启动过程中注册全局配置,扫描包下所由@FeignClient注解描述的接口,然后由系统底层创建接口实现类(JDK代理类),并构建类的对象,然后交给spring管理(注册 IOC 容器)。
3) 接口被调用时被动态代理类逻辑拦截,将 @FeignClient 请求信息通过编码器生成 Request对象,基于此对象进行远程过程调用。
4) 请求对象经Ribbon进行负载均衡,挑选出一个健康的 Server 实例(instance)。
5) 通过 Client 携带 Request 调用远端服务返回请求响应。
6) 通过解码器生成 Response 返回客户端,将信息流解析成为接口返回数据。