2009-08-15 4 views
16

Mam aplikację klient-serwer, która komunikuje się za pomocą WCF i używa NetDataContractSerializer do serializacji wykresu obiektów.Serializuj wiadomość WCF w sposób binarny, a nie jako komunikat SOAP.

Ponieważ wiele danych jest przesyłanych między serwerem a klientem, próbowałem zmniejszyć jego rozmiar, dostosowując rozmiar elementów danych (np. Zmieniono int na krótki, long na int itp.).

Po zakończeniu strojenia dowiedziałem się, że ilość przesłanych danych nie zmieniła się!
Problem polega na tym, że NetDataContractSerializer serializuje wykresy obiektów do formatu XML, więc niezależnie od wielkości elementu danych ważna jest tylko wielkość jego wartości. Na przykład wartość 10023 elementu danych Int16 będzie serializowana jako ciąg "10023" (0x3130303233), zamiast tylko 10023 (0x2727).

Pamiętam, że w Remotingu mogłem użyć BinaryFormatter, który serializował wartości zgodnie z typem elementu danych, ale nie wiem, czy można go używać z WCF.

Czy ktoś ma rozwiązanie?

Odpowiedz

35

WCF używa komunikatów SOAP, ale jakiego rodzaju kodowanie wiadomości jest całkowicie zależne od Ciebie.

Zasadniczo, po wyjęciu z pudełka, masz dwa: kodowanie tekstu (reprezentacja tekstowa wiadomości XML) lub kodowanie binarne. Możesz napisać własne kodowanie wiadomości, jeśli naprawdę musisz i musisz.

Po wyjęciu z pudełka wiązania BasicHttp i wsHttp używają kodowania tekstu - ale możesz to zmienić, jeśli chcesz. Powiązanie netTcp (które jest oczywistym wyborem za firewallami korporacyjnymi) będzie domyślnie używać binarnego.

Można również zdefiniować (tylko w config) swój własny protokół "http binarny", jeśli chcesz:

<bindings> 
     <customBinding> 
     <binding name="BinaryHttpBinding"> 
      <binaryMessageEncoding /> 
      <httpTransport /> 
     </binding> 
     </customBinding> 
    </bindings> 

a następnie używać go w swojej służby i po stronie klienta config:

<services> 
     <service name="YourService"> 
     <endpoint 
      address="http://localhost:8888/YourService/" 
      binding="customBinding" 
      bindingConfiguration="BinaryHttpBinding" 
      contract="IYourService" 
      name="YourService" /> 
     </service> 
    </services> 

Teraz masz protokół transportu oparty na protokole http, który zakoduje wiadomość w kompaktowym formacie binarnym, abyś mógł z niej korzystać!

Nie potrzeba żadnych dodatkowych kodowania lub niechlujnych hacków lub mnóstwa ręcznego kodu serializacji XML - wystarczy go podłączyć i używać! Ach, radość z elastyczności WCF!

+0

Więc czy kodowanie binarne wiadomość oferują znaczną poprawę wydajności? Czy czas serializacji jest skrócony, czy tylko zmniejsza się rozmiar wiadomości? –

+0

Użyłem tego niestandardowego powiązania, jak również binaryMessageEncoding z nazwanym transportem rur, a wiadomości nadal są kodowane XML zgodnie z dziennikami komunikatów w detektorze śledzenia, a także w kliencie testowym WCF. Nie jestem w 100% pewny, że nie wykonują one własnej serializacji XML obiektów, aby je rejestrować, zamiast przyjmować surową wiadomość. WCF utrudnia dołączenie do surowego żądania/odpowiedzi w stosunku do WebAPI, co ułatwia. – AaronLS

+0

Ta odpowiedź jest przydatna, ale należy pamiętać, że kodowanie binarne zmienia tylko sposób, w jaki wiadomość jest wysyłana "na drucie", tj. Po serializacji. Chociaż z pewnością zmniejsza to rozmiar danych, nie zmienia metody serializacji. Kodowanie binarne może być używane z kompresją w celu uzyskania lepszych wyników. –

