2

特定のスクリプトを実行するとデッドロックが発生し、後続のすべてのリクエストが不安定になり、CPU の 99.9% を使用し、最終的にサーバーが効果的にクラッシュするという問題を解決しようとしています。

これは、リンボに置かれた (永遠に待機している) リクエストの 1 つのスタック トレースの例です。

Thread Stack Trace
Trace Time: 21:00:44.463 06-Jun-2012
Request ID: 6131
Script Name: http://www.example.com/allreviews.cfm
Started: 21:00:21.225 06-Jun-2012
Exec Time: 23238ms
Memory Used: (24%)230,667KB
Memory Free: 701,428KB
Thread ID: 0x191e (6430)
Thread Name: jrpp-494
Priority: 5
Hashcode: 1081611879
State: WAITING

"jrpp-494" prio=5 in Object.wait()

java.lang.Object.wait(Object.java:???)[Native Method]
- waiting on <0x9253305> (a coldfusion.util.AbstractCache$Lock)
java.lang.Object.wait(Object.java:485)
coldfusion.util.AbstractCache.fetch(AbstractCache.java:46)
coldfusion.util.SoftCache.get_statsOff(SoftCache.java:133)
coldfusion.util.SoftCache.get(SoftCache.java:81)
coldfusion.runtime.TemplateClassLoader.findClass(TemplateClassLoader.java:609)
coldfusion.runtime.RuntimeServiceImpl.getFile(RuntimeServiceImpl.java:785)
coldfusion.runtime.RuntimeServiceImpl.resolveTemplatePath(RuntimeServiceImpl.java:766)
coldfusion.tagext.lang.CustomTag.setName(CustomTag.java:21)
cfApplication2ecfm456206189._factor0(/srv/www/htdocs/www.example.com/www/Application.cfm:28)
cfApplication2ecfm456206189.runPage(/srv/www/htdocs/www.example.com/www/Application.cfm:1)
coldfusion.runtime.CfJspPage.invoke(CfJspPage.java:231)
coldfusion.tagext.lang.IncludeTag.doStartTag(IncludeTag.java:416)
coldfusion.filter.CfincludeFilter.invoke(CfincludeFilter.java:65)
coldfusion.filter.CfincludeFilter.include(CfincludeFilter.java:33)
coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:279)
coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:48)
coldfusion.filter.MonitoringFilter.invoke(MonitoringFilter.java:40)
coldfusion.filter.PathFilter.invoke(PathFilter.java:94)
coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:70)
coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28)
coldfusion.filter.BrowserFilter.invoke(BrowserFilter.java:38)
coldfusion.filter.NoCacheFilter.invoke(NoCacheFilter.java:46)
coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38)
coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22)
coldfusion.filter.CachingFilter.invoke(CachingFilter.java:62)
coldfusion.CfmServlet.service(CfmServlet.java:200)
coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:89)
jrun.servlet.FilterChain.doFilter(FilterChain.java:86)
com.intergral.fusionreactor.filter.FusionReactorCoreFilter.doHttpServletRequest(FusionReactorCoreFilter.java:503)
com.intergral.fusionreactor.filter.FusionReactorCoreFilter.doFusionRequest(FusionReactorCoreFilter.java:337)
com.intergral.fusionreactor.filter.FusionReactorCoreFilter.doFilter(FusionReactorCoreFilter.java:246)
com.intergral.fusionreactor.filter.FusionReactorFilter.doFilter(FusionReactorFilter.java:121)
jrun.servlet.FilterChain.doFilter(FilterChain.java:94)
coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:42)
coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:46)
jrun.servlet.FilterChain.doFilter(FilterChain.java:94)
jrun.servlet.FilterChain.service(FilterChain.java:101)
jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:106)
jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42)
jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:286)
jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:543)
jrun.servlet.jrpp.JRunProxyService.invokeRunnable(JRunProxyService.java:203)
jrunx.scheduler.ThreadPool$DownstreamMetrics.invokeRunnable(ThreadPool.java:320)
jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:428)
jrunx.scheduler.ThreadPool$UpstreamMetrics.invokeRunnable(ThreadPool.java:266)
jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)

興味があれば、上部にある「ロック スクリプト」と呼ばれる完全なスタック トレースと、それを待機している他のすべてのスタック トレースを確認できます。

この問題に初めて遭遇したとき、スタック トレースはありませんでした。私は、「 ColdFusion が CPU を使い果たしているときに、何を噛んでいる/窒息させているかを調べるにはどうすればよいですか? 」という質問を投稿しました。多くの有益な回答を受け取り、スタック トレースを調べたところ、このデッドロックの問題を何度も引き起こしているのは同じ 3 つのスクリプトであることがわかりました。

