hystrix问题 小总结 及 网络相关知识点

1.关于网络,在分布式系统中,底层的网络通讯皆为 asynchronous communication,需要 看 操作系统 & unix 网络编程 

书籍 Richard Stevens 的 “UNIX® Network Programming Volume 1, Third Edition: The Sockets Networking ”,

6.2节“I/O Models ”

spark 2.0 通信层不适用 akka 转为 netty,

tomcat 为什么不用 Netty作成 non-blocking event-driven 容器。想像tomcat没有servlet规范就知道了。servlet规范 解耦了 处理请求的类 以及 处理业务的类,通过servlet接口以及servlet容器把两者分工明确。也就是 connector和 container,推荐书籍 how tomcat works,这本后续章节没细看,再深入一下container部分讲解会更佳。

说个问题:hystrix熔断功能,tomcat-1执行 hystrixCommand.initilizeContext()后,在hystrix-smsv1-1线程调用restTemplate调第三方服务,熔断超时时间为 3秒,调用第三方服务偶尔会超3秒导致走熔断逻辑,也就是 hystrix-timer-1线程执行 fallback方法去调 另一个降级的服务,但在第四秒或者第八秒(因为生产日志出现的这两个时间间隔)结果返回了,那么本次调用的最终返回结果是熔断线程hystirx-timer-1的结果,但是还是会走完hystrix-smsv1-1 process的逻辑代码,此时,hystrix-smsv1-1在执行 hystirxVariable的时候出现了 HystrixCommand.initializeContext() should executed before invoke hystrixVariable.get() 的报错,按道理之前tomcat-1 中 已经初始化了上下文,并传递给了hystrix-smsv1-1(我debug过)

在线程切换中会不会就是导致了hystrix那个bug,问题的关键 到底这个线程是什么时候生成的?如何调度的?这个需要研究一下 Rxjava的理解以及使用。导致了走了熔断后, 原线程返回结果在同名线程接受时,报错为 HystrixCommand.initializeContext() should executed before invoke hystrixVariable.get()的异常信息。这里的报错应该是出在 Rxjava框架在 监听时,切换线程的时间消耗导致了 原线程的销毁或者作了操作,没有 了上下文,到底这里的上下文是哪种原因(1.原线程死了,2.原线程没死,上下文没了)此处作记录,等解决了这个问题后,贴出答复。

================================================================================================

以下内容编辑于 2019.11.18 16:36

问题已经定位,并且解决。

问题的原因在于hystrix调用超时走了fallback以后,fallback的方法在10ms以内将结果返回给了client,导致这个请求的上下文全部清除,再过1秒,第三方的结果返回了,然后从阻塞的地方继续执行,则 HystrixRequestVariableDefault.get()-> HystrixRequestContext.getContextForCurrentThread() 时,就返回 上下文没有初始化的异常报错。所以将 HystrixRequestVariableDefault.get()提前就可以完美解决这个兼容正常走和超时走 这两种情况。ok这里拓展下熔断的基本流程,或者官方文档

1.正常请求访问调用 @HystrixCommand注解修饰的方法

2.出现 timeout/exception/自定义的异常结果 时,走熔断,借助 RxJava.jar可以打断点 在 两个地方

 第一个地方 com.netflix.hystrix.HystrixCommand
protected final Observable<R> getExecutionObservable() {
        return Observable.defer(new Func0<Observable<R>>() {
            public Observable<R> call() {
                try {
                    return Observable.just(HystrixCommand.this.run());
                } catch (Throwable var2) {
                    return Observable.error(var2);
                }
            }
        }).doOnSubscribe(new Action0() {
            public void call() {
                // add break point here,u can pass this point after waiting for 3-4 seconds
                HystrixCommand.this.executionThread.set(Thread.currentThread());
            }
        });
    }

     第二个地方 com.netflix.hystrix.HystrixCommand

protected final Observable<R> getFallbackObservable() {
        return Observable.defer(new Func0<Observable<R>>() {
            public Observable<R> call() {
                try {
            // add break point here, u can pass this point after waiting for 3-4 seconds
                    return Observable.just(HystrixCommand.this.getFallback());
                } catch (Throwable var2) {
                    return Observable.error(var2);
                }
            }
        });
    }

这两个地方打断点之后,走到第一个断点 你 停 2-3秒执行,在第二个断点等 2-3秒执行,就会出现那个问题。但是那个问题的最本质原因是fallback结果返回了导致上下文清空。

3.在1分钟内出现两次异常时,直接走熔断,不走原来的方法。

4.再过30秒,出现会尝试放开部分请求去访问第三方地址 ,如果还是失败则还是走fallback。

5.直到访问第三方地址正常之后,才关闭 circurt broker.

附带上 我之前梳理的 报错的流程:

1. client请求 gateway/sms/v2 接口 tomcat线程池 按照serlvet规范 分配一个线程 tomcat-1处理该 request,在 filter 初始化了HystrixRequestContext
2. 进入hystrixCommand注解修饰的方法,hystrix线程池 分配线程id为 sms-v2-1 的线程处理,调用 第三方服务,此时超时3秒,走熔断逻辑
3. 由于走熔断逻辑 hystrix-core.jar 依赖 RxJava.jar的观察者模式以及异步特性,此时 创建线程id为 hystrix-timer-1的线程走 fallback方法调我测的hbase服务,由于hbase服务的响应只需 300ms左右,整个观察链将这个结果返回给 client。此时整个观察链结束,销毁父子线程的上下文。
4. 又过了1秒 返回结果到时已经没有上下文了,虽然接收的线程id是同一个,但是这只是在并发量不大,没有竞争条件时 OS 线程调度算法 择 最近使用的一个线程去处理这个结果罢了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值