`
ME-XICAN
  • 浏览: 24619 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

多线程消费使用HttpClient引发的坑

阅读更多

      最近公司短信平台又出问题了,所有客户端都能正常调用,但是就是没有给用户发送短信,然后用户大面积的投诉说收不到短信,业务做不下去。

短信平台框架实现简单的画了一个序列图,大致思想都在里面了。如下:


 

       关于收不到短信的问题以前就曾经出现过一次,原因是有一个短信渠道商的服务不太稳定,当时排查原因发现缓存队列中数据量很大,猜测是消费线程阻塞,再比对日志基本上确认是消费线程阻塞。后来慢慢排查代码才发现是由于短信服务商的api中在httpclient请求时没有设置超时时间,消费线程在使用该渠道商的服务时因为api没有设置超时时间,HttpClient出现阻塞,造成该消费线程长期阻塞后续消息无法消费,反应在用户体验上就是能正常点击,但是收不到短信,后台日志也没有具体体现,线上的解决办法就是重启,但是如果渠道商一旦出现调用问题,短期内就可能会频繁出现调用超时,没有设置超时时间则是短期内频繁出现阻塞。这个阻塞问题在自己事后私下搭建服务调用验证后证明猜想是正确的,HttpClient没有设置超时时间是会长期阻塞的。当时排查出这个问题后自己总结了几个解决方案:

a、重写短信渠道商的API接口

b、修改框架实现使用非阻塞消费线程进行处理,每个消息起一个线程处理

c、在自己服务商中添加超时机制

注意:这里httpclient版本是4.0,以下是对应超时时间设置:

CoreConnectionPNames.CONNECTION_TIMEOUT获取连接超时时间。如果该参数没有设置,那么默认的超时间在不同的OS下是不同的,Windows大概20s,Linux大概180s。为了在访问不存在网页造成的访问阻塞,建议访问时设置此参数。

CoreConnectionPNames.SO_TIMEOUT:数据传输时间。默认的SO_TIMEOUT是0,即一直等待。这也是造成长期阻塞的原因。

 

其中重写API接口当时觉得太麻烦,没有时间进行处理,重写框架呢就更麻烦了,后来找到的解决办法是在消费线程中调用API时进行异步调用,在使用对应渠道商时添加jdk中concurrent包下的Callable进行异步处理,同时解决了没有超时时间的问题。具体代码如下:

         ExecutorService service = Executors.newSingleThreadExecutor();
            Callable<Integer> callable  = new Callable<Integer>(){
                public Integer call() throws Exception{
                    ISms sms=new CHttpPost();
                     //API调用,返回调用结果
                    return sms.send(...);
                }
            };
            Future<Integer> future = service.submit( callable);
            service.shutdown();
            //最长等待三分钟
            if(service.awaitTermination (180000l, TimeUnit.MILLISECONDS) == false)
                throw new TimeOutException("**短信调用超时");
            result =future.get();//获取处理结果

       在awaitTermination时API请求已经在异步线程处理中,如果http请求正常则立即返回结果获取处理结果,否则出现长期阻塞则最长等到三分钟,然后抛出异常,消费线程进行下一个消息的处理。

当时出现这个问题时因为没有足够的重视,现在再次出现后才发现不止一个渠道商的API中没有设置超时时间,而且当时只在那个出现问题的渠道商的调用上添加了超时处理,并没发现其他渠道商也有没有超时设置的,这一点当时还认为是别人的服务low,现在再次出现问题不得不说自己公司的框架也是有坑的,如果能早点考虑到消费线程可能出现的这种长期阻塞现象,提前进行预防就不会出现因为别人的服务有问题而影响自己的服务运行了。

       这是一个个人踩过的坑,分享出来供小伙伴们借鉴学习,希望大家有问题能共同分享,一起进步。
 

 

  • 大小: 35.3 KB
分享到:
评论

相关推荐

    httpclient著名的多线程框架

    在Android系统中,由于主线程不能执行耗时操作,否则会引发ANR(Application Not Responding)错误,因此利用HttpClient的多线程特性,可以将网络请求放到后台线程,保证UI的流畅性。 HttpClient的使用步骤通常包括...

    httpclient多线程下载(分段下载)实践

    本篇文章将深入探讨如何使用HTTPClient进行多线程分段下载的实践。 首先,我们要理解多线程下载的基本原理。多线程下载是通过将大文件分割成多个小段,每个线程负责下载一个或多个段,这样可以充分利用多核处理器的...

    用HttpClient写了一个多线程下载软件

    标题中的“用HttpClient写了一个多线程下载软件”意味着我们将探讨如何使用Apache HttpClient库来创建一个支持多线程的文件下载应用。HttpClient是一个强大的Java库,它提供了丰富的HTTP客户端功能,包括请求发起、...

    android 学习笔记6-HttpClient 多线程下载 断点续传 进度条 源码关联

    4、多线程下载:使用RandomAccessFile输出流写 5、多线程下载-断点续传:使用临时文件记录当前下载的数据,下次读取文件开始下载 6、下载显示进度条-ProgressBar 7、在gitbub上面下载已经有支持断点续传功能的代码...

    HttpClient+ Spring实现多线程

    标题 "HttpClient + Spring 实现多线程" 涉及到的是如何在Spring框架中使用Apache HttpClient库来创建一个支持多线程的HTTP客户端服务。Apache HttpClient是一个强大的HTTP客户端API,它提供了丰富的功能来处理HTTP...

    使用java的HttpClient实现多线程并发

    通过使用HttpClient的连接池和多线程,我们可以有效地并发执行HTTP GET请求,同时控制并发数量,避免过多的网络连接导致服务器压力过大。这种方式提高了请求效率,减少了资源消耗,并且遵循了最佳实践。

    httpclient工具

    本文将详细讲解如何使用HTTPClient进行POST请求,并探讨在多线程环境下的应用,以及与"Grabticket"这个场景相关的实践。 HTTPClient是由Apache基金会开发的一个开源库,它提供了强大的功能来执行HTTP请求,包括GET...

    使用Apache HttpClient实现多线程下载的小例子

    这就是使用Apache HttpClient实现多线程下载的基本步骤。通过这种方式,我们可以有效地利用网络带宽,提高大文件下载的速度。同时,注意在实际应用中,还需要考虑错误处理、断点续传、下载进度显示等功能,以提升...

    使用HttpClient必须的jar包

    7. **异步处理**:HttpClient 4.5以上版本提供了异步客户端API,可以并发处理多个请求,提高应用的并发性能。 8. **SSL/TLS支持**:HttpClient可以配置为使用HTTPS协议,需要`httpmime-x.x.x.jar`(处理MIME类型,...

    使用HttpClient下载图片

    HttpClient是个很不错的开源框架(org.appache.http),封装了访问http的请求头,参数,内容体,响应等等,使用起来更方面更强大。 HttpURLConnection是java的标准类,可以实现简单的基于URL请求、响应功能,什么都...

    一个使用HttpClient调用天气预报接口的例程

    然而,由于这个例程使用了HttpClient,我们需要了解其工作原理和如何在Android环境中正确使用。 7. **注意事项**: - 异步处理:网络请求不应在主线程中进行,以免阻塞用户界面,应使用异步任务或Android的...

    SpringBoot使用httpclient发送Post请求时

    try(CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpPost httpPost = new HttpPost(url); StringEntity stringEntity = new StringEntity(params, Charset.forName("UTF-8")); ...

    java使用HttpClient通过url下载文件到本地

    - **创建HttpClient实例**:首先,我们需要创建一个HttpClient对象,例如使用`HttpClientBuilder`或`HttpClients.createDefault()`方法。 - **构建HttpGet请求**:使用`HttpGet`类创建一个HTTP GET请求,指定要...

    使用httpclient访问servlet

    本篇文章将详细探讨如何使用HttpClient来访问Servlet,并阐述相关的核心知识点。 首先,我们需要理解Servlet的本质。Servlet是一种Java类,它扩展了服务器的功能,用于处理HTTP请求并生成响应。通常,Servlet部署在...

    commons-httpclient-3.0.jar JAVA中使用HttpClient可以用到

    虽然`commons-httpclient-3.0.jar`是一个经典版本,但随着Java的发展,Apache社区已经推出了更现代的HttpClient 4.x系列,提供了更多改进和优化,如更好的线程安全、更丰富的API以及对HTTP/2的支持。因此,建议在新...

    使用HttpClient异步请求数据

    本篇将详细讲解如何使用`HttpClient`进行异步请求数据,并结合Android的`AsyncTask`来处理后台任务,避免阻塞UI线程。 首先,理解`HttpClient`的基本使用方法。`HttpClient`包含几个关键组件,如`HttpClient`实例、...

    使用HttpClient登录网易邮箱

    使用HttpClient登录网易邮箱 博文链接:https://bps.iteye.com/blog/136231

    java使用HttpClient发送http请求

    你可以阅读Apache HttpClient的源码,了解其内部的工作机制,如连接池管理、线程安全策略等。 “工具”标签表明HttpClient是一个实用工具,可以与其他Java项目集成,提高开发效率。在实际项目中,你可能需要结合...

    HttpClient 调用WebService示例

    在本文中,我们将深入探讨如何使用HttpClient调用WebService。 首先,调用WebService通常涉及SOAP(Simple Object Access Protocol)或RESTful API。HttpClient可以处理这两种类型的Web服务。在本示例中,我们假设...

    commons-httpclient,java中使用httpclient中使用的扩展工具

    默认实现`SingleClientConnManager`适用于单线程或短连接的应用,而`MultiThreadedHttpConnectionManager`则适合多线程和长时间运行的程序,它可以维护一个连接池,提高性能。 2. **请求构造**:你可以使用`...

Global site tag (gtag.js) - Google Analytics