`

创建高性能的WCF服务

阅读更多

I had a WCF service where I wanted to be able to support over a hundred concurrent users, and while most of the service methods had small payloads which returned quickly, the startup sequence needed to pull down 200,000 records. The out of the box WCF service had no ability to support this scenario, but with some effort I was able to squeeze orders of magnitude performance increases out of the service and hit the performance goal.

Initially performance was abysmal and there was talk of ditching WCF entirely ( and as the one pushing WCF technology on the project this didn't seem like a career enhancing change )

Here's how performance was optimized. These are listed in the order they were implemented. Some are fairly obvious, others took some time to discover. Each item represents, a significant increase in latency or scalability from the prior - and although I have internal measurement numbers, I'm not comfortable publishing them as the size of the data increased, and the testing approach changed.

  1. Use NetTCP binding
    This helps both throughput and the time it takes to open and close connections
  2. Use DataContract Serializer instead of XMLSerializer
    I started out using DataTables - POCO objects via Linq2Sql yielded a 6x increase
    slow: [OperationContract] MyDataTable GetData(...);
    fast: [OperationContract] IEnumerable<MyData> GetData(...);
  3. Unthrottle your service
    It's quite understanable that WCF is resistant to Denial of Service attacks out of the box, but it's too bad that it's is such a manual operation to hit the "turbo button". It would be nice if the Visual Studio tooling did this for you, or at least had some guidance (MS - hint, hint)

    The items to look at here are:
    1. <serviceBehaviors><serviceThrottling ...> set the max values high
    2. <dataContractSerializer maxItemsInObjectGraph="2147483647" />
    3. and under <netTcpBinding> setting the listenBacklog, maxConnections, and maxBuffer* value high
  4. Cache your data
    WCF, unlike ASP.Net has no built in facility to cache service responses, so you need to do it by hand. Any cache class will do.
  5. Normalize/compress your data
    this doesn't necessarily have to be done in the database, the Linq GroupBy operators make this easy to do in code. To clarify, say your data is kept in a denormalized table
    string Key1
    string Key2
    string Key3
    int val1
    int val2

    the bulk of the result set ends up being duplicate data
    LongKeyVal1 LongKeyVal2 LongKeyVal3 10 12
    LongKeyVal1 LongKeyVal2 LongKeyVal3 11 122
    LongKeyVal1 LongKeyVal2 LongKeyVal3 12 212
    so normalize this into
    LongKeyVal1 LongKeyVal2 LongKeyVal3
    10 12
    11 122
    12 212

    In code, given the following classes

    public class MyDataDenormalized
    {
    public string Key1 { get; set; }
    public string Key2 { get; set; }
    public string Key3 { get; set; }
    public int Val1 { get; set; }
    public int Val2 { get; set; }
    }
    public class MyDataGroup
    {
    public string Key1 { get; set; }
    public string Key2 { get; set; }
    public string Key3 { get; set; }
    public MyDataItem[] Values { get; set; }
    }
    public class MyDataItem
    {
    public int Val1 { get; set; }
    public int Val2 { get; set; }
    }

    you can transform an IEnumerable<MyDataDenormalized> into a IEnumerable<MyDataGroup> via the following

    var keyed = from sourceItem in source
    group sourceItem by new
    {
    sourceItem.Key1,
    sourceItem.Key2,
    sourceItem.Key3,
    } into g
    select g;
    var groupedList = from kItems in keyed
    let newValues = (from sourceItem in kItems select new MyDataItem() { Val1 = sourceItem.Val1, Val2= sourceItem.Val2 }).ToArray()
    select new MyDataGroup()
    {
    Key1 = kItems.Key.Key1,
    Key2 = kItems.Key.Key2,
    Key3 = kItems.Key.Key3,
    Values = newValues,
    };
  6. Use the BinaryFormatter, and cache your serializations
    If you're willing to forgo over the wire type safety, the binary formatter is the way to go for scalability. Data caching has only a limited impact if a significant amount of CPU time is spent serializing it - which is exactly what happens with the DataContract serializer.

    The operation contract changes to
  7. [OperationContract]
    Byte[] GetData(...);

    and the implementation to

    var bf = new BinaryFormatter();
    using (var ms = new MemoryStream())
    {
    bf.Serialize(ms, groupeList);
    // and best to cache it too
    return ms.GetBuffer();
    }

Before items 4,5, and 6 the service would max out at about 50 clients ( response time to go way up and CPU usage would hit 80% - on a 8 core box). After these changes were made, the service could handle of 100 + clients and CPU usage flattened out at 30%

Update: Shay Jacoby has reasonably suggested I show some code.

Update2: Brett asks about relative impact. Here's a summary

item latency scalability
2) DataContract Serializer large large
3) unthrottle small large
4) cache data small
5) normalize data medium
6) cache serialization small large
分享到:
评论

相关推荐

    如何创建高效WCF服务

    在本文中,我们将深入探讨如何创建高效的WCF服务,并讨论从基本的创建方法到利用类库进行优化的各种策略。 **一、理解WCF基础** 在开始创建WCF服务之前,了解其核心概念至关重要。WCF服务由以下四个主要元素组成:...

    如何在azure中创建和寄宿wcf服务

    在Azure中寄宿WCF服务,不仅可以利用云平台的弹性伸缩能力,还能享受到高可用性和易于管理的优势。同时,Azure的其他服务,如Azure SQL Database、Azure Blob Storage等,可以与WCF服务无缝集成,构建更复杂的云应用...

    WCFService可以通过web调用和WCF服务访问

    - **客户端配置**:对于Web调用,Java客户端可以使用JAX-WS或Apache CXF等库来创建代理类,调用WCF服务。对于C#客户端,可以使用`svcutil.exe`工具生成服务代理代码,然后在C#代码中实例化并调用服务。 - **安全性...

    WCF服务编程+源代码

    通过对“Programming WCF Services”源代码的分析和实践,你将能够掌握WCF的核心概念,并有能力创建自己的WCF服务。同时,这也将帮助你理解如何与其他系统进行互操作,以及如何解决在分布式环境中可能出现的问题。

    设计高性能的WCF解决方案 经典中的经典

    最后,遵循最佳实践,如使用适当的安全配置、最小化服务契约和数据契约,以及监控和调整服务行为,都是实现高性能WCF服务的关键步骤。 总的来说,设计高性能的WCF解决方案需要全面考虑传输层、序列化、编码器的选择...

    C# 调用WCF服务例程

    服务端是实现WCF服务的地方,它使用`ClassLibrary1`中的服务合同来创建具体的实现。在`winServer2`项目中,你需要创建一个类(如`Service1`)并实现`IService1`接口。此外,还需要配置服务的终结点(Endpoint),这...

    C#POST请求WCF服务

    要实现C#中的POST请求,你需要创建一个客户端代理类来代表WCF服务。这可以通过使用`svcutil.exe`工具或者在Visual Studio中添加服务引用来完成。生成的代理类会包含方法,这些方法可以直接调用来调用服务的操作。 1...

    WCF服务与客户端的调用

    本教程将深入探讨WCF服务的创建以及客户端如何调用这些服务。 ### 创建WCF服务端 1. **服务契约(Service Contract)**:定义服务提供的操作或方法。这是通过接口来实现的,标记为`[ServiceContract]`。例如: ```...

    WCF服务编程 中文版

    通过学习这些内容,开发者可以掌握创建和管理高效、安全的WCF服务的能力,能够构建符合企业级标准的分布式系统。此外,对于理解SOA(面向服务架构)和微服务架构也有着重要的理论支撑作用。在实际开发中,掌握WCF...

    高性能的WCF解决方案

    **高性能的WCF解决方案** Windows Communication Foundation (WCF) 是微软提供的一种面向服务的通信框架,用于构建可互操作的、安全的、可靠的企业级应用程序。在本文中,我们将深入探讨如何优化WCF服务,以实现更...

    WCF服务宿主及其跨域问题解决实例

    1. **创建WCF服务**:首先创建一个WCF服务,定义接口和实现,并在服务端配置跨域策略文件的路径。 2. **宿主服务**:将服务宿主在Windows服务中,确保服务运行时可正确加载跨域策略文件。 3. **创建Silverlight...

    C#编写的WCF服务项目

    本项目提供了一个使用C#编写的WCF服务示例,适用于Visual Studio 2008及更高版本,便于理解和学习。 1. **WCF服务基础** - WCF是微软提出的一种统一的编程模型,它集成了.NET Framework中的Web服务(ASMX)、...

    wcf服务编程 源码

    WCF(Windows Communication Foundation)是微软.NET框架下的一种面向服务的通信框架,它为构建、配置和部署可互操作的、安全的、可靠的、高性能的服务提供了全面的支持。本压缩包中的源码着重展示了WCF服务的编程...

    VS2010中使用Jquery调用Wcf服务源码

    在本文中,我们将深入探讨如何在Visual Studio 2010 (VS2010) 中使用jQuery调用WCF(Windows Communication Foundation)服务。...通过学习和实践这些内容,开发者能够提高其在构建高性能、可扩展的Web应用方面的技能。

    WCF服务编程

    ### WCF服务编程知识点详解 #### 一、WCF基础概览 **WCF(Windows Communication Foundation)** 是微软提供的一套用于构建服务导向的应用程序框架。它将各种通信技术统一到一个连贯的框架中,使开发人员能够构建...

    如何在windows服务中寄宿wcf服务的例子

    - 在`OnStart`方法内,使用`System.ServiceModel.ServiceHost`类创建WCF服务主机实例,传入服务类型和服务基地址。 - 调用`Open()`方法启动服务主机,使服务可以接受客户端请求。 5. **安装和启动Windows服务**:...

    Wcf 创建及不同宿主方式(自托管,windows服务,IIS)

    IIS是一种流行的Web服务器,能托管WCF服务,提供高可用性和扩展性。 1. **配置IIS**:确保已安装IIS和WCF所需的扩展(ASP.NET和WCF承载)。 2. **发布WCF服务**:通过Visual Studio的“发布”功能或手动复制到IIS...

    宿主为iis的wcf服务程序

    - **性能优化**:通过调整WCF服务的行为和绑定配置,可以优化服务的性能,如增大消息缓冲区大小、启用压缩等。 - **安全性配置**:根据业务需求,可以配置WCF服务支持的身份验证模式,如Windows、证书、基本等,以及...

    Android访问WCF服务源码(WCF服务端)

    1. **创建WSDL**: 首先,你需要拥有WCF服务的WSDL(Web Service Description Language)文件,它是WCF服务的接口描述,包含了服务的地址、绑定、消息格式等信息。在CSDN博客中提到的链接(由于此处无法直接提供链接...

    C#调用WCFService示例

    本教程将详细介绍如何在C#中调用WCF服务,以及在Visual Studio环境下创建和测试这个过程。 首先,理解WCF服务的基本概念至关重要。WCF服务是一种面向服务的架构,它允许开发者创建可以在网络上不同系统之间交换数据...

Global site tag (gtag.js) - Google Analytics