swoft icon indicating copy to clipboard operation
swoft copied to clipboard

请求会有概率没反应,一直卡住,也没返回

Open leunico opened this issue 4 years ago • 18 comments

Q A
Bug report? yes
Feature request? yes
Swoft version 2.0.9 (by php bin/swoft -V)
Swoole version 4.5.1 (by php --ri swoole)
PHP version 7.2.18 (by php -v)
Runtime environment Ubuntu

有概率会请求没反应,200worker 200taskworker 16核32G 平时请求并发600左右 然后有一个接口请求会有概率没有任何反应,一直卡住那种(代码里面有熔断也没触发) 企业微信截图_20200615105531

这是请求方法

  /**
     * xxxxx
     * 
     * @Breaker()
     * @RequestMapping(route="/api/subscribe/shops",method="get")
     * @Validate(validator="SubscribeListValidator",type=ValidateType::GET,params={"universal_union_id"})
     * 
     * @param \Swoft\Http\Message\Request $request
     * @return \Swoft\Http\Message\Response
     * @author dexter
     * @throws Throwable
     */
    public function shopList(Request $request): Response
    {
        $universalUnionId = $request->input('universal_union_id', '');
        $pageLimit = (int) $request->input('limit', 50);
        $page = (int) $request->input('page', 1);
        $return = ['shop_list' => [], 'total' => 0];

        $allsub = SubscribeDao::suffix($universalUnionId)
            ->select('app_id', 'id', 'resource_id as resources_id', 'resource_type', 'content_app_id')
            ->where('universal_union_id', $universalUnionId)
            ->where('status', SubscribeDao::STATUS_OPEN)
            ->orderBy('created_at', 'desc')
            ->get()
            ->whereIn('resource_type', SubscribeDao::RESOURCE_APP)
            ->groupBy('app_id');

        $subscribes = empty($pageLimit) ? $allsub : $allsub->slice(($page - 1) * $pageLimit, $pageLimit);
        if ($subscribes->isEmpty()) {
            return Utils::success($return);
        }

        $shops = DB::query('mysql_config.pool')
            ->from('t_app_conf')
            ->select('shop_name', 'shop_logo as shop_icon', 'app_id')
            ->whereIn('app_id', $subscribes->keys())
            ->where('wx_app_type', 1)
            ->get()
            ->keyBy('app_id');

        $return['total'] = $allsub->count();
        foreach ($subscribes->toArray() as $key => $value) {
            if (! isset($shops[$key])) {
                return Utils::error(StringConstants::Code_Failed, '店铺数据异常[' . $key . ']');
            }
            $item = $shops[$key];
            $item->resources = array_slice($value, 0, 3);
            $return['shop_list'][] = $item;
        }
        
        return Utils::success($return);
    }

leunico avatar Jun 15 '20 03:06 leunico

这个时间点或之前有错误日志吗

inhere avatar Jun 15 '20 04:06 inhere

这个时间点或之前有错误日志吗

没有任何日日志,-d模式下运行的,我在日志文件没看到任何报错

leunico avatar Jun 15 '20 04:06 leunico

会不会跟数据库的连接池有关系,可是我不明白为啥会卡住没有任何返回,就一直卡着

leunico avatar Jun 15 '20 04:06 leunico

连接池有没有设置超时时间,有可能是连接用完了

lengfengbyit avatar Jun 16 '20 03:06 lengfengbyit

去掉下面这段代码就好了,我怀疑连接池的切换会有问题

连接池有没有设置超时时间,有可能是连接用完了

用完了不会建立新的连接吗?还是是固定的连接数?用完了啥都没返回就很奇怪=。=

leunico avatar Jun 16 '20 03:06 leunico

如果在连接池的配置中没有设置  maxWaitTime  这个参数, 当连接池中没有可用的连接后, 默认是永久等待,  就会造成卡死的情况。 

目前发现rpc-client有一个bug, 在src/Concern/ServiceTrait.php中的 sendAndRecv 方法中抛出了异常, 但是没有回收连接, 会导致连接耗尽

