Статьи

Службы данных WCF с Windows Phone — измерены требования к пропускной способности

В связи с тестированием синхронизации между базой данных SQL Server Compact в Windows Phone 8 и базой данных SQL Server (с помощью службы данных WCF, размещенной в IIS), я сделал несколько интересных наблюдений относительно требований к пропускной способности, которыми я хотел бы поделиться.

Я тестирую образец базы данных Chinook , загружая на устройство всю таблицу PlaylistTrack (8715 строк) через службу WCF Data Services. На стороне сервера я использую последнюю версию серверных компонентов WCF Data Services версии 5.3.0. Версия 5.1 или более поздняя включает более новый облегченный формат JSON (просто для сравнения я также включаю размеры для предыдущего формата JSON)

На стороне сервера я создал веб-приложение ASP.NET с сервисом данных WCF, которое предоставляет базу данных Chinook на моем SQL Server через Entity Framework DbContext. Сила служб данных WCF заключается в том, что для этого не требуется кода для настройки. Я настроил свой сервис следующим образом:

    public class SyncService : DataService<ChinookEntities>
    {
        // This method is called only once to initialize service-wide policies.
        public static void InitializeService(DataServiceConfiguration config)
        {
            config.UseVerboseErrors = true;
            //config.SetEntitySetAccessRule("TrackPurchases", EntitySetRights.WriteAppend);
            config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
        }
    }

Чтобы получить доступ к службе IIS Express из моего эмулятора Windows Phone 8, я следовал инструкциям здесь: http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj684580(v=vs.105) .aspx 

Чтобы измерить размер полезной нагрузки, я использую Fiddler2, следуя инструкциям здесь: http://blogs.msdn.com/b/fiddler/archive/2010/10/15/fiddler-and-the-windows-phone -emulator.aspx

Команда служб данных WCF также предоставляет клиента служб данных WCF для Windows Phone , который может использовать ссылку на службу, но у этого клиента есть некоторые серьезные ограничения, которые плохо влияют на потребление полосы пропускания: он поддерживает только формат ATOM на основе XML , но вы можете включить сжатие, как описано здесь: http://blogs.msdn.com/b/astoriateam/archive/2011/10/04/odata-compression-in-windows-phone-7-5-mango.aspx 

На стороне клиента я просто использую HttpWebRequest для вызова URL REST и включаю поддержку gzip через библиотеку ICSharpCode.SharpZipLib (например, http://nuget.org/packages/SharpZipLib-WP7/ ).

Вот реализация WebClient:

        static public async Task<T> GetData<T>(Uri uri, bool useJson = true, bool version3 = true, bool compress = true)
        {
                //uri = new Uri(uri.AbsoluteUri + "&format=json");
                HttpWebRequest client = WebRequest.CreateHttp(uri);
                {
                    if (compress)
                        client.Headers[HttpRequestHeader.AcceptEncoding] = "deflate, gzip";
                    if (version3)
                    {
                        client.Headers["MaxDataServiceVersion"] = "3.0";
                    }
                    else
                    {
                        client.Headers["MaxDataServiceVersion"] = "2.0";
                    }
                    if (useJson)
                        client.Accept = "application/json";
                    
                    using (WebResponse response = await client.GetResponseAsync())
                    {
                        string result = await response.GetResponseText();

                        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
                        T resultType;
                        using (MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(result)))
                        {
                            resultType = (T)serializer.ReadObject(stream);
                        }
                        return resultType;
                    }
                }
        }

        public static async Task<string> GetResponseText(this WebResponse response)
        {
            using (
            Stream stream = response.IsCompressed()
                                   ? new GZipInputStream(response.GetResponseStream())
                                   : response.GetResponseStream())
            {
                using (var reader = new StreamReader(stream))
                {
                    return await reader.ReadToEndAsync();
                }
            }
        }

        public static bool IsCompressed(this WebResponse response)
        {
            return Regex.IsMatch((response.Headers["Content-Encoding"] ?? "")
                                     .ToLower(), "(gzip|deflate)");
        }

(Я использую Microsoft.Threading.Tasks.Extensions.dll для реализации GetResponseAsync)

Я использую классы DataContext, сгенерированные моим SQL Server Compact Toolbox, для десериализации, с небольшим дополнением — я добавил этот атрибут во все свойства EntitySet <T> и EntityRef <T> (это будет включено в следующий выпуск Toolbox):

[Глобальный :: System.Runtime.Serialization.IgnoreDataMember]

Я звоню по следующему URL: http: // <MyIP>: 2065 / SyncService.svc / PlaylistTracks

Это мой тестовый код:

/ATOM-XML
await WebClient.GetData<PlaylistTrackRoot>(uri, false, false, false);
//Verbose json
await WebClient.GetData<PlaylistTrackRoot>(uri, true, false, false);
//Verbose json + gzip
await WebClient.GetData<PlaylistTrackRoot>(uri, true, false, true);
//Plain json
await WebClient.GetData<PlaylistTrackRoot>(uri, true, true, false);
//Plain json + gzip
await WebClient.GetData<PlaylistTrackRoot>(uri, true, true, true);

public class PlaylistTrackRoot { public List<PlaylistTrack> value { get; set; } }

И, наконец, невероятные цифры для загрузки всей таблицы PlaylistTrack с 8715 строками (помните, что ATOM — это формат клиента WCF Data Services по умолчанию)

Тип полезной нагрузки Размер тела (в байтах)
ATOM-XML 9.322.665 (100% — реализация клиента DS по умолчанию)
JSON (многословно) 5,016,977 (54%)
JSON (многословно) + gzip 328,410 (3,5%)
JSON (обычный) 790,845 (8,5%)
JSON (обычный) + gzip 43,023 (0,5%)

Поэтому, прежде чем вы решите использовать WCF Data Services (очень мощная технология), помните: огромная сила — большая ответственность.