小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Web服務(wù)設(shè)計三種模式-學(xué)習(xí)筆記 - 山間小溪 - 博客園

 ShangShujie 2006-11-12

這篇文章在去年就看了,但當(dāng)時不是很理解;現(xiàn)在回頭看,有些體會。

實現(xiàn)SOA的一個重要途徑是使用Xml WebServices,相對一些“高山流水、曲高和寡”的理論和概念來說,對于俺們平庸之輩,它門檻低,可操作性強(qiáng)。

為了便于理解后邊的內(nèi)容,再次老話重提……SOA的四個基本原則:

1)邊界明確:Boundaries Are Explicit

2)服務(wù)自治:Services Are Autonomous

3)服務(wù)共享架構(gòu)和契約:Services Share Schemas & Contacts

4)基于策略來使服務(wù)兼容:Service Compatibilility Is Based Upon Policy.

也許因為翻譯非常抽象,可以仔細(xì)閱讀

原英文文章(建議翻譯的中文頁面就不要看了,越看越迷糊) WebCast教程

 

進(jìn)入正題。文檔處理器(Documoent Processor)、冪等消息(Idempotent Message)和預(yù)訂(Reservation)是在進(jìn)行web 服務(wù)設(shè)計時可參考的三個模式。



模式 1: Document Processor

核心:根據(jù)現(xiàn)有文檔和已知的業(yè)務(wù)事件來構(gòu)建業(yè)務(wù)處理模型。

注解:

1)在進(jìn)行web服務(wù)接口設(shè)計時,應(yīng)完全站在業(yè)務(wù)角度,而非設(shè)計角度;

2)所謂文檔,應(yīng)指的是反映在業(yè)務(wù)流程中不同異構(gòu)系統(tǒng)中用于交換和流通的數(shù)據(jù)資料;

3)所設(shè)計的服務(wù)接口應(yīng)該很好地封裝內(nèi)部實現(xiàn)的細(xì)節(jié);

4)以文檔為參照來定義或重用 XML 架構(gòu)以表示服務(wù)的請求和響應(yīng)消息;并直接從這些架構(gòu)生成對象,以加速開發(fā)。

5)所定義的服務(wù)必須為一個完整的過程,避免“CRUD”;

示例:

本示例設(shè)計:查詢某個國家的客戶。代碼下載

//不好的設(shè)計------返回DataSet類型,如果使用者不是.Net很難使用

 [WebMethod(Description="Find customers in the Customer table based on a specific country code This method returns a dataset - consider this an ANTI-Pattern for interoperable web services.")]

public NWCustomerDataSet FindCustomerByCountryReturnDataSet(string Country)

{

    try

    {

        CustomerService svc = new CustomerService();

        return svc.FindCustomerByCountryReturnDataSet(Country);             }

   

}

//好的設(shè)計-返回一個結(jié)構(gòu)化的文檔信息,簡單規(guī)范,任何使用者都很方便使用

[WebMethod(Description="Find customers in the Customer table based on a specific country code.\nThis method returns a structured \"document\" of customer information - a much cleaner approach than returning datasets.")]

public FindCustomerResponse FindCustomersByCountry(string Country)

{

    try

    {

        // Get the customer data

        CustomerService svc = new CustomerService();

        NWCustomerDataSet nwCustomers;

        nwCustomers = svc.FindCustomerByCountryReturnDataSet(Country);

        // At the service boundary, translate the data into a format

      // described by the schema

        FindCustomerResponse Customers = new FindCustomerResponse();

 

        // Copy the data into a data transfer object               

foreach (NWCustomerDataSet.CustomersRow custRow in nwCustomers.Customers)

        {

            // Generated wrapper class

            Customers.Add(CopyRowToDTO(custRow));      

        }

 

        return Customers;

    }

    catch (Exception ex)

    {

        System.Diagnostics.Trace.WriteLine(ex.Message);

        return null;

    }

}

 

//以下是FindCustomerResponse結(jié)構(gòu)化文檔:

<?xml version="1.0" encoding="utf-16"?>

