1

Windows/IIS サーバーで ColdFusion 8 を使用して、何百もの PDF をバッチで生成する Web アプリケーションがあります。

プロセスは私の開発サーバーとステージング サーバーで正常に実行されますが、もちろんクライアントは安価で、私の開発/ステージング ボックスほど高速ではない共有ホスティングに対してのみ料金を支払っています。その結果、PDF 生成スレッドがタイムアウトします。

流れは次のようなものです。

  1. PDF を生成するためにページが実行されます。
  2. どの PDF を生成する必要があるかを判断するためにクエリが実行され、生成する必要がある各 PDF に対してアプリケーション スコープの UDF 呼び出しがループによって開始されます。
  3. その UDF は、指定されたアイテムの情報を検索し、PDF 生成用のスレッドを作成して、生成によってページの速度が低下するのを防ぎます。
  4. スレッドは、単に CFDocument を使用して PDF を作成し、ディスクに保存してから終了します。

スレッドは再結合せず、スレッドの終了を待っているものは何もありません。UDF 呼び出しを行うページは数ミリ秒で終了します。タイムアウトしているのはスレッド自体です。

UDF (およびスレッド作成) のコードは次のとおりです。

<cffunction name="genTearSheet" output="false" returntype="void">
    <cfargument name="partId" type="numeric" required="true"/>
    <!--- saveLocation can be a relative or absolute path --->
    <cfargument name="saveLocation" type="string" required="true"/>
    <cfargument name="overwrite" type="boolean" required="false" default="true" />
    <cfset var local = structNew() />

    <!--- fix save location if we need to --->
    <cfif left(arguments.saveLocation, 1) eq "/">
        <cfset arguments.saveLocation = expandPath(arguments.saveLocation) />
    </cfif>

    <!--- get part info --->
    <cfif structKeyExists(application, "partGateway")>
        <cfset local.part = application.partGateway
        .getByAttributesQuery(partId: arguments.partId)/>
    <cfelse>
        <cfset local.part = createObject("component","com.admin.partGateway")
        .init(application.dsn).getByAttributesQuery(partId: arguments.partId)/>
    </cfif>

    <!--- define file name to be saved --->
    <cfif right(arguments.saveLocation, 4) neq ".pdf">
        <cfif right(arguments.saveLocation, 1) neq "/">
            <cfset arguments.saveLocation = arguments.saveLocation & "/" />
        </cfif>
        <cfset arguments.saveLocation = arguments.saveLocation & 
        "ts_#application.udf.sanitizePartNum(local.part.PartNum)#.pdf"/>
    </cfif>

    <!--- generate the new PDF in a thread so that page processing can continue --->
    <cfthread name="thread-genTearSheet-partid-#arguments.partId#" action="run" 
    filename="#arguments.saveLocation#" part="#local.part#" 
    overwrite="#arguments.overwrite#">
        <cfsetting requestTimeOut=240 />
        <cftry>
        <cfoutput>
        <cfdocument format="PDF" marginbottom="0.75" 
        filename="#attributes.fileName#" overwrite="#attributes.overwrite#">
            <cfdocumentitem type="footer">
                <center>
                <font face="Tahoma" color="black" size="7pt">
                pdf footer text here
                </font>
                </center>
            </cfdocumentitem>
            pdf body here
        </cfdocument>
        </cfoutput>
        <cfcatch>
        <cfset application.udf.errorEmail(application.errorEmail,
        "Error in threaded PDF save", cfcatch)/>
        </cfcatch>
        </cftry>
    </cfthread>
</cffunction>

ご覧のとおり<cfsetting requestTimeout=240 />、スレッドの先頭に a を追加して、スレッドを長持ちさせようとしました...サイコロはありません。また、CFThread タグに timeout パラメータがあることを知って少し興奮しましたが、それがスレッドに参加するとき (action=join) にのみ適用されることに気付きました。

これは共有ホストであるため、ColdFusion Administrator でデフォルトのタイムアウトを変更することはできません。

これらのスレッドをより長く存続させる方法について誰かがアイデアを持っている場合は、本当に感謝しています.

4

4 に答える 4

3