------------------ 原始邮件 ------------------ 发件人: "Leunico"<[email protected]>; 发送时间: 2020年6月16日(星期二) 中午11:14 收件人: "swoft-cloud/swoft"<[email protected]>; 抄送: "冷锋"<[email protected]>;"Comment"<[email protected]>; 主题: Re: [swoft-cloud/swoft] 请求会有概率没反应,一直卡住,也没返回 (#1313)

去掉下面这段代码就好了,我怀疑连接池的切换会有问题

连接池有没有设置超时时间,有可能是连接用完了

用完了不会建立新的连接吗?还是是固定的连接数?用完了啥都没返回就很奇怪=。=

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

lengfengbyit avatar Jun 16 '20 06:06 lengfengbyit

这个我理解了,但是swoft的熔断没有触发也很奇怪。。。。

leunico avatar Jun 16 '20 08:06 leunico

swoft的熔断是服务端熔断, 现在是客户端根本连接不上服务端, 所以自然没办法熔断

------------------ 原始邮件 ------------------ 发件人: "Leunico"<[email protected]>; 发送时间: 2020年6月16日(星期二) 下午4:33 收件人: "swoft-cloud/swoft"<[email protected]>; 抄送: "冷锋"<[email protected]>;"Comment"<[email protected]>; 主题: Re: [swoft-cloud/swoft] 请求会有概率没反应,一直卡住,也没返回 (#1313)

如果在连接池的配置中没有设置  maxWaitTime  这个参数, 当连接池中没有可用的连接后, 默认是永久等待,  就会造成卡死的情况。  目前发现rpc-client有一个bug, 在src/Concern/ServiceTrait.php中的 sendAndRecv 方法中抛出了异常, 但是没有回收连接, 会导致连接耗尽 … ------------------ 原始邮件 ------------------ 发件人: "Leunico"<[email protected]>; 发送时间: 2020年6月16日(星期二) 中午11:14 收件人: "swoft-cloud/swoft"<[email protected]>; 抄送: "冷锋"<[email protected]>;"Comment"<[email protected]>; 主题: Re: [swoft-cloud/swoft] 请求会有概率没反应,一直卡住,也没返回 (#1313) 去掉下面这段代码就好了,我怀疑连接池的切换会有问题 连接池有没有设置超时时间,有可能是连接用完了 用完了不会建立新的连接吗?还是是固定的连接数?用完了啥都没返回就很奇怪=。= — You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe. 这个我理解了,但是swoft的熔断没有触发也很奇怪。。。。

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

lengfengbyit avatar Jun 16 '20 08:06 lengfengbyit

swoft的熔断是服务端熔断, 现在是客户端根本连接不上服务端, 所以自然没办法熔断 ------------------ 原始邮件 ------------------ 发件人: "Leunico"<[email protected]>; 发送时间: 2020年6月16日(星期二) 下午4:33 收件人: "swoft-cloud/swoft"<[email protected]>; 抄送: "冷锋"<[email protected]>;"Comment"<[email protected]>; 主题: Re: [swoft-cloud/swoft] 请求会有概率没反应,一直卡住,也没返回 (#1313) 如果在连接池的配置中没有设置  maxWaitTime  这个参数, 当连接池中没有可用的连接后, 默认是永久等待,  就会造成卡死的情况。  目前发现rpc-client有一个bug, 在src/Concern/ServiceTrait.php中的 sendAndRecv 方法中抛出了异常, 但是没有回收连接, 会导致连接耗尽 … ------------------ 原始邮件 ------------------ 发件人: "Leunico"<[email protected]>; 发送时间: 2020年6月16日(星期二) 中午11:14 收件人: "swoft-cloud/swoft"<[email protected]>; 抄送: "冷锋"<[email protected]>;"Comment"<[email protected]>; 主题: Re: [swoft-cloud/swoft] 请求会有概率没反应,一直卡住,也没返回 (#1313) 去掉下面这段代码就好了,我怀疑连接池的切换会有问题 连接池有没有设置超时时间,有可能是连接用完了 用完了不会建立新的连接吗?还是是固定的连接数?用完了啥都没返回就很奇怪=。= — You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe. 这个我理解了,但是swoft的熔断没有触发也很奇怪。。。。 — You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

没有,应该连上了的,因为已经在代码里面运行了,比如查数据的时候发现连接池连接数不够这个时候已经是服务端在处理了,但是里面的代码超时却没有出现熔断,我看代码连接池的超时和熔断都是管道控制的,不知道是不是影响了

leunico avatar Jun 16 '20 09:06 leunico

这个时间点或之前有错误日志吗

想问下为啥这里会触发不了熔断?

leunico avatar Jun 16 '20 09:06 leunico

连接池的这个参数实则了吗?  maxWaitTime

------------------ 原始邮件 ------------------ 发件人: "Leunico"<[email protected]>; 发送时间: 2020年6月16日(星期二) 下午5:22 收件人: "swoft-cloud/swoft"<[email protected]>; 抄送: "冷锋"<[email protected]>;"Comment"<[email protected]>; 主题: Re: [swoft-cloud/swoft] 请求会有概率没反应,一直卡住,也没返回 (#1313)

swoft的熔断是服务端熔断, 现在是客户端根本连接不上服务端, 所以自然没办法熔断 … ------------------ 原始邮件 ------------------ 发件人: "Leunico"<[email protected]>; 发送时间: 2020年6月16日(星期二) 下午4:33 收件人: "swoft-cloud/swoft"<[email protected]>; 抄送: "冷锋"<[email protected]>;"Comment"<[email protected]>; 主题: Re: [swoft-cloud/swoft] 请求会有概率没反应,一直卡住,也没返回 (#1313) 如果在连接池的配置中没有设置  maxWaitTime  这个参数, 当连接池中没有可用的连接后, 默认是永久等待,  就会造成卡死的情况。  目前发现rpc-client有一个bug, 在src/Concern/ServiceTrait.php中的 sendAndRecv 方法中抛出了异常, 但是没有回收连接, 会导致连接耗尽 … ------------------ 原始邮件 ------------------ 发件人: "Leunico"<[email protected]>; 发送时间: 2020年6月16日(星期二) 中午11:14 收件人: "swoft-cloud/swoft"<[email protected]>; 抄送: "冷锋"<[email protected]>;"Comment"<[email protected]>; 主题: Re: [swoft-cloud/swoft] 请求会有概率没反应,一直卡住,也没返回 (#1313) 去掉下面这段代码就好了,我怀疑连接池的切换会有问题 连接池有没有设置超时时间,有可能是连接用完了 用完了不会建立新的连接吗?还是是固定的连接数?用完了啥都没返回就很奇怪=。= — You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe. 这个我理解了,但是swoft的熔断没有触发也很奇怪。。。。 — You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

没有,应该连上了的,因为已经在代码里面运行了,比如查数据的时候发现连接池连接数不够这个时候已经是服务端在处理了,但是里面的代码超时却没有出现熔断,我看代码连接池的超时和熔断都是管道控制的,不知道是不是影响了

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

lengfengbyit avatar Jun 16 '20 09:06 lengfengbyit

连接池的这个参数实则了吗?  maxWaitTime

对,我在本地试了,的确会出现这种一直卡住的情况,但是得关了熔断,否则会先抛出熔断

leunico avatar Jun 16 '20 09:06 leunico

@lengfengbyit 现象是间歇性的连不上rpc服务吗?能分享一下暂时怎么解决的吗?

yumindayu avatar Jun 17 '20 01:06 yumindayu

我这边遇到的情况是, rpc-client连接池耗尽连接的问题, 昨天提了bug, 官方将会再下个版本解决,  我们目前是先修改了源码,手动释放连接, 等官方发布下个版本, 在发布代码

rpc的连接池配置里加上 maxWaitTime  这个参数,  如果 报下面这个错误就是连接池里的连接耗尽了

连接池取连接超时,我设置的超时时间是5秒, 没有设置默认是0,就会卡死, 不会报错 Channel pop timeout by 5.000000s

------------------ 原始邮件 ------------------ 发件人: "yumindayu"<[email protected]>; 发送时间: 2020年6月17日(星期三) 上午9:52 收件人: "swoft-cloud/swoft"<[email protected]>; 抄送: "冷锋"<[email protected]>;"Mention"<[email protected]>; 主题: Re: [swoft-cloud/swoft] 请求会有概率没反应,一直卡住,也没返回 (#1313)

@lengfengbyit 现象是间歇性的连不上rpc服务吗?能分享一下暂时怎么解决的吗?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

lengfengbyit avatar Jun 17 '20 02:06 lengfengbyit

请问你是在哪里修改手动释放连接代码的?楼上的?

yyuemc avatar Jul 12 '20 14:07 yyuemc

这个文件: vendor/swoft/rpc-client/src/Concern/ServiceTrait.php

------------------ 原始邮件 ------------------ 发件人: "swoft-cloud/swoft" <[email protected]>; 发送时间: 2020年7月12日(星期天) 晚上10:19 收件人: "swoft-cloud/swoft"<[email protected]>; 抄送: "冷锋"<[email protected]>;"Mention"<[email protected]>; 主题: Re: [swoft-cloud/swoft] 请求会有概率没反应,一直卡住,也没返回 (#1313)

请问你是在哪里修改手动释放连接代码的?楼上的?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

lengfengbyit avatar Jul 13 '20 03:07 lengfengbyit

帮忙把修改之后的ServiceTrait.php代码贴一下可好?我也同样遇到这个问题了,不返回任何东西。

这个我分析是这个原因:分布式大量重复提交插入或更新同一个数据同一条记录,首先导致数据库锁,因为我在数据库中有大量锁的报错,Mysql的超时默认是50秒,也就是说要50秒那个连接池的连接才会释放,导致swoft的连接池占满而释放非常慢,最终导致连接池耗尽,最后请求任何接口时导致无连接池可用,导致整个Swoft服务死掉了~!

由数据库锁未及时释放引起的连锁反应!不知你是否与我一样的情况

解决方式应该是先解决大量重复提交,避免引行锁表,因为锁表之后不管你连接池多少都会卡在那里,设置maxWaitTime只是缓解

yyuemc avatar Jul 14 '20 03:07 yyuemc

可以看下github的仓库, 这个bug官方已经修改了

lengfengbyit avatar Jul 14 '20 03:07 lengfengbyit