Fegin

是一个http请求调用的轻量级框架,是以Java接口注解的方式调用Http请求,而不用像Java中通过封装HTTP请求报文的方式直接调用。Feign通过处理注解,将请求模板化,当实际调用的时候,传入参数,根据参数再应用到请求上,进而转化成真正的请求,这种请求相对而言比较直观。

使用Feign替代RestTemplate发送Rest请求。使之更符合面向接口化的编程习惯。

使用Nacos 注册text、fegin两个服务;使用feign实现服务直接的调用;

dc12f20258cab3a10a0619f8bf14574a.png

Feign服务 

依赖

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
  <version>版本号</version>
</dependency>

在启动类上加入 @EnableFeignClients,表示开启Feign 

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

@FeignClient

  • name/value:指定FeignClient的名称,如果指定了注册中心,指注册的服务名称。
  • url:可以手动指定@FeignClient调用的地址。
  • contextId:指定beanID。
  • decode404:当发生http 404错误时,如果该字段位true,会调用decoder进行解码,否则抛出FeignException。
  • configuration: Feign配置类,可以自定义Feign的Encoder、Decoder、LogLevel、Contract
  • fallback: 定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口
  • fallbackFactory: 工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码
  • path: 定义当前FeignClient的统一前缀
@FeignClient(
        value = "text"
        // url = "127.0.0.1:8090" 通过url指定服务地址访问也是可以的
)
public interface TextClient {

    @GetMapping("/text/findOrderDetailById")
    OrderDetail findOrderDetailById(@RequestParam String detailId);
}

服务调用

@RestController
@RequestMapping("/fegin")
public class FeginController {

    @Autowired
    private TextClient textClient;

    @GetMapping("/findOrderDetailById")
    public OrderDetail findOrderDetailById(@RequestParam("detailId") String detailId){
        return textClient.findOrderDetailById(detailId);
    }

}

 Text服务

@RestController
@RequestMapping("/text")
public class TextController {

    @GetMapping("/findOrderDetailById")
    public OrderDetail findOrderDetailById(@RequestParam("detailId") String detailId){
        return new OrderDetail(detailId);
    }
}

测试

fed82c55cce5308ed19462f44458e41c.png

configuration:Feign配置类,可以自定义Feign配置

23e4d4e3aacc079e47a410a414934949.png

Retryer:

  1. Feign默认配置是不走重试策略的,当发生RetryableException异常时直接抛出异常。
  2. 并非所有的异常都会触发重试策略,只有 RetryableException 异常才会触发异常策略。
  3. 在默认Feign配置情况下,只有在网络调用时发生 IOException 异常时,才会抛出 RetryableException,也是就是说链接超时、读超时等不不会触发此异常。

因此常见的 SocketException、NoHttpResponseException、UnknownHostException、HttpRetryException、SocketConnectException、ConnectionClosedException 等异常都可触发Feign重试机制。
注:常见的还有 SocketTimeoutException、TimeoutException、ReadTimeoutException、WriteTimeoutException 等都不属于IO异常,因为不会触发Feign重试机制。

@Slf4j
public class FeginConfig {

    /**
     * 自定义重试
     * maxAttempts:最多请求次数
     * period:发起当前请求的时间间隔,单位毫秒
     * maxPeriod:发起当前请求的最大时间间隔,单位毫秒
     * @return
     */
    @Bean
    public Retryer feginRetryer(){
        // 默认最大请求次数为5,初始间隔时间为100ms,下次间隔时间1.5倍递增,重试间最大间隔时间为1s,
//        return new Retryer.Default();
        return new Retryer.Default(1000, 0, 3);
    }

    /**
     * 自定义错误码
     * 当feign调用返回HTTP报文时,会触发这个方法,方法内可以获得HTTP状态码,可以用来定制一些处理逻辑等等
     * @return
     */
    @Bean
    public ErrorDecoder feginErrorDecoder() {
        return (key, response) -> {

            switch (response.status()) {
                case 404:
                    log.error("请求Text服务404异常,返回:{}", response.body());
                    break;
                case 503:
                    log.error("请求Text服务503异常,返回:{}", response.body());
                    break;
                default:
                    log.error("请求Text服务异常,返回:{}", response.body());
            }

            // 其他异常交给Default去解码处理
            // 这里使用单例即可,Default不用每次都去new
            return new ErrorDecoder.Default().decode(key, response);
        };
    }

}

自定义重试类

@Slf4j
@Component
@NoArgsConstructor
public class CustomRetryer implements Retryer{

    private int retryMaxAttempt;

    private long retryInterval;

    private int attempt = 1;


    public CustomRetryer(int retryMaxAttempt, Long retryInterval) {
        this.retryMaxAttempt = retryMaxAttempt;
        this.retryInterval = retryInterval;
    }

    @Override
    public void continueOrPropagate(RetryableException e) {
        log.info("Feign retry attempt {} due to {} ", attempt, e.getMessage());

        if(attempt++ == retryMaxAttempt){
            throw e;
        }
        try {
            Thread.sleep(retryInterval);
        } catch (InterruptedException ignored) {
            Thread.currentThread().interrupt();
        }

    }

    @Override
    public Retryer clone() {
        return new CustomRetryer(6, 2000L);
    }
}

全局配置

feign:
	client:
		config:
		# 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
		default:
			#  日志级别
			loggerLevel: FULL
			# 连接超时
			connectTimeout: 1000
			# 读取超时
			readTimeout: 1000
			# 自定义重试
            retryer: com.Fegin.config.CustomRetryer