<xs:schema xmlns="http://www./1.0.0.0/Customers.xsd" xmlns:b="http://schemas.microsoft.com/BizTalk/2003" elementFormDefault="qualified" targetNamespace="http://www./1.0.0.0/Customers.xsd" id="Customers" xmlns:xs="http://www./2001/XMLSchema">

 <xs:complexType name="NorthwindCustomer">

    <xs:sequence>

      <xs:element name="CustomerID" type="xs:string" />

      <xs:element name="CompanyName" type="xs:string" />

      <xs:element name="ContactName" type="xs:string" />

      <xs:element name="ContactTitle" type="xs:string" />

      <xs:element name="Address" type="xs:string" />

      <xs:element name="City" type="xs:string" />

      <xs:element name="Region" type="xs:string" />

      <xs:element name="PostalCode" type="xs:string" />

      <xs:element name="Country" type="xs:string" />

      <xs:element name="Phone" type="xs:string" />

      <xs:element name="Fax" type="xs:string" />

    </xs:sequence>

 </xs:complexType>

 <xs:complexType name="FindCustomerResponse">

    <xs:sequence>

      <xs:element name="Customer" type="NorthwindCustomer" minOccurs="0" maxOccurs="unbounded" />

    </xs:sequence>

 </xs:complexType>

 <xs:complexType name="FindCustomerByCountryRequest">

    <xs:sequence>

      <xs:element name="Country" type="xs:string" />

    </xs:sequence>

 </xs:complexType>

</xs:schema>

 

問題:

模式固然是好的,但要根據(jù)具體情況進(jìn)行取舍。因為:服務(wù)使用者必須將該結(jié)構(gòu)化的xml文檔映射回其內(nèi)部本身的數(shù)據(jù)架構(gòu),與此同時,效率必然也會大大降低。

 


   模式 2:Idempotent Message

核心:使用帶有公共契約的消息請求進(jìn)行通訊。

注解:

1)什么是冪等消息?

a)        一來一往,可靠的消息傳輸:可以理解為TCP,一來一往,保證消息是可靠的;不冪等呢,可以理解為UDP,發(fā)送過去,結(jié)果到底怎么樣就不知道了;

b)        使用者很有可能多次發(fā)送同一請求,比如在網(wǎng)上購物,用戶反復(fù)點擊結(jié)賬(不知道為什么);

2)如上圖所示,服務(wù)使用方在發(fā)送請求的時候,攜帶一個UOW-工作單元IDWeb服務(wù)接口根據(jù)該UOW來判斷請求的命令是否已經(jīng)執(zhí)行過;

3)關(guān)于UOW:可以把UOW設(shè)計為一個定制的SOAP headerURI,在這里面可以(如果需要)加上直接調(diào)用者及相關(guān)信息,這樣做是為了解決使用者使用同一UOW進(jìn)行多次請求的處理問題: URI協(xié)助服務(wù)方分析調(diào)用者的信息,以決定具體采用什么方式進(jìn)行回應(yīng)?

c)       如包含上次沒收到結(jié)果的信息,服務(wù)方就可以再次處理請求;

d)       如果是寫操作,且上次已經(jīng)成功返回,則服務(wù)端就可以拋出異常;

e)       如果是讀操作,則把對應(yīng)的緩存數(shù)據(jù)返回;

4)由上面幾條,我覺得結(jié)論是:這種模式比較復(fù)雜,并不好操作。因為本來使用復(fù)雜的消息頭或URI已經(jīng)額外增加了工作量;確定合理的緩存策略更是讓人頭疼,制定不好肯定會嚴(yán)重影響服務(wù)性能。

示例:

本示例設(shè)計: 代碼下載

/// <summary>

/// This method updates the number of Insureds covered with a relative value. Since each /// call to update query modifies the database value to a new value, the call to update

/// database should be made only if not done earlier. This is ensured by checking the RequestId

/// passed as first parameter. If the RequestId passed is different from the previously /// passed RequestId value, only than update database call is made.

/// Each RequestId is maintained in a list.

/// </summary>

/// <returns></returns>

public UpdatePolicyResponse UpdateInsuredsCovered(int requestId, int policyId, int insuredsCovered)