6

Pierwsza myśl; czy włączyłeś kompresję transportu?

Jak złożone są dane? Jeśli jest to coś, co działałoby ze standardowym DataContractSerializer (tj. Prostym drzewem obiektów), wówczas może być użyteczny protobuf-net. Jest to bardzo skuteczny binarnym serializacji biblioteki ze wsparciem dla WCF poprzez dodatkowych atrybutów w umowie o świadczenie usług - na przykład:

[ServiceContract] 
public interface IFoo 
{ 
    [OperationContract, ProtoBehavior] 
    Test3 Bar(Test1 value); 
} 

([ProtoBehaviour] jest co zamienia się w inną serializatora dla tej metody)

Jednakże:

  • musi być w stanie zidentyfikować znacznik liczbowy dla każdej nieruchomości - za pośrednictwem dodatkowych atrybutów, lub można go użyć Order w atrybucie [DataMember(Order = x)]
  • dziedziczenia (jeśli używasz go) wymaga dodatkowych atrybutów
  • działa najlepiej, jeśli używasz udostępnianie montażową („mex” nie kocham go ...)

Ładnie, ale również współpracuje z MTOM, zmniejszając koszt bazowy 64 dla większych wiadomości.

1

Enkoder binarny NIE serializuje obiektu w systemie binarnym, ponieważ nie ma on nic wspólnego z serializacją! Jest to coś, co działa na niższej warstwie i decyduje o sposobie przesyłania komunikatu między serwerem a klientem.

Innymi słowy, obiekt zostanie najpierw przekształcony do postaci szeregowej (na przykład przez DataContractSerializer), a następnie zakodowany (przez BinaryEncoder). Zatem obiekt będzie zawsze w formacie XML, o ile zaangażowany jest obiekt DataContractSerializer.

Jeśli chcesz bardziej kompaktowy danych i lepszą wydajność, czytać tego bloga:

https://blogs.msdn.microsoft.com/dmetzgar/2011/03/29/protocol-buffers-and-wcf/

1

Oto przykład jak zrobić niestandardowe kodowanie tutaj https://www.codeproject.com/Articles/434665/WCF-Serialization-A-Case-Study

Warto zauważyć, że to, co faktycznie zostanie wysłana jest taka sama, jak gdybyś miał metodę wysyłania bajtu [] z domyślnym kodowaniem. Wiadomość przechodząca przez przewód nadal używa koperty XML SOAP niezależnie od tego, jak skonfigurować serializację.

Wygląda to tak:

POST http://127.0.0.1:12345/forSwerGup182948/Client HTTP/1.1 
Content-Type: text/xml; charset=utf-8 
VsDebuggerCausalityData: uIDPo+WkoDpet/JOtGlW+EHdpDQAAAAAvFs5XOJ0tEW0wTvNVRDUIiabR6u+p+JNnd5Z+SWl1NcACQAA 
SOAPAction: "http://tempuri.org/ITransmissionService/SendData" 
Host: 127.0.0.1:12345 
Expect: 100-continue 
Accept-Encoding: gzip, deflate 
Content-Length: 2890 

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><SendData xmlns="http://tempuri.org/"><message>eyI8Q2FsbGJhY2tJZD5rX19CYWNraW5nRmllbGQiOiJlYTQ3ZWIzMS1iYjIzLTRkODItODljNS1hNTZmNjdiYmQ4MTQiLCI8RnJvbT5rX19CYWNraW5nRmllbGQiOnsiPENoYW5uZWxOYW1lPmtfX0JhY2tpbmdGaWVsZCI6Ikdyb3VwMSIsIjxOYW1lPmtfX0==</message></SendData></s:Body></s:Envelope> 
Powiązane problemy