Câu hỏi này là về cách làm thế nào để kiến trúc sư WCF dịch vụ để làm cho nó dễ dàng phát triển theo thời gian. Khó khăn để có được chiều sâu phản ứng với điều này mà không mô tả vấn đề.Kiến trúc WCF và Evolution, Phiên bản
nền
Tôi đang phát triển một hệ thống lớn của các dịch vụ WCF và khách hàng. Phía máy chủ là "dễ dàng" để cập nhật vì chỉ có 10 máy chủ được đề cập đang chạy mã này.
Khách hàng rất khó cập nhật, mặc dù mức độ tự động hóa cao, với hơn 300.000 khách hàng WCF, cập nhật là thứ luôn mất thời gian và chỉ đạt được tỷ lệ thành công cập nhật cao trong khoảng thời gian từ hai đến ba tuần .
Dữ liệu Hợp đồng
[DataContract]
public class MyContract
{
[DataMember]
public int Identity {get; set;}
[DataMember]
public string Name {get; set;}
// More members
}
Các DataContract
là khó khăn để khởi và có một MyContractFactory
lớp tiêu chuẩn để khởi được thể hiện thích hợp cho máy tính của bạn.
public class static MyContractFactory
{
public static MyContract GetMyContract()
{
// Complex implementation
}
}
ServiceContracts
Các DataContract
là rất phổ biến trên một loạt các dịch vụ web.
namespace MyPrefix.WebServicve1
{
[ServiceContract]
public class IMyInterface1
{
[OperationContract]
public void DoSomethingWithMyContract(MyContract data);
}
[ServiceContract]
public class IMyInterface2
{
[OperationContract]
public void DoSomethingDifferentWithMyContract(MyContract data);
}
}
Khách hàng
Khách hàng của tôi là có plugin dựa với các plugin chạy trong cả hai quá trình riêng biệt, lĩnh vực ứng dụng tùy thuộc vào mức độ tin tưởng chúng tôi có trong plugin.
thi hành 1.
thực hiện ban đầu của tôi về này (mặc định WCF) đã kết thúc với DataContract
trong một lắp ráp, ServiceContract
, và thực hiện trong lắp ráp riêng của mình.
Các khách hàng đã kết thúc với một rất xấu xí,
MyWebService1.MyContract
MyWebService2.MyContract
Với một sao chép và dán các MyContractFactory
trong gần như mọi plugin. Trong khi các DataContract
là như nhau, thực tế là các khách hàng không bao gồm các lắp ráp DataContract
có nghĩa là nó xuất hiện dưới không gian tên khác nhau như các đối tượng khác nhau.
Thực hiện 2
Các khách hàng hiện nay bao gồm lắp ráp DataContract
, ServiceContracts
đang ở trong một hội đồng riêng biệt để thực hiện dịch vụ, khách hàng có thể bao gồm một số các ServiceContract
hội nếu nó sẽ hỗ trợ với mã tái sử dụng (không có bản sao hơn và dán).
Câu hỏi
Với việc thực hiện thứ hai Tôi bây giờ phải đối mặt với khó khăn trong việc, làm thế nào để cập nhật DataContract
và ServiceContracts
của tôi?
Tôi có cập nhật cùng một phiên bản và tăng số phiên bản không? Làm thế nào để bảo toàn tính tương thích ngược trong khi tất cả các máy khách nâng cấp? Phá vỡ các khách hàng cho đến khi họ cập nhật là không thể chấp nhận được.
Tôi có tạo một hội đồng mới với một lớp mở rộng
MyDataContract
, phương pháp mới chấp nhận loại mới theo mộtServiceContract
mới? Điều đó có nghĩa là đối với mọi thay đổi nhỏ đối với hợp đồng của tôi, tôi cần một hội đồng mới? Làm thế nào tôi có thể ngăn không cho nó trở thành hàng trăm năm trong một vài năm?Một số giải pháp khác?
Bất kể các giải pháp mà tôi nghĩ qua, tất cả chúng đều có nhược điểm lớn.
Hiện không có vẻ được (ít nhất là với tôi) của,
- Bảo tồn tương thích ngược cho đến khi khách hàng cập nhật
- Giữ khách hàng cắt không có sưng lên như các phần mềm tiến hóa theo thời gian
- Không gây ô nhiễm đáng kể số
ServiceContract
của tôi (tình trạng quá tải củaOperationContract
cần một "tên" mới). Tôi đã có những thứ như dưới đây, và nó tấn công tôi một cơn ác mộng để duy trì theo thời gian.
Hợp đồng vận hành phức tạp
[OperationContract]
public void DoSomethingWithMyContract(MyContract data);
[OperationContract(Name = "DoSomethingWithMyDataByAdditionalData"]
public void DoSomethingWithMyContract(MyContract data, MyContract2 additionalData);
Tôi đang tìm kiếm một giải pháp mà đã làm việc trong một khoảng thời gian trong một môi trường quy mô lớn. Các bài viết trên blog và những nội dung tương tự rất được hoan nghênh.
Cập nhật 1
Nhìn qua những hạn chế của việc sử dụng "schemaless" thay đổi, không gian tên khác nhau có vẻ như phương pháp chắc chắn duy nhất. Tuy nhiên, nó không hoạt động như mong đợi, ví dụ:dưới đây
[ServiceContract(
Name = "IServiceContract",
Namespace = "http://myurl/2012/05")]
public interface IServiceContract1
{
// Some operations
}
[ServiceContract(
Name = "IServiceContract",
Namespace = "http://myurl/2012/06")]
public interface IServiceContract2
{
// Some different operations using new DataContracts
}
Với dịch vụ sau
public class MyService : IServiceContract1, IServiceContract2
{
// Implement both operations
}
và cấu hình sau
<service behaviorConfiguration="WcfServiceTests.ServiceBehavior"
name="Test.MyService">
<endpoint
address="2012/05"
binding="wsHttpBinding"
contract="Test.IServiceContract1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint
address="2012/06"
binding="wsHttpBinding"
contract="Test.IServiceContract2">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
Kết quả trong hai hợp đồng với hai tên gọi khác nhau, tôi mong rằng tôi có thể chỉ cho khách hàng của tôi đến,
http://myurl.com/MyService.svc/2012/05 cho phiên bản cũ và http://myurl.com/MyService.svc/2012/06
, nhưng có vẻ như nếu tôi muốn giữ tên ServiceContract, chúng phải là hai dịch vụ riêng biệt thay vì các địa chỉ điểm cuối riêng biệt cho cùng một dịch vụ?
Cập nhật 2
tôi đã kết thúc bằng cách sử dụng phương pháp tôi đã mô tả dưới cập nhật 1. Mặc dù WSDL có vẻ sai, nhưng dịch vụ này thực sự tương thích ngược với các máy khách cũ hơn khi tôi đã kiểm tra điều này.
@ marc-s một số câu trả lời tuyệt vời trong các liên kết này, cảm ơn! Vẫn đang tiêu hóa chúng –
@ marc-s có vẻ như bạn không thể giữ cùng một tên hợp đồng? –
@MAfifi: không - và bạn cũng không nên! Đó là một nguyên tắc cơ bản mà một giao diện giống như một hợp đồng dịch vụ là ** không thay đổi ** - nếu bạn cần phải thêm một cái gì đó vào nó, bạn cần phải cung cấp cho nó một cái tên mới. Và tất nhiên, bạn nên ** không bao giờ bao giờ ** phá vỡ giao diện hiện tại bằng cách thay đổi ví dụ: số hoặc kiểu dữ liệu của paramters ... –