6

この質問はおそらく大量の何かを行うことに関連している可能性がありますが、この場合、私は電子メールを送信しようとしています.

ユーザーが待たないように新しいスレッドで送信プロセスをセットアップし、リクエストのタイムアウトを1時間にオーバーライドしました。

問題は、プロセスが約 2000 通の電子メールを送信すると (以下のコードで約 2000 回ループ)、サーバーがメモリ不足になり、応答を停止し、再起動が必要になることです。

これに関する他のトピックを読むと、CF はこの量の電子メールをうまく処理できるはずです。

私が検討したことの 1 つは、すべてのオブジェクト呼び出しをストレート DB クエリに変更し、cfmail タグを使用して (私が推測するに) すべてのオブジェクトが作成されないようにし、リーチ リクエストで構築されないようにすることです (これが起こっていることだと思います)。それが違いを生むかどうかわからないので、可能であればそのアプローチを避けたいと思っています。私が考えた他のことは、それを3つまたは4つの別々のスレッドに分割することでしたが、それが問題を解決するかどうかはわかりません.

誰かがこの問題に直面したことがありますか? RAM がゆっくりといっぱいになり、サーバーを強制終了することなく処理を続行できるようにするために何が機能したと思いますか?

thread name="sendBroadcastEmail" rc="#rc#" prc="#prc#" filters="#rc.filters#" email="#email#" emailSignature="#emailSignature#"{
    createObject( "java", "coldfusion.tagext.lang.SettingTag" ).setRequestTimeout(javaCast( "double", 3600 ));

        //get profiles that it will be sent to
        var sendToProfiles = profileService.getWithFilters(rc.filters);

        var mailService = getPlugin("MailService");
        var emailSent = false;
        var sentCount = 0;
        var failedCount = 0;

        //send the email (and log in profile events)
        if (listFind(attributes.rc.email.action,'send')){

            for ( i=1; i<=arrayLen(sendToProfiles);i++){
                var profile = sendToProfiles[i];
                try{

                    if (len(trim(profile.getPrimaryEmail()))){

                        var emailBody = profile.processDynamicPlaceholders(attributes.rc.email.body);
                        var emailBody = attributes.emailSignature.getHeader() & emailBody & attributes.emailSignature.getFooter();

                        var sendEmail = mailService.newMail(
                             from = attributes.emailSignature.getEmailAddress(),
                             //to = profile.getPrimaryEmail(),
                             to = Application.settings.testemail,
                             subject = attributes.rc.email.subject,
                             body = emailBody,
                             type="html");

                             sendEmail.addMailParam(disposition='attachment', file=attributes.email.getAttachmentWithPath());
                             mailService.send(sendEmail);

                        //log profile event
                        profile.saveEvent(eventType = 3,
                                        title="Broadcast Email: #attributes.rc.email.subject#", 
                                        description="Broadcast Email Sent: Subject: <br> #attributes.rc.email.subject#",
                                        sentContent=emailBody,
                                        ref2=1);
                    sentCount++;
                    }
                }
                catch (any exception){
                    //log profile event
                    profile.saveEvent(eventType = 3,
                                    title="FAILED Broadcast Email", 
                                    description="<br>Subject: #attributes.email.subject#<br>This email should have been sent to this profile, but the attempted send failed.  The likely cause is a malformed email address.",
                                    sentContent=emailBody,
                                    ref2=0);
                    failedCount++;
                }

            }   
            emailSent = true;

        }


        //persist email object
        if (listFind(attributes.rc.email.action,'save')){
            email.setTstamp(attributes.prc.now);
            email.setSent(emailSent);
            email.setStatsSent(sentCount);
            email.save();
        }

    }//end thread   
4

1 に答える 1

3

1 つのアプローチは、負荷を均等に分散するために時間指定されたバッチで電子メールを生成することです。バッチ サイズとバッチ間の遅延は、環境に合わせて調整できます。

    thread name="sendBroadcastEmail" rc="#rc#" prc="#prc#" filters="#rc.filters#" email="#email#" emailSignature="#emailSignature#"{
    createObject( "java", "coldfusion.tagext.lang.SettingTag" ).setRequestTimeout(javaCast( "double", 3600 ));

            // set thread to a lowish prority
            var currentThread = CreateObject( "java","java.lang.Thread" ).currentThread();
            var priority = currentThread.getPriority();
            currentThread.setPriority( 3 );

        //get profiles that it will be sent to
        var sendToProfiles = profileService.getWithFilters(rc.filters);

        var mailService = getPlugin("MailService");
        var emailSent = false;
        var sentCount = 0;
        var failedCount = 0;

        //send the email (and log in profile events)
        if (listFind(attributes.rc.email.action,'send')){

            var emailsPerBatch = 1000; // divide into batches, set size here
            var batchcount = Ceiling( ArrayLen( sendToProfiles ) / emailsPerBatch ); // number of batches
            var batchdelay = 120000; // set delay between batches (ms)
            // initialise first batch
            var firstitem = 1;
            var lastitem = emailsPerBatch;

            for( var batch=1; batch<=batchcount; batch++ ) {
                if( batch > 1 ){
                    // delay sending next batch and give way to other threads
                    currentThread.yield();
                    currentThread.sleep( batchdelay );
                }

            for ( var i=firstitem; i<=lastitem;i++ ){
                var profile = sendToProfiles[i];

                            // generate emails ...

            }


            // initialise next batch
            firstitem = lastitem++;
            lastitem += emailsPerBatch;
            if( lastitem > ArrayLen( sendToProfiles ) ) {
                // last batch
                lastitem = ArrayLen( sendToProfiles );
            }

            }
            emailSent = true;
        }

            currentThread.setPriority( priority ); // reset thread priority


    }//end thread
于 2014-06-24T08:45:26.270 に答える