浅析如何避免CPU飙高?还出现502了

75 篇文章 1 订阅
  • 业务足,那必须硬件条件够,也就是服务器配置足够
  • 业务不足,但还飙高如何处理?
  • 业务足,硬件也足,代码问题?

思考一个场景,您这边需要根据你库中的一个表,持续的去抓取第三方接口数据然后更新入库你会如何处理?

//采用分页脚本去跑脚本

 /**
     * 对接方提供接口我方抓取:门店订单抓取至商城脚本
     *  desc: 抓门店订单入库
     */
    public function actionGetOrderList()
    {
        set_time_limit(0);
        date_default_timezone_set("PRC");
        $store_list = array_column(Store::find()->where(['is_delete' => 0, 'is_recycle' => 0])->select(['id'])->asArray()->all(), 'id');
        if (empty($store_list)) {
            return;
        }

        $limit = 100;
        //遍历商户
        foreach ($store_list as $store_id) {
            if($store_id == 1){
                $option = Option::get('shop_order_list', 0, 'admin', '1');
            }else{
                $option = Option::get('shop_order_list', $store_id, 'admin');
            }
            if(!$option){
                continue;
            }
            $option = \Yii::$app->serializer->decode($option);
            if(!$option){
                continue;
            }
            $erp_member_list = Option::get('erp_member_list', $store_id, 'admin', '{"status":"0"}');
            if(!$erp_member_list){
                continue;
            }
            $erp_member_list = \Yii::$app->serializer->decode($erp_member_list);
            if ($erp_member_list['status'] != 1) {
                continue;
            }
            try {
                //循环会员卡结果集合
                $membership_data = \Yii::$app->cache->get(CacheKeyEnum::USER_MEMBER_DATA.$store_id);
                if(!$membership_data){
                    $count = UserMember::find()->where(['store_id' =>$store_id])->andWhere(['IS NOT', 'membership_number', null])->count();
                    \Yii::$app->cache->set(CacheKeyEnum::USER_MEMBER_DATA.$store_id,$count);
                    usleep(10*1000);
                }
                $count = \Yii::$app->cache->get(CacheKeyEnum::USER_MEMBER_DATA.$store_id);
                $j = \Yii::$app->cache->get(CacheKeyEnum::USER_MEMBER_DATA.$store_id."_i") ? : 0 ; //从上次跑的页数开始跑
                for ($i = $j; $i <= floor($count / $limit); $i++) {
                    $membership_numbers = UserMember::find()->select(['user_id','membership_number','wechat_union_id'])->where(['store_id' => $store_id])->andWhere(['IS NOT', 'membership_number', null])->limit($limit)->offset($i*$limit)->asArray()->all();
                    $membership_numbers = array_column($membership_numbers,null, 'membership_number');
                    foreach ($membership_numbers as $k =>$v){
                        if(empty($v['membership_number'])){
                            continue;
                        }
                        $param = [
                            'membership_number' => $v['membership_number'],
                        ];
                        $res = requestCardApi($option['order_list_url'], $param,$option['app_key'],1,true); //true限制超时时间3秒杀;防止对接方超时导致其他商户不可用
                        if($res['code'] == 0){
                            $user = UserMember::find()->where(['store_id'=>$store_id,'wechat_union_id'=>$v['wechat_union_id']])->one();
                            $user_id = $v['user_id'] ? :  ( $user ? $user->id : 0 );
                            $this->saveData($res['data'],$user_id,$store_id);
                        }else{
                            \Yii::error($res, date('Y-m-d H:i:s').'商户接口错误:会员卡抓取门店订单记录失败,商户ID:'.$store_id.',会员卡号:'.$v['membership_number']);
                        }
                    }
                    //记录跑的页数,跑完删除缓存,没跑完下次接着跑
                    \Yii::$app->cache->set(CacheKeyEnum::USER_MEMBER_DATA.$store_id."_i",$i+1);
                    usleep(10*1000);
                    if(floor($count / $limit) == $i){
                        \Yii::$app->cache->delete(CacheKeyEnum::USER_MEMBER_DATA.$store_id."_i");
                        \Yii::$app->cache->delete(CacheKeyEnum::USER_MEMBER_DATA.$store_id);
                    }
                    unset($membership_numbers);
                }
            } catch (\Exception $e) {
                \Yii::error(['data' => $e->getMessage()], date('Y-m-d H:i:s')."会员卡抓取门店订单记录失败商户ID:".$store_id);
            }
        }
    }
