又一次Task.Wait引起的教训

沙海 2021年6月29日01:08:09Java评论27字数 3202阅读10分40秒阅读模式
摘要

智能摘要

智能摘要文章源自JAVA秀-https://www.javaxiu.com/35750.html

BeetleX的tcpclient中使了无限超时来等待ssl验证环节,正常局域网环境这个等待是不会卡死的,毕竟网内环境良好要么成功要因异常触发取消等。但在网络差的环境下就存在问题了,socket的异步receive无法触发异常引起这个Wait把线程永久挂起了,当一段时间太多这种情况出现那非常的事情就是大量线程被这个Wait抽干导致服务不能正常工作。把超时设置成5秒,在创建连接5秒后ssl还没有握手成功就直接超时关闭连接重新创建。文章源自JAVA秀-https://www.javaxiu.com/35750.html

原文约 700 | 图片 1 | 建议阅读 1 分钟 | 评价反馈文章源自JAVA秀-https://www.javaxiu.com/35750.html

又一次Task.Wait引起的教训

原创 beetlex.io beetlex 文章源自JAVA秀-https://www.javaxiu.com/35750.html

收录于话题文章源自JAVA秀-https://www.javaxiu.com/35750.html

#Beetlex14文章源自JAVA秀-https://www.javaxiu.com/35750.html

#httpclient6文章源自JAVA秀-https://www.javaxiu.com/35750.html

#性能优化1文章源自JAVA秀-https://www.javaxiu.com/35750.html

        最近一用户在使用BeetleX.HttpClient组件并发访问延时比较高的https服务时引起了卡死现像。由于组件更多使用场景是内部服务和非https,一直没有这情况出现;但用户提供测试场景下这情况必现,所以翻查了一些相关代码。文章源自JAVA秀-https://www.javaxiu.com/35750.html

    protectedvirtualvoidOnSslAuthenticate(SslStream sslStream) { Task task;if (SslProtocols == null) SslProtocols = System.Security.Authentication.SslProtocols.Tls | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls12; task = sslStream.AuthenticateAsClientAsync(SslServiceName, CertificateCollection.Count > 0 ? CertificateCollection : null, SslProtocols.Value, false);            task.Wait(); }
    文章源自JAVA秀-https://www.javaxiu.com/35750.html

    BeetleX的tcpclient中使了无限超时来等待ssl验证环节,正常局域网环境这个等待是不会卡死的,毕竟网内环境良好要么成功要因异常触发取消等。但在网络差的环境下就存在问题了,socket的异步receive无法触发异常引起这个Wait把线程永久挂起了,当一段时间太多这种情况出现那非常的事情就是大量线程被这个Wait抽干导致服务不能正常工作。文章源自JAVA秀-https://www.javaxiu.com/35750.html

            为了解决这些比较特殊的情况加上超时时间就好了文章源自JAVA秀-https://www.javaxiu.com/35750.html

      protectedvirtualvoidOnSslAuthenticate(SslStream sslStream) { Task task;if (SslProtocols == null) SslProtocols = System.Security.Authentication.SslProtocols.Tls | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls12; task = sslStream.AuthenticateAsClientAsync(SslServiceName, CertificateCollection.Count > 0 ? CertificateCollection : null, SslProtocols.Value, false);if (!task.Wait(5000)) {thrownew BeetleX.BXException($"connect {mIPAddress}:{mPort} SSL Authenticate timeout!"); } }
      文章源自JAVA秀-https://www.javaxiu.com/35750.html

      把超时设置成5秒,在创建连接5秒后ssl还没有握手成功就直接超时关闭连接重新创建。文章源自JAVA秀-https://www.javaxiu.com/35750.html

              基础的问题解决了,但httpclientpool层面还有一个问题需要处理。当连接池一开始处于满负载请求,同时创建大量的Client会引起大量线程等待导致服务不太稳定(毕竟在不很多稳定的网络环境下ssl握手时间有些长)。为了解决问题使用一个指定的线程数的队列来创建ssl握手处理机制,这样就可以避免同时创建大量连接线程引起短暂卡壳现象。文章源自JAVA秀-https://www.javaxiu.com/35750.html

        public Task<HttpClientHandler> Pop() { HttpClientHandler result; TaskCompletionSource<HttpClientHandler> completionSource;lock (this) {if (mPools.Count > 0) { result = mPools.Pop(); result.Using = true; result.TimeOut = BeetleX.TimeWatch.GetElapsedMilliseconds() + TimeOut;return Task.FromResult(result); }if (Clients.Count > MaxConnections) {if (mWaitQueue.Count < MaxWaitLength) { completionSource = new TaskCompletionSource<HttpClientHandler>(); mWaitQueue.Enqueue(completionSource);return completionSource.Task; }else {thrownew HttpClientException($"Request {Host} connections limit"); } } } completionSource = new TaskCompletionSource<HttpClientHandler>(); mCreateDispatchCenter.Next().Enqueue(new CreateClientTask { ClientHandlerPool = this, CompletionSource = completionSource });return completionSource.Task;        }struct CreateClientTask {public TaskCompletionSource<HttpClientHandler> CompletionSource;public HttpClientHandlerPool ClientHandlerPool; }privatestatic BeetleX.Dispatchs.DispatchCenter<CreateClientTask> mCreateDispatchCenter = new Dispatchs.DispatchCenter<CreateClientTask>(OnProcessCreateClient, 20);privatestaticvoidOnProcessCreateClient(CreateClientTask e) {try {var result = e.ClientHandlerPool.Create(); result.Using = true; result.TimeOut = BeetleX.TimeWatch.GetElapsedMilliseconds() + e.ClientHandlerPool.TimeOut; e.CompletionSource.TrySetResult(result); }catch (Exception e_) { e.CompletionSource.TrySetException(e_); } }
        文章源自JAVA秀-https://www.javaxiu.com/35750.html

        简单修改一下连接池Pop方法的代码就可以了。文章源自JAVA秀-https://www.javaxiu.com/35750.html

        BeetleX

        开源跨平台通讯框架(支持TLS)提供高性能服务和大数据处理解决方案文章源自JAVA秀-https://www.javaxiu.com/35750.html

        又一次Task.Wait引起的教训文章源自JAVA秀-https://www.javaxiu.com/35750.html

        https://beetlex.io文章源自JAVA秀-https://www.javaxiu.com/35750.html

        继续阅读
        速蛙云 - 极致体验,强烈推荐!!!购买套餐就免费送各大视频网站会员!快速稳定、独家福利社、流媒体稳定解锁!速度快,全球上网、视频、游戏加速、独立IP均支持!基础套餐性价比很高!这里不多说,我一直正在使用,推荐购买:https://www.javaxiu.com/59919.html
        weinxin
        资源分享QQ群
        本站是JAVA秀团队的技术分享社区, 会经常分享资源和教程; 分享的时代, 请别再沉默!
        沙海
        • 版权声明:本站是JAVA秀团队的技术分享社区,我们会经常分享资源和教程。
        • 转载请注明:又一次Task.Wait引起的教训 - JAVA秀 ☜(ˆ▽ˆ)
        匿名

        发表评论

        匿名网友 填写信息

        :?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

        确定