いずれの場合も、「ロック スクリプト」の一番上の行には次のように書かれています。

coldfusion.compiler.ClassReader.skipFully(ClassReader.java:79)

そして、他のすべてのリクエストはその背後に詰まっており、それぞれのスタック トレースに次の行があります。

- waiting on <0x9253305> (a coldfusion.util.AbstractCache$Lock)

私を悩ませていたのは、リクエストのタイムアウトが尊重されなかった理由です。これらのスクリプトは永久にハングアップし、死ぬことはありません。なんてことだろう?だから私は自分でやらなければなりませんでした。そのため、「ロック スクリプト」を強制終了すると、他のスクリプトは辺鄙な状態から解放されます。その時点で、リクエストのタイムアウトを下回っている場合は処理を終了し、それを超えている場合 (ほとんどの場合はそうです)、単にタイムアウトに進みます。しかし、それらは単独でタイムアウトすることはなく、アクティブなスレッドが使用され、スレッド キューがいっぱいになり、すべてが処理されるまで、要求が積み重なっていきます。

要求されるたびにこれらを手動で強制終了することは明らかに解決策ではありません。そのため、妻がいつも思い出させてくれるように、「デバッグ、デバッグ、デバッグ」してください。条件<cfabort>を使用してステップスルーしたところ、Application.cfm、header.cfm、そして<cfinclude>問題のスクリプトの . 問題のスクリプトの<cfabort> 内部(最上部であっても) を配置すると、中断せず、デッドロックの問題が発生します。インクルードの直前に配置すると、リクエストが中止され、デッドロックの問題が回避されます。奇妙です。

これら 2 つの場所の間にコードはありませんよね?インクルードの直前とインクルードのすぐ内側は機能的に同等であるはずですよね?明らかに何かがそこで起こっているので、おそらくそうではありません。

<cflock>タグは一切使用しておりません。発生しているロックは、テンプレート キャッシュ レベルで発生しているようです。admin で「Trusted Cache」、「Cache Template In Request」、または「Component Cache」オプションがオンになっているかどうかに関係なく、同じ動作が観察されます (オン/オフの任意の組み合わせで)。テンプレート キャッシュをクリアし、各コンポーネントキャッシュを複数回.CFサーバーを何度も再起動しました...すべて役に立ちませんでした.

トラブルシューティング中に、CF8 (8.0.1) のコンパイラ キャッシュ ロックに関する同様の問題と、それを修正するためのパッチを適用する手順について説明しているこの記事を読みました。しかし、それは CF9 ではないので、明らかに彼らのパッチを適用することはできません。

何をすべきか?他の誰かがこの問題に遭遇しましたか? ...解決策はありますか?

4

2 に答える 2

2

クラス ファイルが破損していて、再生成が必要な場合があることがわかりました。この問題が発生すると、前述のように、破損したクラス ファイルをロードしようとしてデッドロックが発生します。クラス ファイルを再生成する手順は次のように簡単です。

  1. ColdFusion Administrator > サーバー設定 > キャッシュに移動します。

  2. 次のオプションのチェックを外します。

    [ ] クラス ファイルを保存 する このオプションを選択すると、ColdFusion によって生成されたクラス ファイルが、サーバーの再起動後に再利用できるようにディスクに保存されます。アドビでは、実稼働システムでこれを推奨しています。開発中は、このオプションを選択しないことをお勧めします。

  3. [変更を送信] ボタンをクリックします。

  4. ColdFusion サーバーを再起動します。

  5. ColdFusion Administrator > サーバー設定 > キャッシュに移動します。

  6. 次のオプションをチェックします。

    [x] クラス ファイルを保存 する このオプションを選択すると、ColdFusion によって生成されたクラス ファイルがディスクに保存され、サーバーの再起動後に再利用されます。アドビでは、実稼働システムでこれを推奨しています。開発中は、このオプションを選択しないことをお勧めします。

  7. [変更を送信] ボタンをクリックします。

  8. そして、あなたの完了!問題は完全になくなり、すべてが元通りになります。;-)

クラスファイルが破損する理由と方法は? 知らない。おそらく、これは別の質問の主題になる可能性があります。私が知っているのは、これで問題が解決するということだけです。私は通常、自分の回答を信頼できるものとして受け入れることをためらっています。そのため、他の誰かがこの問題とその解決策についてより良い説明を持っている場合は、遠慮なく投稿してください。

于 2012-07-09T20:34:26.317 に答える
0

回避策として、「キャッシュされたテンプレートの最大数」を 0 に設定して、テンプレートのキャッシュを完全に無効にしてみてください。本番環境には理想的ではありませんが、クラッシュするよりはましかもしれません。

于 2012-07-02T01:42:34.980 に答える