Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (7.15 MB, 706 trang )
475
476
Chương 12: Dịch vụ Web XML và Remoting
M
icrosoft .NET Framework hỗ trợ hai mô hình lập trình phân tán cấp cao là
Remoting và dịch vụ Web XML. Mặc dù cả hai công nghệ này có nhiều điểm
tương đồng (ví dụ, cả hai cùng trừu tượng hóa lời gọi giữa các tiến trình hay giữa
các máy tính khác nhau thành lời gọi phương thức của các đối tượng ở xa), nhưng chúng cũng
có vài điểm khác nhau cơ bản.
Dịch vụ Web XML được xây dựng bằng các chuẩn xuyên-nền và dựa vào khái niệm XML
messaging. Dịch vụ Web XML được thực thi bởi bộ thực thi ASP.NET; nghĩa là chúng có được
các tính năng của ASP.NET như output-caching. Điều này cũng có nghĩa là dịch vụ Web XML
thuộc dạng phi trạng thái (stateless). Nói chung, dịch vụ Web XML thích hợp nhất khi bạn cần
xuyên biên nền (ví dụ, một Java-client gọi một dịch vụ Web ASP.NET) hay biên tin cậy (ví
dụ, trong các phiên giao dịch thương mại). Trong chương này, chúng ta sẽ bàn một số mục
liên quan đến dịch vụ Web XML sau:
Nâng cao tính linh hoạt của các lớp proxy bằng cách không viết mã cứng cho địa chỉ
của dịch vụ Web XML (mục 12.1).
Sử dụng kỹ thuật caching để nâng cao hiệu năng và khả năng phục vụ (tính quy mô)
của dịch vụ Web XML (mục 12.2 và 12.3).
Tạo phương thức giao dịch cho dịch vụ Web XML (mục 12.4).
Truyền thông tin xác thực cho một dịch vụ Web XML bằng proxy (mục 12.5).
Gọi bất đồng bộ một phương thức của dịch vụ Web XML (mục 12.6).
Remoting là một công nghệ đặc trưng của .NET dành cho các đối tượng phân tán và được xem
như là một hậu duệ của công nghệ DCOM. Công nghệ này lý tưởng cho các hệ thống inhouse4; trong đó, tất cả các ứng dụng đều được xây dựng trên nền .NET, chẳng hạn backbone
của một hệ thống xử lý hóa đơn. Remoting cho phép các chuẩn giao tiếp khác nhau, chẳng hạn
các thông điệp nhị phân nhỏ gọn và các kết nối TCP/IP hiệu quả hơn mà dịch vụ Web XML
không hỗ trợ. Ngoài ra, Remoting còn là công nghệ duy nhất hỗ trợ các đối tượng có trạng
thái, và giao tiếp hai chiều thông qua callback. Nó cũng là công nghệ duy nhất cho phép gởi
các đối tượng .NET tùy biến qua mạng. Trong chương này, chúng ta sẽ bàn một số mục liên
quan đến Remoting sau:
Tạo các đối tượng khả-truy-xuất-từ-xa; đăng ký và quản lý chúng trên IIS (mục 12.7,
12.8, và 12.9).
Phát sinh sự kiện trên các kênh truy xuất từ xa (mục 12.10).
Kiểm soát thời gian sống và phiên bản của các đối tượng khả-truy-xuất-từ-xa (mục
12.11 và 12.12).
Hiện thực các phương thức một chiều trong các đối tượng khả-truy-xuất-từ-xa (mục
12.13).
4
in-house system: Hệ thống công nghệ thông tin do phòng IT của một công ty xây dựng nên.
477
Chương 12: Dịch vụ Web XML và Remoting
1.
Chương này chỉ đưa ra một số kỹ thuật hữu dụng trong việc sử dụng dịch vụ
Web XML và Remoting. Để hiểu sâu hơn, bạn cần tham khảo các sách chuyên về
đề tài này.
Tránh viết mã cứng cho địa chỉ URL của dịch vụ Web XML
Bạn cần sử dụng một dịch vụ Web XML được đặt tại một địa chỉ URL mà địa chỉ
này có thể thay đổi sau khi bạn triển khai ứng dụng client.
Sử dụng địa chỉ URL động cho dịch vụ Web XML. Khi đó, địa chỉ động này được
lấy một cách tự động từ file cấu hình của ứng dụng client. Trong Microsoft
Visual Studio .NET, bạn có thể cấu hình địa chỉ URL động bằng cách thay đổi
tùy chọn URL Behavior của Web Reference. Bạn cũng có thể sử dụng công cụ
Web Services Description Language (Wsdl.exe) với đối số /appsettingurlkey.
Theo mặc định, khi bạn tạo một lớp proxy thì địa chỉ URL của dịch vụ Web XML là mã cứng
trong phương thức khởi dựng của lớp proxy này. Bạn có thể chép đè thiết lập này trong mã
lệnh bằng cách điều chỉnh thuộc tính Url của lớp proxy sau khi tạo một thể hiện của nó. Tuy
nhiên, có một tùy chọn khác: cấu hình cho lớp proxy sử dụng một địa chỉ URL động.
Trong Visual Studio .NET, bạn có thể thực hiện điều này bằng cách chọn Web Reference trong
cửa sổ Solution Explorer và thay đổi tùy chọn URL Behavior trong cửa sổ Properties (xem
hình 12.1).
Hình 12.1 Cấu hình địa chỉ URL cho dịch vụ Web XML
Sau khi bạn thay đổi như trên, địa chỉ URL của dịch vụ Web XML sẽ tự động được thêm vào
file cấu hình của ứng dụng client. File cấu hình này có tên là Web.config đối với các ứng dụng
Web, và [AppName].exe.config đối với các ứng dụng khác (lưu ý, nguồn xuất hiện trong môi
trường thiết kế chỉ là App.config, nhưng sau đó sẽ được Visual Studio .NET đổi tên một cách
tự động). Ví dụ dưới đây là thiết lập được sinh tự động trong file cấu hình:
478
Chương 12: Dịch vụ Web XML và Remoting
value="http://localhost/WebServices/MyService.asmx"/>
Bạn cũng có thể sử dụng địa chỉ URL động do công cụ Wsdl.exe sinh ra. Trong trường hợp
này, bạn sử dụng đối số /appsettingurlkey để cho biết tên của thiết lập cấu hình mà URL sẽ
được lưu trữ ở đó. Bạn phải tạo file cấu hình bằng tay.
wsdl /out:Proxy.cs http://localhost/WebServices/MyService.asmx?WSDL
/appsettingurlkey:MyService
Trong cả hai trường hợp, mã lệnh của lớp proxy sẽ được sửa đổi để đọc địa chỉ URL từ file
cấu hình. Nếu không tìm thấy giá trị cần thiết, nó sẽ mặc định sử dụng địa chỉ URL được sử
dụng trong quá trình phát triển ứng dụng. Cách tiếp cận này cho phép bạn đổi địa chỉ URL của
dịch vụ Web XML sau khi đã biên dịch và triển khai ứng dụng (chỉ cần thay đổi file cấu hình).
2.
Sử dụng kỹ thuật response-caching trong dịch vụ Web XML
Bạn muốn nâng cao hiệu năng của dịch vụ Web XML bằng cách lưu trữ giá trị
trả về của một phương thức web.
Sử dụng response-caching bằng cách thiết lập thuộc tính CacheDuration của đặc
tính System.Web.Services.WebMethod.
Trong ASP.NET, dịch vụ Web XML hỗ trợ response-caching giống hệt như các trang web
ASP.NET. Khi response-caching được kích hoạt, mã lệnh của bạn chỉ thực hiện một lần, và giá
trị trả về của phương thức web sẽ được lưu lại và được trả về trong các lần gọi tiếp theo. Đối
với Web Form, caching được thực hiện cho từng form. Đối với dịch vụ Web XML, caching
được kích hoạt và cấu hình riêng cho mỗi phương thức web.
Ví dụ, phương thức web dưới đây trả về giá trị ngày giờ hiện hành trên máy server. Thông tin
này được lưu lại trong một phút, nghĩa là các lời yêu cầu tiếp theo trong khoảng thời gian này
sẽ nhận lại thông tin đã được lưu trước đó.
Using System;
using System.Web.Services;
public class ResponseCaching {
[WebMethod(CacheDuration=60)]
479
Chương 12: Dịch vụ Web XML và Remoting
public string GetDate() {
return DateTime.Now.ToString();
}
}
Nếu phương thức web của bạn nhận nhiều đối số, ASP.NET sẽ sử dụng lại giá trị đã được lưu
chỉ khi các giá trị đối số cũng giống như thế. Nếu bạn có một phương thức nhận tầm giá trị
rộng thì caching trở nên không hiệu quả và đôi khi trở nên lãng phí, vì có quá nhiều thông tin
cần được lưu nhưng ít khi được sử dụng lại. Ví dụ, sử dụng caching trong một phương thức
web thực hiện phép tính dựa trên đầu vào dạng số không phải là một sự lựa chọn tốt. Trái lại,
sử dụng caching trong một phương thức web nhận giá trị ID của một nhóm nhỏ sản phẩm
chắc chắn là một sự lựa chọn tốt. Bao giờ cũng vậy, response-caching bỏ qua mã lệnh của
bạn, khiến nó trở nên không đủ tư cách nếu phương thức web của bạn cần thực hiện các hành
động khác (chẳng hạn ghi nhật ký), hay phương thức web của bạn phụ thuộc vào một số thông
tin khác ngoài các đối số được đưa vào (chẳng hạn thông tin xác thực của người dùng hay dữ
liệu trong phiên làm việc).
3.
Một hạn chế của response-caching là nó chỉ cho phép bạn sử dụng lại dữ liệu
trong phạm vi của một phương thức web. Nếu bạn muốn sử dụng lại dữ liệu
trong nhiều phương thức web khác nhau, kỹ thuật data-caching sẽ hiệu quả hơn.
Sử dụng kỹ thuật data-caching trong dịch vụ Web XML
Bạn cần chạy phương thức web của bạn nhưng vẫn sử dụng một số thông tin đã
được lưu. Hoặc, bạn muốn nâng cao hiệu năng của dịch vụ Web XML bằng cách
lưu trữ một số dữ liệu, và cần sử dụng lại dữ liệu này trong một số phương thức.
Bạn có thể lưu bất cứ đối tượng nào vào cache bằng phương thức Insert của đối
tượng System.Web.Caching.Cache. Bạn có thể truy xuất cache thông qua thuộc
tính tĩnh HttpContext.Current.
Cách thức làm việc của data-caching với một dịch vụ Web XML cũng giống như với một trang
web. Bạn có thể lưu trữ dữ liệu vào cache bằng mã trang web và lấy nó về trong một dịch vụ
Web XML, hay ngược lại. Để có thêm thông tin về data-caching và các kiểu chính sách hết
hiệu lực (expiration policy) mà nó hỗ trợ, bạn hãy tham khảo mục 7.15.
Điểm khác biệt duy nhất giữa caching trong một dịch vụ Web XML và caching trong một
trang web là: Trong dịch vụ Web XML, bạn không thể thu lấy đối tượng Cache như một thuộc
tính nội tại; thay vào đó, bạn cần truy xuất cache thông qua thuộc tính tĩnh
HttpContext.Current.
Ví dụ dưới đây trình bày một dịch vụ Web XML với hai phương thức web:
•
GetProductCatalog: Trả về một DataSet với các thông tin về sản phẩm. DataSet này có
thể được lấy từ cache hoặc được sinh tự động (nếu cần) bằng hàm GetCustomerDataSet.
•
GetProductList: Cũng sử dụng DataSet và hàm GetCustomerDataSet nhưng chỉ lấy một
phần thông tin (tên sản phẩm).
480
Chương 12: Dịch vụ Web XML và Remoting
Cả hai phương thức web trên đều có thể sử dụng chung dữ liệu đã được lưu, điều này làm
giảm nhẹ gánh nặng đặt lên cơ sở dữ liệu.
using System;
using System.Data;
using System.Data.SqlClient;
using System.Web.Services;
using System.Web;
public class DataCachingTest {
private static string connectionString = "Data Source=localhost;" +
"Initial Catalog=Northwind;user ID=sa";
[WebMethod()]
public DataSet GetProductCatalog() {
// Trả về DataSet (từ cache, nếu có thể).
return GetCustomerDataSet();
}
[WebMethod()]
public string[] GetProductList() {
// Truy xuất bảng khách hàng (từ cache, nếu có thể).
DataTable dt = GetCustomerDataSet().Tables[0];
// Tạo mảng chứa tên khách hàng
string[] names = new string[dt.Rows.Count];
// Đổ dữ liệu vào mảng.
int i = 0;
foreach (DataRow row in dt.Rows) {
names[i] = row["ProductName"].ToString();
i += 1;
}
481
Chương 12: Dịch vụ Web XML và Remoting
return names;
}
private DataSet GetCustomerDataSet() {
// Kiểm tra item đã có trong cache chưa.
DataSet ds = HttpContext.Current.Cache["Products"] as DataSet;
if (ds == null) {
string SQL = "SELECT * FROM Products";
// Tạo các đối tượng ADO.NET.
SqlConnection con = new SqlConnection(connectionString);
SqlCommand com = new SqlCommand(SQL, con);
SqlDataAdapter adapter = new SqlDataAdapter(com);
ds = new DataSet();
// Thực thi câu truy vấn.
try {
con.Open();
adapter.Fill(ds, "Products");
// Lưu item vào cache (trong 60 giây).
HttpContext.Current.Cache.Insert("Products", ds, null,
DateTime.Now.AddSeconds(60), TimeSpan.Zero);
} catch (Exception err) {
System.Diagnostics.Debug.WriteLine(err.ToString());
} finally {
con.Close();
}
}
return ds;
}
}
482
Chương 12: Dịch vụ Web XML và Remoting
Tạo phương thức web hỗ trợ giao dịch
4.
Bạn muốn thực thi tất cả các hành động của một phương thức web trong ngữ
cảnh của một phiên giao dịch COM+ sao cho chúng chỉ có hai khả năng: hoặc là
thành công hoặc là thất bại.
Kích hoạt một phiên giao dịch tự động bằng cách chọn một giá trị thuộc kiểu liệt
kê System.EnterpriseServices.TransactionOption và áp dụng nó cho thuộc tính
TransactionOption của đặc tính WebMethod.
Trong ASP.NET, dịch vụ Web XML hỗ trợ các phiên giao dịch tự động (có thể được kích hoạt
trên mỗi phương thức). Khi được kích hoạt, bất kỳ nguồn dữ liệu nào có hỗ trợ giao dịch
COM+ sẽ tự động được đưa vào phiên giao dịch hiện hành khi nó được sử dụng trong mã lệnh
của bạn. Phiên giao dịch sẽ tự động được commit khi phương thức web hoàn tất. Phiên giao
dịch này được roll-back khi có bất kỳ ngoại lệ chưa-được-thụ-lý nào xảy ra hoặc bạn gọi
phương thức SetAbort của lớp System.EnterpriseServices.ContextUtil.
Để kích hoạt việc hỗ trợ giao dịch cho một phương thức web, bạn cần thiết lập thuộc tính
TransactionOption của đặc tính WebMethod là RequiresNew. Ví dụ, phương thức web (hỗ trợ
giao dịch) dưới đây sẽ xóa các bản ghi trong một cơ sở dữ liệu và rồi hủy bỏ phiên giao dịch
này. Để sử dụng đoạn mã này, bạn phải thêm một tham chiếu đến
System.EnterpriseServices.dll.
using System;
using System.Data.SqlClient;
using System.Web.Services;
using System.EnterpriseServices;
public class TransactionTest {
private static string connectionString = "Data Source=localhost;" +
"Initial Catalog=Northwind;user ID=sa";
[WebMethod(TransactionOption=TransactionOption.RequiresNew)]
public void FailedTransaction() {
// Tạo kết nối.
SqlConnection con = new SqlConnection(connectionString);
// Tạo câu truy vấn SQL.
SqlCommand cmd = new SqlCommand("DELETE * FROM Customers", con);
483
Chương 12: Dịch vụ Web XML và Remoting
// Thực thi câu truy vấn. Tác vụ này sẽ tự động được
// đăng ký như một phần trong phiên giao dịch.
con.Open();
cmd.ExecuteNonQuery();
con.Close();
// Gọi một phương thức nào khác.
DoSomething();
// Nếu không có lỗi xảy ra, các thay đổi trong cơ sở dữ liệu
// sẽ được commit ở đây khi phương thức này kết thúc.
}
private void DoSomething() {
// Hủy bỏ phiên giao dịch.
ContextUtil.SetAbort();
}
Bạn có thể sử dụng tiện ích Component Service (trong phần Administrative Tools của Control
Panel) để theo dõi phiên giao dịch trên. Trong tiện ích này, bạn hãy chọn mục Distributed
Transaction Coordinator của máy tính hiện hành, và xem Transaction Statistics. Hình 12.2
cho thấy một phiên giao dịch không thành công khi chạy đoạn mã trên.
484
Chương 12: Dịch vụ Web XML và Remoting
Hình 12.2 Theo dõi một phiên giao dịch không thành công
[
Vì bản chất phi trạng thái (stateless) của giao thức HTTP, nên một phương thức web chỉ có
thể góp phần làm gốc của một phiên giao dịch; nghĩa là bạn không thể đưa nhiều hơn một
phương thức web vào cùng một phiên giao dịch. Mặc dù thuộc tính TransactionOption chấp
nhận tất cả các giá trị TransactionOption chuẩn, nhưng các giá trị này không mang ý nghĩa
như mong đợi. Ví dụ, Disabled, NotSupported, và Supported đều có cùng tác dụng là vô hiệu
việc hỗ trợ giao dịch. Tương tự, cả Required và RequiresNew đều kích hoạt việc hỗ trợ giao
dịch và khởi chạy một phiên giao dịch mới. Bạn nên sử dụng RequiresNew trong các phương
thức web vì tên của nó tương xứng với hành vi thật sự (!).
Các giao dịch COM+ làm việc một cách trong suốt với hầu hết các nguồn dữ liệu
vì chúng cung cấp các bộ quản lý tài nguyên tương thích. Nhưng luôn nhớ rằng,
nếu bạn tương tác với một tài nguyên không hỗ trợ giao dịch, mã lệnh sẽ không
được roll-back. Một số hoạt động không phải là giao dịch: ghi file, đặt thông tin
vào trạng thái phiên làm việc, và truy xuất một thiết bị phần cứng (như máy in).
Mặt khác, các thao tác dữ liệu với hầu hết các hệ cơ sở dữ liệu Enterprise (bao
gồm Microsoft SQL Server và Oracle) đều là tương thích COM+.
485
Chương 12: Dịch vụ Web XML và Remoting
Thiết lập thông tin xác thực cho dịch vụ Web XML
5.
Bạn muốn gửi các thông tin đăng nhập từ client của dịch vụ Web XML đến IIS
authentication.
Sử dụng thuộc tính Credentials của lớp proxy. Bạn có thể tạo một đối tượng
NetworkCredential mới chứa username và password; hoặc sử dụng
CredentialCache để lấy các thông tin xác thực của người dùng hiện hành.
Cũng giống như trang web, dịch vụ Web XML có thể được sử dụng cùng với IIS
authentication. Những gì bạn cần làm là đặt dịch vụ Web XML vào một thư mục ảo hạn chế
việc truy xuất nặc danh. Tuy nhiên, nếu người dùng có thể cung cấp các thông tin ánh xạ đến
một tài khoản người dùng hợp lệ, người dùng này sẽ được xác thực và bạn có thể lấy các
thông tin xác thực này thông qua đối tượng WebService.User.
Khác với trang web, dịch vụ Web XML không có sẵn phương thức nào để thu lấy thông tin xác
thực từ client vì dịch vụ Web XML được thực thi bởi các ứng dụng khác, chứ không phải bởi
người dùng. Do đó, ứng dụng đang tương tác với dịch vụ Web XML sẽ chịu trách nhiệm nhập
bất kỳ thông tin xác thực cần thiết nào.
Ví dụ sau mô phỏng một dịch vụ Web XML có thực hiện xác thực người dùng. GetIISUser trả
về người dùng đã được IIS xác thực. Nếu truy xuất nặc danh được phép thì kết quả sẽ là một
chuỗi rỗng. Nếu truy xuất nặc danh bị từ chối thì kết quả sẽ là một chuỗi có dạng
[DomainName]\[UserName] hay [ComputerName]\[UserName].
public class AuthenticationTest : System.Web.Services.WebService {
// Lấy thông tin về người dùng đã được IIS xác thực.
[WebMethod()]
public string GetIISUser() {
return User.Identity.Name;
}
}
Bước cuối cùng là tạo một client có thể cung cấp các thông tin xác thực. Các thông tin này
được nhập thông qua thuộc tính Credentials của đối tượng proxy (thiết lập thuộc tính này
tương tự như thiết lập thuộc tính WebRequest.Credentials khi lấy về một trang web—tham
khảo mục 11.3). Đoạn mã dưới đây trình bày cách truy xuất một dịch vụ Web XML sử dụng
Basic authentication (xác thực cơ bản):
// Tạo proxy.
localhost.AuthenticationTest proxy = new localhost.AuthenticationTest();
// Tạo thông tin xác thực.
proxy.Credentials = new System.Net.NetworkCredential(
"myUserName", "myPassword");