配置feign+ribbon+hystrix踩坑记录

先前公司使用的是在开源微服务框架的基础上二次开发的,后来伴随着业务不断增多,逐渐发现项目规模大到一定程度,其实天天解决的并不是BUG,而是执行效率问题,整天被time-out问题困扰,我逐渐有了需要重新捋一遍框架的冲动,这里多说一句,现在开源微服务框架很多,很多公司项目工期紧张,会直接购买或者拿开源的框架搭建业务平台,我对这点不是很认同,因为别人的框架,咱们学习一下还行,直接用的话,出了问题都不清楚如何解决,特别是微服务类平台,就是java技术及相关组件的大杂烩,如果项目当天晚上要发版,突然出现个问题,因为使用别人的框架,不晓得问题出在哪?咋办呢?跑路都来不及,所以还是需要一点一点搭建框架,虽然慢点,但心里踏实。最近研究微服务间通信,涉及feign、hystrix、ribbon,原来一直用,但一直没过多关注,反正就是在yml里配一山的东西,这么多配置信息,就属它的配置多。打算好好看一看,至于看它的原因,是因为日常工作中服务间通信效率问题实在是把我坑死了。这次又是搞了一天才搞定,踩了很多坑,担心后面忘了,记录一下,分享出来给大家看看

一、第一坑
一般网上的资料或教程在配置openfeign的时候,都是直接在启动类上直接加上注解@EnableFeignClients,由于我的框架场景不是这样,说个题外话哈,我玩微服务也有些时间了,根据以往经验,我认为微服务框架中的服务可以大体分为三类,第一类是工具服务,比如说网关、zipkin、springadmin、nacos等,第二类是可以写成通用功能的微服务,最典型的就是认证中心、鉴权中心还有管理客户信息的客户中心,这类服务就是固定的业务,就拿认证中心来说把,其实就是干一件事,用户是谁的问题吗?其实就是搞一些如何生成token以及如何解析token的那些事,但有了网关之后,这部分功能就放在网关层了,因为token是无状态的,如果是jwttoken,还要判断token本身的失效时间以及缓存刷新时间,说实话,代码不复杂,逻辑有点复杂,后面我会拿单独的一篇文章聊聊。像这类服务如果肯用点心的话,完全可以写成通用的,暴露出接口之后,可以远程支撑其他业务服务,相信我,只要用心一定是可以做到的。另外还有一类服务就是业务服务,这就得根据项目现用现写了,带过团队的人都知道,你不可能保证团队的所有开发人员都是高手,大部分人还是整天干CRUD的活的,但像网关、认证中心、鉴权中心等核心服务,最好不要让他们接触到,不定谁手贱给你改了代码,查问题很困难,所以我搭建架构的原则是:1、最核心的代码封装在jar包里依赖(spring的自动注入是个好东西,哈哈);2、核心的微服务要在独立的一个maven工程里的,除了核心骨干人员,其他人就不要接触了;3、普通的业务微服务也是一个独立的maven工程,这样一般的开发人员就老老实实干CRUD的活吧,干成狗屎也影响不了大局。

正因为上述原因,我将提供端的feign接口单独在放在一个jar文件里,通过maven把依赖暴露出来,然后在调用端里引入依赖,这样就实现了彻底解耦,而且再有其他调用端调用的话,直接引入依赖调用接口就行了,但也因为如此,我的坑也就随之而来了.......

1、提供端代码片段

2、调用端代码片段

 在调用端测试类调用的时候,日志报feign接口没有对应的实现bean,日志我看明白了,但问题不晓得出在哪,最后才发现,原来由于feign接口提供端以及调用端已经不再一个工程目录了,openfeign根本就扫描不到,也就没法进行生成bean进行注入,于是我就在提供端的启动类和调用端的启动类上加上了扫描路径:

1、接口提供端启动类

@RefreshScope
@EnableCircuitBreaker
@EnableDiscoveryClient
@EnableFeignClients(basePackages = {"cn.**.*","com.**.*"})
@SpringBootApplication
public class AuthStarterApplication {
    public static void main(String[] args) {
        SpringApplication.run(AuthStarterApplication.class, args);
    }
}
2、接口调用端启动类

/**
 * 微服务业务服务启动类
 * @author  gaoh
 */
