{"action":"created","issue":{"url":"https://api.github.com/repos/chanjarster/weixin-java-tools/issues/323","repository_url":"https://api.github.com/repos/chanjarster/weixin-java-tools","labels_url":"https://api.github.com/repos/chanjarster/weixin-java-tools/issues/323/labels{/name}","comments_url":"https://api.github.com/repos/chanjarster/weixin-java-tools/issues/323/comments","events_url":"https://api.github.com/repos/chanjarster/weixin-java-tools/issues/323/events","html_url":"https://github.com/chanjarster/weixin-java-tools/issues/323","id":171347053,"number":323,"title":"WxMpServiceImpl.executeInternal 方法阻塞导致服务器宕机的问题","user":{"login":"WesleyWu","id":833816,"avatar_url":"https://avatars.githubusercontent.com/u/833816?v=3","gravatar_id":"","url":"https://api.github.com/users/WesleyWu","html_url":"https://github.com/WesleyWu","followers_url":"https://api.github.com/users/WesleyWu/followers","following_url":"https://api.github.com/users/WesleyWu/following{/other_user}","gists_url":"https://api.github.com/users/WesleyWu/gists{/gist_id}","starred_url":"https://api.github.com/users/WesleyWu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/WesleyWu/subscriptions","organizations_url":"https://api.github.com/users/WesleyWu/orgs","repos_url":"https://api.github.com/users/WesleyWu/repos","events_url":"https://api.github.com/users/WesleyWu/events{/privacy}","received_events_url":"https://api.github.com/users/WesleyWu/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2016-08-16T07:56:14Z","updated_at":"2016-08-16T09:45:08Z","closed_at":null,"body":"目前方法的签名是这样的：\r\n\r\nprotected synchronized T executeInternal(RequestExecutor executor, String uri, E data) throws WxErrorException {...}\r\n\r\n里边执行了一个超耗时的https的阻塞请求，直到微信官方网站返回了执行结果，才会结束这个方法。\r\n\r\n所以，如果有多个线程通知执行 execute （然后 executeInternal），比如通过16个线程同时发送100万个模板消息，早晚都一定会发生一大堆线程阻塞在这个方法的起始处。\r\n\r\n我们就遇到了这个情况，用 jstack 查看我们的 jvm 的线程状况，大部分都这样：\r\n\"http-nio-8081-exec-188\" #1201 daemon prio=5 os_prio=0 tid=0x00007f99f0498000 nid=0x4822 waiting for monitor entry [0x00007f99c6ef4000]\r\njava.lang.Thread.State: BLOCKED (on object monitor)\r\nat me.chanjar.weixin.mp.api.WxMpServiceImpl.executeInternal(WxMpServiceImpl.java:729)\r\n- waiting to lock <0x00000000c7332ed8> (a me.chanjar.weixin.mp.api.impl.WxMpServiceImpl)\r\nat me.chanjar.weixin.mp.api.WxMpServiceImpl.execute(WxMpServiceImpl.java:705)\r\n\r\n于是，整个jvm的线程数量耗尽，导致tomcat假死，服务器资源消耗基本为0。\r\n\r\n所以我的问题如下：\r\n1、这里的这个 synchronized 关键字为什么一定要加？\r\n2、可以去掉不？\r\n3、如果去掉，会导致什么严重问题？\r\n\r\n感谢。"},"comment":{"url":"https://api.github.com/repos/chanjarster/weixin-java-tools/issues/comments/240055919","html_url":"https://github.com/chanjarster/weixin-java-tools/issues/323#issuecomment-240055919","issue_url":"https://api.github.com/repos/chanjarster/weixin-java-tools/issues/323","id":240055919,"user":{"login":"zxkane","id":843303,"avatar_url":"https://avatars.githubusercontent.com/u/843303?v=3","gravatar_id":"","url":"https://api.github.com/users/zxkane","html_url":"https://github.com/zxkane","followers_url":"https://api.github.com/users/zxkane/followers","following_url":"https://api.github.com/users/zxkane/following{/other_user}","gists_url":"https://api.github.com/users/zxkane/gists{/gist_id}","starred_url":"https://api.github.com/users/zxkane/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zxkane/subscriptions","organizations_url":"https://api.github.com/users/zxkane/orgs","repos_url":"https://api.github.com/users/zxkane/repos","events_url":"https://api.github.com/users/zxkane/events{/privacy}","received_events_url":"https://api.github.com/users/zxkane/received_events","type":"User","site_admin":false},"created_at":"2016-08-16T09:45:08Z","updated_at":"2016-08-16T09:45:08Z","body":"同步锁并不是导致tomcat资源耗尽的最终原因。\r\n\r\n你现在是把100w个消息短时间发送给服务器，而服务器处理这些请求的速度(对微信服务器的远程请求)远远跟不上请求进来的速度，会导致服务器没有可用的线程。\r\nWxMpServiceImpl.executeInternal函数有无这个同步锁，在你的这个请求量下都是一样的结局。\r\n\r\n合理的做法应该是有消费者来消费这100w个消息，并同步用wechat\r\napi发送请求给微信服务器。也就是说，处理不过来的消息在队列中等待，而不是一股脑扔给服务器程序。\r\n\r\n\r\nKane\r\n\r\nhttps://vme360.com\r\n\r\n2016-08-16 15:56 GMT+08:00 Wesley Wu <notifications@github.com>:\r\n\r\n> 目前方法的签名是这样的：\r\n>\r\n> protected synchronized T executeInternal(RequestExecutor executor, String\r\n> uri, E data) throws WxErrorException {...}\r\n>\r\n> 里边执行了一个超耗时的https的阻塞请求，直到微信官方网站返回了执行结果，才会结束这个方法。\r\n>\r\n> 所以，如果有多个线程通知执行 execute （然后 executeInternal），比如通过16个线程同时发送100万个模板消息，\r\n> 早晚都一定会发生一大堆线程阻塞在这个方法的起始处。\r\n>\r\n> 我们就遇到了这个情况，用 jstack 查看我们的 jvm 的线程状况，大部分都这样：\r\n> \"http-nio-8081-exec-188\" #1201 daemon prio=5 os_prio=0\r\n> tid=0x00007f99f0498000 nid=0x4822 waiting for monitor entry\r\n> [0x00007f99c6ef4000]\r\n> java.lang.Thread.State: BLOCKED (on object monitor)\r\n> at me.chanjar.weixin.mp.api.WxMpServiceImpl.executeInternal(\r\n> WxMpServiceImpl.java:729)\r\n>\r\n>    - waiting to lock <0x00000000c7332ed8> (a\r\n>    me.chanjar.weixin.mp.api.impl.WxMpServiceImpl) at\r\n>    me.chanjar.weixin.mp.api.WxMpServiceImpl.execute(\r\n>    WxMpServiceImpl.java:705)\r\n>\r\n> 于是，整个jvm的线程数量耗尽，导致tomcat假死，服务器资源消耗基本为0。\r\n>\r\n> 所以我的问题如下：\r\n> 1、这里的这个 synchronized 关键字为什么一定要加？\r\n> 2、可以去掉不？\r\n> 3、如果去掉，会导致什么严重问题？\r\n>\r\n> 感谢。\r\n>\r\n> —\r\n> You are receiving this because you are subscribed to this thread.\r\n> Reply to this email directly, view it on GitHub\r\n> <https://github.com/chanjarster/weixin-java-tools/issues/323>, or mute\r\n> the thread\r\n> <https://github.com/notifications/unsubscribe-auth/AAzeJ0LUo2mntPvDy3uoLlaVclqaK3q_ks5qgW0ggaJpZM4JlIKq>\r\n> .\r\n>\r\n"}}
{"actor":{"display_login":"zxkane"}}