分散式交易問題排除經驗再一則與MSDTC快速ASPX測試法
3 |
以為自己MSDTC的處理經驗已夠豐富,不料今天又有新的心得,筆記之。
某台新裝測試主機,多支涉及分散式交易程式冒出「The transaction manager has disabled its support for remote/network transactions.」錯誤,老問題一枚,推測是忘了啟用Network DTC Access。檢查果真漏了啟動選項,啟動後,其中一個ASP.NET網站的分散式交易就正常,但另一個ASP.NET網站下的ASP(對,是ASP不是ASPX,滄海桑田屹立十餘年的阿公級ASP)卻依然噴出系統不支援分散式交易的錯誤訊息:
難道這台機器上只有ASPX才支援分散式交易,ASP不行?不合理!
為了簡化測試及重現問題,把以前寫過的DTC驗證測試改成ASPX程式碼內嵌版分別丟進兩個ASP.NET網站測試:(參考:小密技-在IIS主機現場撰寫測試ASPX偵錯)
<%@Page Language="C#"%>
<%@Import Namespace="System.Data" %>
<%@Import Namespace="System.Data.SqlClient" %>
<%@Import Namespace="System.Transactions" %>
<script runat="server">
private void querySqlServer()
{
string cnStr = "Data Source=server;User Id=user;Password=pwd;";
cnStr += "Application Name=" + Guid.NewGuid().ToString();
using (SqlConnection cn = new SqlConnection(cnStr))
{
SqlCommand cmd = new SqlCommand("SELECT getdate() as D", cn);
cn.Open();
SqlDataReader dr = cmd.ExecuteReader();
dr.Read();
Response.Write("<li>" + dr["D"] + "</li>");
cn.Close();
}
}
void Page_Load(object sender, EventArgs e)
{
using (TransactionScope tx=new TransactionScope())
{
Response.Write("<ul>");
querySqlServer();
querySqlServer();
Response.Write("<li>" + Transaction.Current.TransactionInformation.LocalIdentifier + "</li>");
Response.Write("<li>" + Transaction.Current.TransactionInformation.DistributedIdentifier + "</li>");
Response.Write("</ul>");
tx.Complete();
}
}
</script>
執行結果讓人意外,同一支DTCTest.aspx放進ASPX網站執行OK(看到兩組GUID值),丟到ASP所在網站就出現The transaction manager has disabled its support for remote/network transactions.錯誤。同一支程式在同一機器的兩個Web Application傳回不同結果十分吊詭。優先想到是Application Pool設定不同所致,而二者最大差異在於ASP網站被設成Classic模式,而ASP.NET用的則是Integrated,雖然不覺得是關鍵,但總得試試才知。
將ASP網站的AppPool改成Integrated,但因不相容網站壞掉無法測試,只能再改回Classic,無意間再跑一次DTCTest.aspx,發現分散式交易已正常~
事後推敲,應是Classic改Integrated的過程重啟了AppPool,分散式交易支援才生效,但為什麼ASPX網站不需要重啟就能生效仍待研究。總之,為此修訂設定MSDTC之SOP,納入「設定後要IISRESET」以避免類似狀況再次發生。
Comments
# by supershowwei
asp 環境的怪問題真的都讓人驚豔。
# by Gelis
我猜,會有這樣的差異是因為 IIS 的 Integrated AppPool 採用的是多行程隔離(Process Isolation) 方式啟動,而 Classes AppPool 採用的相容 IIS6.0以前的 ISAPI 來啟動 Handler,而這之間最大的差異在於,記憶體與狀態管理的模式不同,過去ISAPI和現有的大部分Win32 API一樣會自動配置緩衝區,這也是過去ISAPI容易發生錯誤的原因。IIS7.0新的 Integrated 整合模式的所有API則都由伺服器管理記憶體,所以不用重新啟動即可生效。
# by Jeffrey
to Gelis, 這個推測蠻合理的,感謝補充。