2012-05-29 42 views
5

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 DataContractServiceContracts của tôi?

  1. 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.

  2. 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ột ServiceContract 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?

  3. 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ủa OperationContract 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.

Trả lời

5

Cả Microsoft và hầu hết các WCF đáng kính trọng đều có thể nói cùng một điều: phiên bản phải được xử lý bằng cách sử dụng hợp đồng các không gian tên.

tôi không có nghĩa là không gian tên NET của hội đồng của bạn - Ý tôi là các dịch vụ WCF thực tế (và hợp đồng dữ liệu) không gian tên - vì vậy bạn nên có:

[ServiceContract(Namespace="http://services.yourcompany.com/Service1/V01"] 

hoặc một cái gì đó tương tự - một số người như tới phiên bản theo năm/tháng:

[ServiceContract(Namespace="http://services.yourcompany.com/Service1/2012/05"] 

Điều này cho phép bạn có nhiều phiên bản cũ hơn (được chỉ định bởi vùng tên dịch vụ), họ sẽ nhận được phiên bản cũ (miễn là bạn vẫn phơi bày điều đó).

Xem:

+0

@ 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 –

+0

@ marc-s có vẻ như bạn không thể giữ cùng một tên hợp đồng? –

+1

@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 ... –