{

    UpdatePolicyResponse response = new UpdatePolicyResponse();

 

    response.RequestID = requestId.ToString();

    response.PolicyId = policyId.ToString();

    response.InsuredsCovered = insuredsCovered.ToString();

 

    //

    // The requestId should be a number greater than zero

    //

    if (requestId <= 0)

    {

        response.Result = ResultConts.INVALID_REQUEST_MSG;

        return response;

    }

 

    //

    // Make the update of the price as required

    //

    UpdatePolicy updateData = new UpdatePolicy();

    response.Result = updateData.UpdateInsuredsCovered(requestId, policyId, insuredsCovered);

    return response;

}      


 
模式 3:預(yù)訂

核心:使用預(yù)訂ID、狀態(tài)保存和過期策略,處理需要多次請求才能完成的業(yè)務(wù)流程。


注解:

1)針對的問題:復(fù)雜的、長時間的業(yè)務(wù)流程。如充值業(yè)務(wù),網(wǎng)上購物等。

2)在完成業(yè)務(wù)過程最后一個步驟之前;所有前邊的請求都被認(rèn)為“試探性操作”,即隨時有可能取消;因此前面所有的試探性操作的結(jié)果都會被跟蹤保存;

3)當(dāng)開始第一步試探性請求時,服務(wù)方會創(chuàng)建一個預(yù)訂的ID ,以后每次校驗該ID,如果不符,則交易取消;

4)服務(wù)端對每次試探性操作蓋上時間戳,超過時間沒有下一個操作,交易也會取消;

5)每一步試探性操作都是一來一回:使用者請求,服務(wù)端處理后發(fā)送確認(rèn)消息,當(dāng)使用者收到確認(rèn)消息以后才算該操作完成;

5)對于重復(fù)預(yù)訂請求,可以結(jié)合Idempotemt模式進(jìn)行處理;

示例:

本示例設(shè)計:代碼下載

// For a given Flight number, check travel date and number of seats.

// The service checks the availability of seats and returns the availability as ‘Y‘ or ‘N‘.

// If the the seats are available the service also returns a RequestID that can be used // to confirm the reservation. The RequestID is set to 0 if the seats are not available // for the requested flight. If the request is successfully processed the value of Result // element will be "Success" In case of invalid input or exceptional conditions an error // message is returned in the Result element of the response.

[WebMethod(BufferResponse=false,

         CacheDuration=60,

         Description="Check the availability of reservation in the specified flight. The Travel Date must be in mm/dd/yyyy format and Number of Seats must be greater than Zero. For testing purposes you can use Flight Numbers AI111 or AI112."

 )]

public ReservationStatusResponse CheckSeatAvailability( string FlightNumber,string TravelDate, string NumberofSeats )

{

    FBReservationService svc = new FBReservationService ();

    return svc.CheckReservationStatus(FlightNumber,TravelDate,NumberofSeats);

}

       

// This service checks the validity of the incoming RequstID. Valid RequestIDs will be

// confirmed. Return statuses are as follows:

//      Confirm - for Valid RequestIDs

//      Duplicate - for valid but not unexpired RequestIDs

//      Invalid Requst - for all other RequestIDs

//

// If the request is successfully processed the value of Result element is "Success"

// For invalid input or exceptional conditions an error message is returned in the Result // element.

[WebMethod(BufferResponse=false,

         CacheDuration=60,

         Description="Confirm the reservation for the provided Request Id. The Request Id must be greater than Zero. Use a RequestId that you previously received from the CheckSeatAvailability web service. If the Request Id does not exist a Failure message will be returned."

 )]

public ConfirmReservationResponse ConfirmReservationRequest( string RequestID )

{

    FBReservationService svc = new FBReservationService ();

    return svc.ConfirmReservationStatus(RequestID);

}

最后,引用一個名言:pattern is “an abstraction from a concrete form which keeps recurring in specific, non-arbitrary contexts." 所謂模式,只是在特定環(huán)境中過程的最佳實踐,并不是萬能的。況且,模式往往是抽象成了最簡單的,現(xiàn)實情況更復(fù)雜,所以,把它當(dāng)成戰(zhàn)略就行了。

 

在設(shè)計的時候,沒有最完美,只有最合適。不能被這些華麗的東西蒙住雙眼,Just Keep It Simple

 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約