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.
- Use NetTCP binding
This helps both throughput and the time it takes to open and close
connections
- 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(...);
- 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:
- <serviceBehaviors><serviceThrottling ...> set
the max values high
- <dataContractSerializer
maxItemsInObjectGraph="2147483647" />
- and under <netTcpBinding> setting the listenBacklog,
maxConnections, and maxBuffer* value high
- 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.
- 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
|
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,
};
- 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
[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服务由以下四个主要元素组成:...
在Azure中寄宿WCF服务,不仅可以利用云平台的弹性伸缩能力,还能享受到高可用性和易于管理的优势。同时,Azure的其他服务,如Azure SQL Database、Azure Blob Storage等,可以与WCF服务无缝集成,构建更复杂的云应用...
- **客户端配置**:对于Web调用,Java客户端可以使用JAX-WS或Apache CXF等库来创建代理类,调用WCF服务。对于C#客户端,可以使用`svcutil.exe`工具生成服务代理代码,然后在C#代码中实例化并调用服务。 - **安全性...
通过对“Programming WCF Services”源代码的分析和实践,你将能够掌握WCF的核心概念,并有能力创建自己的WCF服务。同时,这也将帮助你理解如何与其他系统进行互操作,以及如何解决在分布式环境中可能出现的问题。
最后,遵循最佳实践,如使用适当的安全配置、最小化服务契约和数据契约,以及监控和调整服务行为,都是实现高性能WCF服务的关键步骤。 总的来说,设计高性能的WCF解决方案需要全面考虑传输层、序列化、编码器的选择...
服务端是实现WCF服务的地方,它使用`ClassLibrary1`中的服务合同来创建具体的实现。在`winServer2`项目中,你需要创建一个类(如`Service1`)并实现`IService1`接口。此外,还需要配置服务的终结点(Endpoint),这...
要实现C#中的POST请求,你需要创建一个客户端代理类来代表WCF服务。这可以通过使用`svcutil.exe`工具或者在Visual Studio中添加服务引用来完成。生成的代理类会包含方法,这些方法可以直接调用来调用服务的操作。 1...
本教程将深入探讨WCF服务的创建以及客户端如何调用这些服务。 ### 创建WCF服务端 1. **服务契约(Service Contract)**:定义服务提供的操作或方法。这是通过接口来实现的,标记为`[ServiceContract]`。例如: ```...
通过学习这些内容,开发者可以掌握创建和管理高效、安全的WCF服务的能力,能够构建符合企业级标准的分布式系统。此外,对于理解SOA(面向服务架构)和微服务架构也有着重要的理论支撑作用。在实际开发中,掌握WCF...
**高性能的WCF解决方案** Windows Communication Foundation (WCF) 是微软提供的一种面向服务的通信框架,用于构建可互操作的、安全的、可靠的企业级应用程序。在本文中,我们将深入探讨如何优化WCF服务,以实现更...
1. **创建WCF服务**:首先创建一个WCF服务,定义接口和实现,并在服务端配置跨域策略文件的路径。 2. **宿主服务**:将服务宿主在Windows服务中,确保服务运行时可正确加载跨域策略文件。 3. **创建Silverlight...
本项目提供了一个使用C#编写的WCF服务示例,适用于Visual Studio 2008及更高版本,便于理解和学习。 1. **WCF服务基础** - WCF是微软提出的一种统一的编程模型,它集成了.NET Framework中的Web服务(ASMX)、...
WCF(Windows Communication Foundation)是微软.NET框架下的一种面向服务的通信框架,它为构建、配置和部署可互操作的、安全的、可靠的、高性能的服务提供了全面的支持。本压缩包中的源码着重展示了WCF服务的编程...
在本文中,我们将深入探讨如何在Visual Studio 2010 (VS2010) 中使用jQuery调用WCF(Windows Communication Foundation)服务。...通过学习和实践这些内容,开发者能够提高其在构建高性能、可扩展的Web应用方面的技能。
### WCF服务编程知识点详解 #### 一、WCF基础概览 **WCF(Windows Communication Foundation)** 是微软提供的一套用于构建服务导向的应用程序框架。它将各种通信技术统一到一个连贯的框架中,使开发人员能够构建...
- 在`OnStart`方法内,使用`System.ServiceModel.ServiceHost`类创建WCF服务主机实例,传入服务类型和服务基地址。 - 调用`Open()`方法启动服务主机,使服务可以接受客户端请求。 5. **安装和启动Windows服务**:...
IIS是一种流行的Web服务器,能托管WCF服务,提供高可用性和扩展性。 1. **配置IIS**:确保已安装IIS和WCF所需的扩展(ASP.NET和WCF承载)。 2. **发布WCF服务**:通过Visual Studio的“发布”功能或手动复制到IIS...
- **性能优化**:通过调整WCF服务的行为和绑定配置,可以优化服务的性能,如增大消息缓冲区大小、启用压缩等。 - **安全性配置**:根据业务需求,可以配置WCF服务支持的身份验证模式,如Windows、证书、基本等,以及...
1. **创建WSDL**: 首先,你需要拥有WCF服务的WSDL(Web Service Description Language)文件,它是WCF服务的接口描述,包含了服务的地址、绑定、消息格式等信息。在CSDN博客中提到的链接(由于此处无法直接提供链接...
本教程将详细介绍如何在C#中调用WCF服务,以及在Visual Studio环境下创建和测试这个过程。 首先,理解WCF服务的基本概念至关重要。WCF服务是一种面向服务的架构,它允许开发者创建可以在网络上不同系统之间交换数据...