Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tomcat 不能 graceful shutdown #535

Closed
gtyang opened this issue Apr 12, 2018 · 9 comments · Fixed by #2583 or #2587
Closed

Tomcat 不能 graceful shutdown #535

gtyang opened this issue Apr 12, 2018 · 9 comments · Fixed by #2583 or #2587

Comments

@gtyang
Copy link

gtyang commented Apr 12, 2018

我的配置是 tomcat + spring boot mvc,从spring boot 的例子工程中修改出来的,sdk 的版本 2.9.6。部署到tomcat下运行,不能正常的shutdown,有很多线程不能shutdown,例如:

12-Apr-2018 20:24:51.951 WARNING [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [ROOT] appears to have started a thread named [pool-2-thread-9] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 sun.misc.Unsafe.park(Native Method)
 java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
 java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
 java.lang.Thread.run(Thread.java:748)

还有这类的:

12-Apr-2018 20:24:52.004 SEVERE [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks The web application [ROOT] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@2926f399]) and a value of type [com.github.binarywang.wxpay.bean.WxPayApiData] (value [
【请求地址】:https://api.mch.weixin.qq.com/pay/unifiedorder
【请求数据】:<xml>
  <appid>wxxxxxxx</appid>
  <mch_id>1xxx</mch_id>
  <nonce_str>1523530799119</nonce_str>
  <sign>3D1?????????????</sign>
  <body>abcddd</body>
  <out_trade_no>tx-341</out_trade_no>
  <total_fee>1</total_fee>
  <spbill_create_ip>172.31.233.29</spbill_create_ip>
  <time_start>20180412185959</time_start>
  <time_expire>20180412205959</time_expire>
  <notify_url>http://mp.x.moxxbi.com/pay/notify</notify_url>
  <trade_type>JSAPI</trade_type>
  <openid>oEKyxCRT93OmoI</openid>
</xml>
【响应数据】:<xml><return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wx????da0???]]></appid>
<mch_id><![CDATA[14966786487324-002]]></mch_id>
<nonce_str><![CDATA[EyuXgXeSJyDAeM4W]]></nonce_str>
<sign><![CDATA[F1C2CF6??????618B4D56EE74495A4686]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<prepay_id><![CDATA[wx12x883721bd45d2797498456]]></prepay_id>
<trade_type><![CDATA[JSAPI]]></trade_type>
</xml>]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.

我没看到在哪里设置graceful shutdown相关的配置,

请求帮助

@binarywang
Copy link
Owner

你这两种错误都属于网上常见警告或错误,并不影响使用,不过既然你觉得不爽,就可以在网上搜索对应相关错误信息,会找到很多种不同的分析和解决办法

@gtyang
Copy link
Author

gtyang commented Apr 13, 2018

这个问题的影响是不能正常的 shutdown tomcat,还要手工的 kill 进程,这个比较影响运维。

通常来讲这个问题是线程池没有shutdown,但是我不知道是那里的线程池,能找到这个线程池,我说可以在shutdown的钩子里去关闭它。

@binarywang
Copy link
Owner

那我明白你的意思了,第一个我估计应该是那个后台定期关闭空闲http请求的线程,第二个的话是使用的ThreadLocal的那个类,类名上面也列出来了,你可以先研究下怎么处理,如有可行办法,可以提供下,供其他人参考,或者如果是sdk需要配合修改的,麻烦提供一个PR,谢谢了

@gtyang
Copy link
Author

gtyang commented Apr 13, 2018

初步判断,是 WxMpMessageRouter 启动了一个线程池,但是没有shutdown。这个类没有暴露出这个线程池,所以没有办法处理这个池。


因为这个类只有一个构造方法 WxMpMessageRouter(WxMpService wxMpService),在这个构造方法中创建了线程池,所以后面即使在注入了外部的线程池,那么还是会存在一个没有shutdown的线程池的。

应该要有方法来关闭这个线程池才行。

```
 * @author Daniel Qian
 */
public class WxMpMessageRouter {

  private static final int DEFAULT_THREAD_POOL_SIZE = 100;
  protected final Logger log = LoggerFactory.getLogger(WxMpMessageRouter.class);
  private final List<WxMpMessageRouterRule> rules = new ArrayList<>();

  private final WxMpService wxMpService;

  private ExecutorService executorService;

  private WxMessageDuplicateChecker messageDuplicateChecker;

  private WxSessionManager sessionManager;

  private WxErrorExceptionHandler exceptionHandler;

  public WxMpMessageRouter(WxMpService wxMpService) {
    this.wxMpService = wxMpService;
    this.executorService = Executors.newFixedThreadPool(DEFAULT_THREAD_POOL_SIZE);
    this.messageDuplicateChecker = new WxMessageInMemoryDuplicateChecker();
    this.sessionManager = new StandardSessionManager();
    this.exceptionHandler = new LogExceptionHandler();
  }

  /**
   * <pre>
   * 设置自定义的 {@link ExecutorService}
   * 如果不调用该方法,默认使用 Executors.newFixedThreadPool(100)
   * </pre>
   */
  public void setExecutorService(ExecutorService executorService) {
    this.executorService = executorService;
  }

```

