之前我与一个Microsoft Support Engineer交谈时,他提到在一些像我们这样的高负载的服务代理环境中,通过重用服务代理会话能够大大提升服务代理的性能。 为每一个消息创建和关闭会话需要的开销大约是4X,而对于接收消息的性能提升大约能达到10X。Remus Rusanu在他发布在Reusing Conversations的博客上,谈到这个估值可能更大,并且还提出了一种重用会话的解决方案。 我喜欢Remuss的解决方案,但其中有一个问题:我不愿意为每一个SPID创建不同的会话。
如果我使用这种方法,就会有大量的会话打开,这样我还需要去关闭它们。在应用中,许多问题都可能触发一个……
我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。
我原创,你原创,我们的内容世界才会更加精彩!
【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】
微信公众号
TechTarget
官方微博
TechTarget中国
之前我与一个Microsoft Support Engineer交谈时,他提到在一些像我们这样的高负载的服务代理环境中,通过重用服务代理会话能够大大提升服务代理的性能。
为每一个消息创建和关闭会话需要的开销大约是4X,而对于接收消息的性能提升大约能达到10X。Remus Rusanu在他发布在Reusing Conversations的博客上,谈到这个估值可能更大,并且还提出了一种重用会话的解决方案。
我喜欢Remuss的解决方案,但其中有一个问题:我不愿意为每一个SPID创建不同的会话。如果我使用这种方法,就会有大量的会话打开,这样我还需要去关闭它们。在应用中,许多问题都可能触发一个服务代理消息的发送。而且通常情况下都会有大量的线程在同一时间对数据库进行访问。这就要求我们在实际环境使用Remuss的方法之前要对它进行优化,使之更灵活。我的想法是为我们应用中的每一个进程创建一个会话。并且在一定周期内,有一些会话会被关闭,也有些新的会话被创建。
首先我先介绍一些关于安装服务代理的背景知识。我已经有2个队列和2个服务。每一个服务都在它自己的队列中。同时我有一个专门的消息类型,它用于将消息从源发送到目标位置。
- 我的消息类型是MT_ObjectDelete,
- 我的契约:CT_ObjectDelete,
- 我的队列:Q_ObjectDelete_Source和Q_ObjectDelete_Destination,
- 我的服务:Svc_ObjectDelete_Source和Svc_ObjectDelete_Destination,
另外我的另一个消息类型是MT_ConversationSwitch,它也是契约CT_ObjectDelete的一部分。
为了存储我将生成的会话句柄,我会使用现有一个保存各种配置信息的表Setting。我已经添加了一些新的会话终端记录到表中。其中在Setting表中的查询名称是SSB_Session_Delete。我使用GetSystemSettingValue方法来查询Setting表得到配置值。发送数据的存储过程是这样的:
CREATE PROCEDURE [dbo].[SendDelete] @FileName varchar(1024) AS DECLARE @DialogHandle uniqueidentifier, @msg XML, @date nvarchar(100) BEGIN IF @msg IS NOT NULL BEGIN SET @DialogHandle = cast(dbo.GetSystemSettingValue('SSB_Session_Delete') as uniqueidentifier) IF CAST(RAND()*100 AS INT) = 0 OR @DialogHandle IS NULL BEGIN IF @DialogHandle IS NOT NULL SEND ON CONVERSATION @DialogHandle MESSAGE TYPE [MT_ConversationSwitch] BEGIN DIALOG CONVERSATION @dialogHandle FROM SERVICE [Svc_ObjectDelete_Source] TO SERVICE Svc_ObjectDelete_Destination ON CONTRACT [CT_ObjectDelete_Multi]; UPDATE Setting SET DefaultValue = @DialogHandle WHERE SettingName = SSB_Session_Delete; END; SEND ON CONVERSATION @dialogHandle MESSAGE TYPE [MT_ObjectDelete] (@msg) IF @DialogHandle <> cast(dbo.GetSystemSettingValue(SSB_Session_Delete) as uniqueidentifier) SEND ON CONVERSATION @DialogHandle MESSAGE TYPE [MT_ConversationSwitch] END END GO |
你可以从代码中看到,我通过查询获取当前的会话句柄。如果没有找到句柄,我会创建一个新句柄并将句柄值保存到我的Setting表中。如果CAST(RAND()*100 AS INT)返回0,我会使用现在会话中的MT_ConversationSwitch消息类型发送一条消息,它将触发接收程序的逻辑,终止该会话。在我终止该会话后,我再创建新的会话并将它存储在数据库中。
然后我在该会话句柄上发送一条消息。接着我会再次检查Setting表,以确保我使用的值与表中的值是相匹配的。如果不匹配,我会认为另一个线程已经在相同的代码块中运行,然后关闭该会话,因为我不希望该会话继续存在。
我的接收程序非常简单:
CREATE PROCEDURE [dbo].[util_ProcessDelMonitorData] @MsgToRead INT = 1000 AS DECLARE @message_type_name sysname; DECLARE @message_body VARBINARY(max) DECLARE @msgTable TABLE ( message_body VARBINARY(max), [conversation_handle] UNIQUEIDENTIFIER ); BEGIN DECLARE @conversation_handle UNIQUEIDENTIFIER WHILE 1=1 BEGIN WAITFOR (RECEIVE TOP (1) @Message_Body = message_body, @conversation_handle = [conversation_handle], @message_type_name = message_type_name FROM [Q_ObjectDelete_Destination]), TIMEOUT 1000 IF @conversation_handle IS NULL BEGIN break END IF @message_type_name = MT_ConversationSwitch END CONVERSATION @conversation_handle IF @message_body IS NOT NULL BEGIN INSERT INTO @msgTable (message_body, [conversation_handle]) values (@message_body, @conversation_handle) END SET @conversation_handle = NULL SET @message_type_name = NULL END /*Business Logic happens here*/ END GO |
你可以看到,我会对于第一条消息做标准的接收。如果消息没有发现值,我会转而处理我之前存储在@msgTable表变量中的数据。
如果消息类型message_type_name是MT_ConversationSwitch,我会对该会话做一个中止会话(END CONVERSATION)的操作。
如果@message_body变量中有数据,我会将该值存储到表变量中,给后面的业务逻辑进行处理。
另外在发送队列中还有一个激活的程序,它只是对它接收的每一个消息做简单的中止会话(END CONVERSATION)操作。
我真心希望这个例子能对你有所帮助。如果你对此有任何问题,请提交你的问题,我将尽快地回复你。
Denny
翻译
TechTarget中国特约技术编辑,某高校计算机科学专业教师和网络实验室负责人,曾任职某网络国际厂商,关注数据中心、开发运维、数据库及软件开发技术。有多本关于思科数据中心和虚拟化技术的译著,如《思科绿色数据中心建设与管理》和《基于IP的能源管理》等。
相关推荐
-
云端SQL Server高可用性最佳做法
与内部部署相比,在云端运行SQL Server可为数据库软件用户提供更多的灵活性和可扩展性,也可能更省钱。但云 […]
-
绘制数据关系图的利器:SQL Server 图像数据库工具
SQL Server 2017新增了图形数据库功能,你可以使用图结构来表示不同数据元素之间的关系。
-
如何在Azure部署时选择合适的SQL Server?
想要在Azure上运行SQL Server,企业一般会面临两种选择:在Azure虚拟机上安装SQL Server或使用Azure SQL Database。
-
Linux支持的引入 推动了SQL Server 2016集成服务的发展
随着SQL Server的不断发展,集成服务也在发生相应的变化。在最新的SSIS更新中,增加Linux支持和SQL Server 2016升级向导。