@RefreshScope
@EnableCircuitBreaker
@EnableFeignClients(basePackages = {"cn.**.*","com.**.*"})
@EnableDiscoveryClient
@SpringBootApplication
public class DemoStarterApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoStarterApplication.class, args);
    }
}
问题立马解决,这里为啥是全路径扫描呢,这就来源于生活了,哈哈,在搭建架构的过程中,大家要考虑一件事,那就是团队里开发人员干活,有些人干活会时刻以学习的状态进行工作,会以“为什么”的态度去工作;但有些人干活就是整口饭吃,这类人与其说是编码,倒不如说是在copy编码,我搭建架子的过程中把扫描目录写死,我是知道啥意思的,但有些人他们就不在乎,在新建微服务创建启动类时直接copy,最后还以一副研究高深问题的样子,惦着脸问我为啥他写的代码老是调不通,很费解,既浪费我时间也浪费我精力,所以我索性就写个模糊扫描的目录吧,省心........

二、第二坑
第二个坑就是,我在调用端调用feign接口时,日志给我打印出一个带有注册中心服务ID的URL,说404错误调不通,我知道这是feign封装的restURL,我看了看路径也没错,调用方式也没错,咋就调不通呢,搞得我心力交瘁,最后看了下网上的帖子,又试了一下,才发现,是因为我的工程yml里配置了上下文路径 context-path:

server:
  port: 9002
  servlet:
    context-path: /admin
我去掉前缀后重启提供端服务,feign和ribbon就起作用了,其实配上下文路径这事并不是我手残,是故意为止,因为在配置网关路由转发时,如服务有个上下文路径的话,网关路由的配置能方便点,就在路由里配个“"pattern": "/admin/**"”就完事了,没想到就因为这个事feign接口还调不通,我也没多少时间解决这个问题,只能把上下文配置去掉了,网关路由配置麻烦点就麻烦点吧

三、第三坑
这个坑是最贱的一个坑,上面两个坑填上之后,feign接口终于调通了,开始集成hystrix,本来希望一把就过,谁知道坑又来了,先把代码贴上看看:

@FeignClient(
        contextId = "ExternalPermissionCheckClient",
        value = "hcbycloud-platform-service-auth-starter",
        fallbackFactory = ExternalPermissionCheckClientFallback.class)
public interface ExternalPermissionCheckClient {
    /**
     * 根据认证信息获取权限列表
     *
     * @param loginInfoDTO
     * @return
     */
    @PostMapping(value = "/external/permissions")
    List<String> getPermissionsByFeign(@RequestBody LoginInfoDTO loginInfoDTO);

    /**
     * 根据认证信息获取角色列表
     *
     * @param loginInfoDTO
     * @return
     */
    @PostMapping(value = "/external/roles")
    List<String> getRolesByFeign(@RequestBody LoginInfoDTO loginInfoDTO);
}
@Slf4j
@Component
public class ExternalPermissionCheckClientFallback implements FallbackFactory<ExternalPermissionCheckClient> {

    @Override
    public ExternalPermissionCheckClient create(Throwable throwable) {
        log.warn("ExternalPermissionCheckClient error " + "(Hystrix FallbackFactory): [{}]", throwable.getMessage(), throwable);
        return new ExternalPermissionCheckClient() {
            @Override
            public List<String> getPermissionsByFeign(LoginInfoDTO loginInfoDTO) {
                return CollUtil.newArrayList();
            }
            @Override
            public List<String> getRolesByFeign(LoginInfoDTO loginInfoDTO) {
                return CollUtil.newArrayList();
            }
        };
    }
}
大家看看代码是不是很标准,典型的openfeign接口配置,但是调用端调接口时,程序流程怎么一直会跳到Fallback(后备模式)的代码里呢,我确定一定以及肯定:提供端的微服务没问题啊,开始扒拉帖子资料一通查、试、查、试.........,最后发现是hystrix的超时配置时间太短,但我没配置hystrix呀,就只配了个feign开启hystrix,搞了半天人家是默认配置,擦!最后在网上copy了一段代码,把超时时间延长了不少,问题解决,对了有个事我还要记录一下,就是在配置yml文件的过程中,我有个习惯,就是在idea的ide里习惯性的用鼠标点点yml上配置的key和value,能点进去至少说明单词没有打错,配置的没有问题,但hystrix.command.default.xxxxxxx.这段配置鼠标点上去不高亮也点不进去,其实你没有配错,它就是点不进去,哎!强迫症害死人啊,我把配置的代码贴上,大家可以看看是不是遇到过相同的问题

hystrix:
  command:
    default:
      execution:
        isolation:
          strategy: SEMAPHORE
          thread:
            timeoutInMilliseconds: 600000
          semaphore:
            maxConcurrentRequests: 1000
  shareSecurityContext: true
ribbon:
  ReadTimeout: 100000
  ConnectTimeout: 100000
over!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiao_pa_cai0800

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值