Opracowujemy usługę WCF do przesyłania strumieniowego dużej ilości danych, dlatego zdecydowaliśmy się użyć funkcji WCF Streaming w połączeniu z serializacją protobuf-net.Lazy, serializacja obiektów sterowanych strumieniowo za pomocą protobuf-net
Kontekst:
Generalnie pomysł jest do serializacji obiektów w służbie, zapisać je do strumienia i wysłać. Po drugiej stronie wywołujący odbierze obiekt Stream i będzie mógł odczytać wszystkie dane.
Więc aktualnie usługa kod metoda wygląda nieco jak poniżej:
public Result TestMethod(Parameter parameter)
{
// Create response
var responseObject = new BusinessResponse { Value = "some very large data"};
// The resposne have to be serialized in advance to intermediate MemoryStream
var stream = new MemoryStream();
serializer.Serialize(stream, responseObject);
stream.Position = 0;
// ResultBody is a stream, Result is a MessageContract
return new Result {ResultBody = stream};
}
Przedmiotem BusinessResponse jest szeregowane do MemoryStream i który jest zwracany z metody. Po stronie klienta kod wywołujący wygląda tak:
var parameter = new Parameter();
// Call the service method
var methodResult = channel.TestMethod(parameter);
// protobuf-net deserializer reads from a stream received from a service.
// while reading is performed by protobuf-net,
// on the service side WCF is actually reading from a
// memory stream where serialized message is stored
var result = serializer.Deserialize<BusinessResponse>(methodResult.ResultBody);
return result;
Więc kiedy serializer.Deserialize()
nazywa się to czyta ze strumienia methodResult.ResultBody
, w tym samym czasie na WCF bocznej usługa czyta MemoryStream, który został zwrócony z a TestMethod
.
Problem:
Co chcielibyśmy osiągnąć to, aby pozbyć się z MemoryStream
i początkowej serializacji całego obiektu na stronie serwisu naraz. Ponieważ korzystamy z przesyłania strumieniowego, chcielibyśmy, aby przed wysłaniem uniknąć przechowywania w pamięci obiektu zserializowanego.
Pomysł:
Idealnym rozwiązaniem byłoby, aby zwrócić puste, wykonanego na przedmiot strumień (z TestMethod()
) w odniesieniu do przedmiotu, który ma być w odcinkach (Object „BusinessResponse”, w naszym przykładzie). Tak więc, gdy WCF wywołuje metodę Read()
mojego strumienia, wewnętrznie serializuję fragment obiektu za pomocą protobuf-net i zwracam go do wywołującego bez zapisywania go w pamięci.
A teraz jest problem, ponieważ to, czego potrzebujemy, to możliwość serializacji obiektu kawałek po kawałku w momencie odczytu strumienia. Rozumiem, że jest to zupełnie inny sposób serializacji - zamiast przesuwania obiektu do serializera chciałbym poprosić o seryjną treść po fragmencie.
Czy ten rodzaj serializacji jest w jakiś sposób możliwy przy użyciu protobuf-net?
Czy to jeden obiekt? Lub seria obiektów (kolekcja)? To, czy warto się na tym skupić, zależy w rzeczywistości od konfiguracji WCF - w większości konfiguracji zawsze buforuje całą wiadomość w pamięci * w każdym razie * - więc łatwo nie można niczego zmienić. –
Witaj Marc, WCF jest skonfigurowany tak, aby w ogóle nie używać buforowania - to jest punkt streamingu - chcę zmniejszyć ślad pamięci po stronie serwera. Dodatkowo, jeśli chciałbym serializować kolekcję obiektów, użyłbym 'SerializeWithLengthPrefix()' za każdym razem, gdy Klient wywołuje 'Read()' a mój bazowy bufor jest mniejszy niż żądana ilość danych. Problem polega na tym, że chciałbym móc podzielić serializację pojedynczych obiektów. –
ciekawe pytanie. Myślę, że * można to uogólnić, zasadniczo na fałszywy strumień, który sprawia, że praca z czytaniem i pisaniem jest rutynowa. Jeśli nie masz nic przeciwko dodatkowemu wątkowi, można to zrobić za pomocą prostej bramy, jednak Jon Jon miał kilka interesujących pomysłów. Będę musiał rzucić okiem i wrócić do ciebie. Mogę jednak bez wątpliwości powiedzieć, że nie zamierzam hakować rdzenia protobuf-net w tym celu :) –