@binarywang
Copy link
Owner

3.0.2.BETA版本已加入相关支持

@gtyang
Copy link
Author

gtyang commented Apr 17, 2018

实证问题解决了 :)

binarywang added a commit that referenced this issue Jun 22, 2018
* #519 修复小程序客服消息 URL 被转义的问题

* 优化单元测试提示信息

* 网页授权url增加&connect_redirect=1参数解决两次重定向跳转问题: https://blog.csdn.net/jiangguilong2000/article/details/79416615

* 修复错误的feeToYuan方法名为fenToYuan

* #529 EntPayBankRequest增加默认构造函数

* #529 EntPayBankResult中cmmsAmount的数据类型改为Integer

* #528 WxMpUser类增加三个属性:subscribe_scene、 qr_scene 和qr_scene_str

* 修复代码

* 发布3.0.1.BETA测试版本

* #533 微信刷卡支付请求类增加缺少的三个参数

* #536 企业号模块增加获取企业号应用相关接口

* 定义《企业号应用》的bean

* 增加《获取企业号应用》接口实现

* 增加获取测试企业号应用信息测试类

* #535 修复Tomcat 不能正常关闭的问题,增加线程池shutdown相关的操作

* #541 企业号增加实现管理标签的(获取标签成员)接口 

* 定义《企业号应用》的bean

* 增加《获取企业号应用》接口实现

* 增加获取测试企业号应用信息测试类

* tag service增加获取标签成员方法
http://qydev.weixin.qq.com/wiki/index.php?title=管理标签

* #534 公众号发送模版消息中的小程序path改回pagepath

* 发布3.0.2.BETA测试版本

* #547 开放平台模块 componentAccessToken 增加过期自动刷新

* createOrder方法增加H5支付的支持

* #551 文本卡片消息增加btntext字段

* #550 企业微信删除标签成员接口增加部门列表参数

* 清理无用代码

* #530 微信支付申请退款接口结果类增加单个代金券相关参数 ,并根据官方文档整理其他参数

* #531 小程序WxMaMessage类增加小程序卡片消息相关的几个属性

* #520 企业微信网页授权增加使用user_ticket获取成员详情的接口

* 发布3.0.3.BETA测试版本

* 优化代码

* 完善测试

* #559 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀;

* #560 微信开放平台:增加小程序代码模板库管理 

* 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀;

* 微信开放平台:增加小程序代码模板库管理

* #562 小程序增加代码管理相关 API

* 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀;

* 微信开放平台:增加小程序代码模板库管理

* 小程序:增加代码管理相关 API

* #563 小程序增加修改服务器地址、成员管理 API 

* 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀;

* 微信开放平台:增加小程序代码模板库管理

* 小程序:增加代码管理相关 API

* 小程序:增加修改服务器地址、成员管理 API

* #565 小程序增加数据分析相关 API 

* 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀;

* 微信开放平台:增加小程序代码模板库管理

* 小程序:增加代码管理相关 API

* 小程序:增加修改服务器地址、成员管理 API

* 小程序:增加数据分析相关 API

* #567 微信开放平台增加 HTTP proxy 机制

* 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀;

* 微信开放平台:增加小程序代码模板库管理

* 小程序:增加代码管理相关 API

* 小程序:增加修改服务器地址、成员管理 API

* 小程序:增加数据分析相关 API

* 微信开放平台:增加 HTTP proxy 机制

* #568 修复三方平台多次授权时,RefreshToken 没有刷新的问题

* fix 多次授权时,RefreshToken 没有刷新

* null 判断

* 发布3.0.4.BETA测试版本

* fix code

* #569 微信支付几个查询关闭对账下载相关接口增加重载方法,以方便客户端指定更多参数

* #578 微信开放平台增加 WxMaUserService 的实现

* 微信开放平台:1. WxOpenInRedisConfigStorage 支持 JedisPool/JedisSentinelPool 等 Pool<Jedis> 的子类;2. WxOpenInRedisConfigStorage 增加 keyPrefix 以支持可配置的前缀;

* 微信开放平台:增加小程序代码模板库管理