//直接大数组全部处理

 public function erpCoupon($erp_coupon_type)
    {
        date_default_timezone_set('PRC');
        $list = Store::find()->alias('S')->where(['S.is_delete' => 0, 'S.is_recycle' => 0])
            ->leftJoin(Option::tableName() . ' as O', 'O.store_id=S.id')
            ->where(['O.name' => 'interface_list'])
            ->select(['S.id', 'O.value'])->asArray()->all();

        foreach ($list as $key => $value) {
            $option = json_decode(json_decode($value['value'], true), true);
            if ($option['is_docking'] == 1) {//有开  获取相应的策略的id 的券
                $user_member = UserMember::find()
                    ->where(['store_id' => $value['id']])
                    ->andWhere(['<>', 'membership_number', ''])
                    ->select(['membership_number', 'user_id'])
                    ->asArray()
                    ->all();
                if (!empty($user_member)) {
                    $user_ids = array_column($user_member, 'user_id');
                    $query = UserCoupon::find()
                        ->alias('UC')
                        ->leftJoin(Coupon::tableName() . ' as C', 'UC.coupon_id = C.id')
                        ->where(['>', 'C.apprangeid', 0])
                        ->andWhere(['UC.is_expire' => 0, 'UC.store_id' => $value['id'], 'UC.user_id' => $user_ids, 'UC.erp_coupon_type' => $erp_coupon_type])
                        ->orderBy('UC.addtime DESC')
                        ->select(['UC.id', 'UC.user_id', 'UC.erp_coupon_type', 'UC.is_use', 'UC.is_expire', 'C.apprangeid']);

                    if ($erp_coupon_type == 2) {
                        $query->andWhere(['UC.is_use' => 0]);
                    }
                    $user_coupon = $query->asArray()->all();


                    $membership_number_arr = array_column($user_member, 'membership_number', 'user_id');
                    foreach ($user_coupon as $k => $val) {
                        $user_exist = array_key_exists($val['user_id'], $membership_number_arr);
                        if ($user_exist) {
                            $membership_number = $membership_number_arr[$val['user_id']];
                            if (empty($membership_number)) continue;
                        } else {
                            continue;
                        }
                        if ($erp_coupon_type == 0 && $val['is_expire'] == 0 && $val['is_use'] == 0) {
                            $redis = \Yii::$app->redis;
                            $cacheKey = CacheKeyEnum::ERP_COUPON . $val['id'];
                            $cache = $redis->get($cacheKey);
                            if (!$cache) {
                                $redis->setex($cacheKey, 300, $val['id']);
                                $param = [
                                    'insidercardno' => $membership_number,//会员卡号
                                    'apprangeid' => $val['apprangeid'],  //策略ID
                                    'num' => '1',
                                    'couponid' => $val['id'],  //第三方代金券ID
                                ];
                                $res = requestApi($option['generate_url'], $param, $option['app_key']);
                                if ($res['code'] == 1) {
                                    UserCoupon::updateAll(['erp_coupon_type' => 1], ['id' => $val['id']]);
                                }
                            }
                        } else {
                            if ($val['erp_coupon_type'] == 1 && $val['is_use'] == 1) {//使用下,才能核销
                                $data = [
                                    'insidercardno' => $membership_number,
                                    'couponid' => $val['id'],
                                    'exectype' => '1'
                                ];
                                $res = requestApi($option['write_off_url'], $data, $option['app_key']);
                                if ($res['code'] == 1) {
                                    UserCoupon::updateAll(['erp_coupon_type' => 2], ['id' => $val['id']]);
                                }
                            }
                            if ($val['erp_coupon_type'] == 2 && $val['is_use'] == 0) {// 退货 返回券时,被核销的优惠券 也返回 已领取
                                $data = [
                                    'insidercardno' => $membership_number,
                                    'couponid' => $val['id'],
                                    'exectype' => '2'
                                ];
                                $res = requestApi($option['write_off_url'], $data, $option['app_key']);
                                if ($res['code'] == 1) {
                                    UserCoupon::updateAll(['erp_coupon_type' => 1], ['id' => $val['id']]);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

对比效果;CPU直接爆满;而且使用分页的方式任务更多但CPU反而更小!是具有参考意义的。

 当然CPU飙高的原因很多,任务多,处理时间久,线程不够等,我们也可以根据top中sleeping进程数调高初始进程,或者业务上分离等。。。

上面说到的是如何防止CPU飙高,下面说说与第三方对接的坑如何避免502?

第三方提供一个接口,让取线下ERP流水订单展示在线上,但是那帮兔崽子竟然不做分页!!一次全部返回,之前因为一些特殊需求对数据进行了入库处理,现在发现不行!!会处理超时,所有仅在展示时直接调用第三方接口进行缓存!!不要入库了!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值