サーバーでは全体で 90 秒のタイムアウトを使用しますが (CF アドミニストレーターで設定)、CFM ファイルのステートメントを使用して、必要に応じてその設定をオーバーライドします。また、サーバーに 30 秒以上続くすべてのリクエストをログに記録させるので、どのリクエストを最適化する必要があるか、および/または requesttimeout オーバーライドが必要かがわかります (ただし、タイムアウトになったリクエストは他の理由から明らかですが、あなたのリストがあると便利です) C:\ColdFusion8\logs\server.log の最も遅いトランザクション)。

たとえば、夜通しのタスクとして実行される CFM の上部に次のように表示されます。

<cfsetting enablecfoutputonly="Yes" showdebugoutput="No" requesttimeout="80000">

昨夜の実行では、完了するまでに 34,313 秒かかったことがわかります。もちろん、そのプロセスを改善する余地はありますが、オフィスが始まる数時間前に終了します。その requesttimeout パラメータが CFM ファイルで設定されていない場合、そのジョブは 90 秒のマークで確実にタイムアウトします。

その設定をオーバーライドするより長いタスクを実行する前に、要求タイムアウトをはるかに長くして開始し、失敗を監視して、物事を引き締めながらジョブを再実行する必要がありました。理想的には、適切なハードウェア、コード、および適切なデータベース構造があれば、引き続き CF 管理タイムアウトを CF8 の既定値である 30 秒まで引き下げます。残念ながら、私のデータベース構造とコードはまだそのレベルに達していません。

于 2009-02-23T23:25:43.037 に答える
2

cfadminにアクセスできない共有ホストでスレッドを長持ちさせる方法はないと思います。cf admin制限は、アクティブ化されたときに常にcfsetting requesttimeout値をオーバーライドすると思うので、あなたの手はその前にかなり結びついていると思います。

私のアドバイスは、戦略を現在のページ内のすべてのPDFの作成から、代わりに作成する必要のあるPDFごとに別のリクエストを起動するように変更することです。エレガントではないのにiframeを表示しないのが、最も簡単な解決策かもしれません。生成する必要のあるPDFごとに1つのiframeを出力するだけで、ホストによって設定された制限時間内に個々のPDFを生成する必要があるため、タイムアウトの問題が発生することはありません。

于 2008-12-31T02:22:49.323 に答える
1

これは、スレッドのタイムアウトを増やすという私の最初の質問に直接答えることはできませんが、PDFの生成時間を改善することで、プロセスを機能させる(タイムアウトを防ぐ)ことができました。

livedocsによると、ColdFusion 8は、画像ファイルが同じ物理マシン上にあり、HTTP要求を行うのではなく、ローカルファイルとして含める必要があることを示すlocalUrl属性をタグに追加しました。CFDocument

コードを次のように変更するCFDocumentと、プロセスが十分に高速に実行され、スレッドがタイムアウトしなくなりました。

<cfdocument format="PDF" marginbottom="0.75" 
filename="#attributes.fileName#" overwrite="#attributes.overwrite#" localUrl="yes">
    <cfdocumentitem type="footer">
        <center>
        <font face="Tahoma" color="black" size="7pt">
            pdf footer text here
        </font>
        </center>
    </cfdocumentitem>
    pdf body here
    <img src="images/foo/bar.gif"/>
</cfdocument>
于 2009-01-09T15:06:35.500 に答える
0

<cfdocument format="pdf">Hello world</cfdocument>誰かがこの投稿を見つけて、単純な pdf でさえ(ごくわずかなコンテンツ、画像なし) でさえレンダリングに数分かかるという問題を抱えている場合は、以下を確認してください。

Windows\system32\drivers\etc\hosts

サーバーファイルを開き、それ自体を指していることを確認してください

127.0.0.1 localhost

サーバーは正常に機能していましたが、CF 管理者のタイムアウトを 5 分 (?!?!?!) に設定するまで、突然 PDF がタイムアウトになりました。いくつかの更新 (おそらくネットワーク セキュリティ管理者/監視担当者が誰であるかはわかりません) により、上記のファイルが別のイントラネット IP と DNS サーバー名に変更されました。私はそれを元に戻し、PDFは通常の時間の応答でレンダリングを再開しました。

于 2017-01-10T23:07:11.987 に答える