<!-- feign:
  client:
    config:
      defalut: # feign请求默认配置
        connectTimeout: 2000
        readTimeout: 3000
      fiegnName: # fiegnName服务请求的配置,优先defalut配置。
        connectTimeout: 5000 # 链接超时时间
        readTimeout: 5000  # 请求
        loggerLevel: full   # 日志级别
        errorDecoder: com.example.SimpleErrorDecoder #异常处理
        retryer: com.example.SimpleRetryer # 重试策略
        defaultQueryParameters: # 默认参数条件
          query: queryValue
        defaultRequestHeaders:  # 默认默认header
          header: headerValue
        requestInterceptors:    # 默认拦截器
          - com.example.FooRequestInterceptor
          - com.example.BarRequestInterceptor
        decode404: false   #404响应 true-直接返回,false-抛出异常       
        encoder: com.example.SimpleEncoder  #传输编码
        decoder: com.example.SimpleDecoder  #传输解码
        contract: com.example.SimpleContract #传输协议 -->

fallback和fallbackFactory 是Fegin两种降级的方式。不能同时使用。

OpenFegin 3.0 以前 集成了hystrixribbon,3.0以后去除了。这时使用fallbackFactory会失效。

需要单独引入hystrix

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  <version>2.2.10.RELEASE</version>
</dependency>

配置文件 feign.hystrix.enabled 不见了改成 fegin.circuitbreaker.enabled

feign:
  circuitbreaker:
    enabled: true
@Slf4j
@Component
public class TextClientFallbackFactory implements FallbackFactory<TextClient> {

    @Override
    public TextClient create(Throwable cause) {
        return new TextClient() {
            @Override
            public OrderDetail findOrderDetailById(String detailId) {
                log.info("调用{Text}失败,回调:detailId:{}", detailId );
                return new OrderDetail(detailId);
            }
        };
    }
}

测试

44daacf1a8c029f215a38ffa0773373c.png

也可以集成阿里的sentinel。

<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

配置文件开启

feign:
  sentinel:
    enabled: true

测试

a8ec9a96411367d7673958888a078198.png

sentinel和Hystrix区别

ae32b8fdf4c6b6140defad6d867e1ad5.png

使用Fegin实现文件上传

@RestController
@RequestMapping("/fegin")
public class FeginController {

    @Autowired
    private TextClient textClient;

    @PostMapping("/upload")
    public String upload(@RequestParam("file") MultipartFile file){
        return textClient.upload(file);
    }

}

文件上传

文件属性需要使用 @RequestPart 属性,而且在请求中添加 consumes = MediaType.MULTIPART_FORM_DATA_VALUE ,

文件表单上传请求通常使用的ContentType为 multipart/form-data ,通过以上直接调用feign的方式即可实现feign 文件上传。

@RequestPart:用在multipart/form-data表单提交请求的方法上。支持的请求方法的方式MultipartFile,属于Spring的MultipartResolver类。这个请求是通过http协议传输的。

@RequestParam也同样支持multipart/form-data请求。

他们最大的不同是,当请求方法的请求参数类型不再是String类型的时候。@RequestParam适用于name-valueString类型的请求域,@RequestPart适用于复杂的请求域(像JSON,XML)。

produces:它的作用是指定返回值类型,不但可以设置返回值类型还可以设定返回值的字符编码;

consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;

@FeignClient(
        value = "text",
        configuration = FeginConfig.class,
        fallbackFactory = TextClientFallbackFactory.class
)
public interface TextClient {
    
    @PostMapping(value = "/text/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE,
        produces = MediaType.APPLICATION_JSON_VALUE)
    String upload(@RequestPart("file") MultipartFile file);
}

 Text服务

@RestController
@RequestMapping("/text")
public class TextController {

    @PostMapping("/upload")
    public String upload(@RequestParam("file") MultipartFile file){
        return file.getName();
    }
}

 测试

3a371cadf0424edf3333e4b0c5c1ae86.png

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Fegin Token统一认证是一种将微服务架构中的认证流程整合和统一管理的解决方案。在微服务架构中,每个服务都需要进行认证和授权操作,传统的方式是在每个服务中都嵌入认证流程,这样会导致代码重复和维护困难。Fegin Token统一认证提供了一种解决方案,通过将认证和授权流程独立出来,让每个微服务只需要调用认证服务获取令牌即可。 Fegin Token统一认证的核心概念是令牌。在整个认证流程中,首先用户提供用户名和密码,认证服务对用户进行验证,并生成一个令牌。然后,其他微服务在调用时只需要携带该令牌,认证服务会对令牌进行验证,并返回结果。这样,每个微服务都可以通过令牌来确认用户的身份和权限。 Fegin Token统一认证的优点首先是减少了重复代码的编写和维护工作量。由于整个认证流程被独立出来,每个微服务不再需要自己实现认证逻辑,只需要调用认证服务即可。其次,这种统一的认证方式提高了系统的灵活性和可扩展性。如果有新的认证方式需要添加,只需要在认证服务中进行修改,而不需要修改每个微服务。 当然,Fegin Token统一认证也存在一些挑战和注意事项。首先,认证服务的性能和可用性对整个系统至关重要,如果认证服务出现故障或性能瓶颈,将影响到所有微服务的正常运行。因此,认证服务的设计和部署需要特别关注。另外,令牌的生成和验证过程需要进行一定程度的加密和安全保护,以防止令牌被窃取或篡改。 综上所述,Fegin Token统一认证是一种将微服务架构中认证流程统一管理的解决方案,通过将认证和授权流程独立出来,提供了代码复用和灵活性的优势。但是,在实际应用中需要注意保证认证服务的性能和安全性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值