V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lixueyu001
V2EX  ›  Java

[Spring Cloud] 求助,怎么实现 Ribbon 按照 userId 哈希路由?

  •  
  •   lixueyu001 · 2019-10-10 23:04:48 +08:00 · 2922 次点击
    这是一个创建于 1901 天前的主题,其中的信息可能已经有所发展或是发生改变。

    大家有遇到过这种需求吗?

    userId 存在于 Feign 请求的 header 或者参数中,路由是在项目中使用 feign 调用时发生的,不是网关那里的路由。

    我有一个有问题的方案, 1、在 FeignInterceptor 那里拦截一下 userId 放到 ThreadLocal (只能拦截请求没找到返回怎么拦截) 2、然后在 Ribbon 的自定义路由策略 IRule 的 choose 方法中获取 ThreadLocal 里的 userId 并删除 ThreadLocal 里的值存在没有被清空的风险

    求教,可行的路由方案。

    8 条回复    2019-10-12 14:27:35 +08:00
    cluulzz
        1
    cluulzz  
       2019-10-11 10:01:09 +08:00
    seata 我现在就像你说的这样做,不过用的是 InheritableThreadLocal,中间用 aspect 切开...
    lixueyu001
        2
    lixueyu001  
    OP
       2019-10-11 10:27:12 +08:00
    @cluulzz InheritableThreadLocal 会有问题吧,能否说下你的切面怎么实现的。
    https://blog.csdn.net/qq_27570205/article/details/98961963
    cluulzz
        3
    cluulzz  
       2019-10-11 10:37:12 +08:00
    InheritableThreadLocal:
    切面的话 seata-spring 有个注解 @GlobalTransactional

    大概这样
    lixueyu001
        4
    lixueyu001  
    OP
       2019-10-11 10:54:19 +08:00
    @cluulzz 多谢 明白了,只是利用了一下 @GlobalTransactional 注解,跟 seata 没有太直接关系对吧。
    我这边比较麻烦了没有一个统一的注解在 feign 调用上。
    我准备给 feign 和 ribbon 默认一下 Client 为 Okhttp,给 Okhttp 加个拦截器试试。
    跨线程传值用 HystrixRequestVariableDefault 应该可以。
    cluulzz
        5
    cluulzz  
       2019-10-11 11:03:42 +08:00
    @lixueyu001 #4 这样..跨线程那块看来我还要改..
    lixueyu001
        6
    lixueyu001  
    OP
       2019-10-11 17:22:56 +08:00
    @lixueyu001 失败,Okhttp 的拦截器起作用的是在 Ribbon 负载后边
    xuanbg
        7
    xuanbg  
       2019-10-12 14:23:36 +08:00
    没能理解楼主的问题在哪? Ribbon 的路由策略和拦截有啥关系?正常配自定义路由策略就好了吧。feign 请求加请求头的问题?是的话自己实现 feignClient 就行了。
    xuanbg
        8
    xuanbg  
       2019-10-12 14:27:35 +08:00
    上面说得不是很准确,不是自己实现 feignClient,是自己构建 feignClient,就像这样:
    TaskClient taskClient = Feign.builder().decoder(decoder).encoder(encoder)
    .requestInterceptor(template -> {
    Map<String, String> map = call.getHeaders();
    for (String k : map.keySet()) {
    String v = map.get(k);
    template.header(k, v);
    }
    }).target(TaskClient.class, getServiceUrl(call.getService()));
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2416 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 15:58 · PVG 23:58 · LAX 07:58 · JFK 10:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.