* 小程序:增加代码管理相关 API

* 小程序:增加修改服务器地址、成员管理 API

* 小程序:增加数据分析相关 API

* 微信开放平台:增加 HTTP proxy 机制

* 微信开放平台:增加 WxMaUserService 的实现

* 修复小程序码的相关方法命名:WxCode->WxaCode, WxCodeLimit -> WxaCodeUnlimit

* #556 日志信息中如果含有secret值的,将其值隐藏掉

* #585 小程序二维码支持is_hyaline参数生成透明背景二维码

* 发布3.0.5.BETA测试版本

* #584 修复企业付款到银行卡接口签名失败的问题

* 简化代码

* #586 微信支付 WxPayConfig增加支持byte数组方式设置证书

* #581 增加微信公众号错误信息枚举类WxMpErrorMsg,并提供方法,方便根据错误代码查询错误信息内容

* #555 修复微信支付服务商模式支付验证签名失败的问题

* #521 微信支付回调通知类WxPayOrderNotifyResult增加version参数

* #583 企业微信新增人员接口新增字段to_invite

* #583 企业微信通讯录管理增加邀请成员接口

* #587 企业微信几个接口增加个人二维码字段

* 修复字符

* 修复单元测试

* 发布3.0.6.BETA测试版本

* 重构WxError相关代码,自动根据代码补充错误中文说明

* 优化微信支付代码

* #584 修复企业付款queryEntPay签名失败问题

* #591 文件上传接口不自动关闭inputStream,由调用方自己控制

* #595 优化WxPayException

* 发布3.0.7.BETA测试版本

* 更新pom

* 优化代码

* #615 公众号客服消息添加 "发送小程序卡片" 类型

* 优化XStreamTransformer

* 微信支付模块jodd-http修改scope

* 发布3.0.8.BETA测试版本

* #623 群发接口增加clientmsgid

* add author for some files

* clean code

* 重构规范RequestExecuter代码

* #532 实现微信AI开放接口的三个接口:语音上传、查询识别结果和微信翻译功能

* 发布3.0.9.BETA测试版本

* #516 增加获取Wi-Fi门店列表接口

* #629 修复WxPayOrderNotifyResult解析xml报错问题

* #639 修复小程序代码模版库管理 access_token key 错误

* 发布3.1.0正式版本
@nadirvishun
Copy link

同样遇到此问题,但是目前此pr只是能解决“微信公众号”的问题,企业微信的还是没有shutdown方法关闭,而且企业微信与公众号不同的是多个应用会存在多个WxCpService和多个WxCpMessageRouter,因为他不是和企业微信一样是用単例实现用switchover方式切换的,所以仅仅是增加shutdown方法也不好调用。而且shutdown方法最好增加awaitTermination()方法来保证超时关闭。
@binarywang ,麻烦看下能否修改企业微信sdk的调用方式和微信公众号一致(或者能实现关闭线程池也行)?并增加shutdown方法?

@binarywang
Copy link
Owner

同样遇到此问题,但是目前此pr只是能解决“微信公众号”的问题,企业微信的还是没有shutdown方法关闭,而且企业微信与公众号不同的是多个应用会存在多个WxCpService和多个WxCpMessageRouter,因为他不是和企业微信一样是用単例实现用switchover方式切换的,所以仅仅是增加shutdown方法也不好调用。而且shutdown方法最好增加awaitTermination()方法来保证超时关闭。 @binarywang ,麻烦看下能否修改企业微信sdk的调用方式和微信公众号一致(或者能实现关闭线程池也行)?并增加shutdown方法?

欢迎直接提供PR

@nadirvishun
Copy link

nadirvishun commented Apr 11, 2022

企业微信如果要改成和公众号类似的单例的形式我这边要提交pr的话有几个问题:

  • agentId并不一定是唯一的,如果恰好要集成多个企业的微信的话,可能会有冲突,所以是不是在WxCpDefaultConfigImpl中再增加一个成员变量cpId比较好,如果是单个企业,则可以用agentId赋值给cpId,多个企业可以用corpId + agentId赋值给cpId,或者是自定义能保证唯一就行。
  • 对于企业微信第三方的同样是有这个单例及线程池问题,但是我这边从来没作过第三方的集成,所以不是很清楚相关的逻辑。
  • 如果改动的话貌似是不好兼容以前的版本,这样没问题吗?

上方的pr仅仅是提交了增加线程池关闭的方法,如果有多个实例,那就遍历多个来结束线程池,暂时是能满足要求的,但是其它的都是单例的形式运行,就企业微信要实例化好几个,从行为上来说不是很统一。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants