BizTalk - 接收端口从数据库读取两次

发布于 2024-08-19 19:58:20 字数 313 浏览 6 评论 0原文

我的接收端口是 sqlBinding 和类型轮询。它调用 SP 来获取记录,并根据过滤条件启动相应的编排。 BizTalk组由2台服务​​器组成;因此有 2 个 ReceiveHostInstances。如果两个主机实例都在运行 - 在某些时候相同的请求被读取两次 - 导致接收端出现重复。但是,为什么接收端口多次读取同一条记录呢?读取记录的过程会更新记录并更新它,以便它不会再次受到影响。

我在提交 10 个请求时观察到了这种情况;接收端口读取 11 次并启动 11 个编排。

我对一台主机(如在我的开发中)尝试了相同的操作(10 个请求),接收仅显示 10 个。有什么线索吗?

My receive port is of sqlBinding and typed polling. It invokes a SP to fetch a record and based on filter condition the corresponding orchestration kicks off. The BizTalk group consists of 2 servers; thus 2 ReceiveHostInstances. If both the host instances are running -at some point the same request is being read twice - causing a duplicate at the receivers end. But, why is the reeive port reading it the same record more than once? The proc which reads the updates the record and updates it so that it wont be fecthed again.

I observed this scenario while submitting 10 requests; receive port read 11 times and 11 orchestrations started.

I tried the same (10 request) with one host (as in my Dev), the receive is showing 10 only. Any clues?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

〆一缕阳光ご 2024-08-26 19:58:20

快速的答案是,您有两个选项可以解决此问题:

  1. 修复您的存储过程,使其在并发情况下正常运行。
  2. 将 SQL 轮询接收处理程序放置在群集 BizTalk 主机中。

下面是对正在发生的事情的解释,并在其中提供了解决该问题的实现的详细信息:

解释

这是由于在多个主机实例上运行时 BizTalk 接收位置的工作方式(即,接收位置中指定的适配器正在具有多个主机实例的主机上运行)。

在这种情况下,两个主机实例都将运行其接收处理程序。

这通常不是问题 - 大多数接收适配器都可以管理此问题并为您提供您所期望的行为。例如,文件适配器在读取文件时对其进行锁定,以防止重复读取。

出现此问题的主要位置正是您所看到的 - 当轮询 SQL 接收位置正在命中存储过程时。在这种情况下,BizTalk 没有其他选择,只能相信 SQL 过程会给出正确的结果。

如果不查看您的过程,很难判断,但是您查询记录的方式并不能保证唯一的读取。

也许您有这样的情况:

Select * From Record 
Where Status = 'Unread'

Update Record 
Set Status = 'Read'
Where Status = 'Unread'

上面的过程可能会给出重复的记录,因为在选择和更新之间,选择的另一个调用能够潜入并选择尚未更新的记录。

实施解决方案

修复过程 该

过程的一个简单修复是首先使用唯一的 id 进行更新:

Update Record 
Set UpdateId = @@SPID, Status = 'Reading'
Where Status = 'Unread'

Select * From Record
Where UpdateId = @@SPID
And Status = 'Reading'

Update Record
Set Status = 'Read'
Where UpdateId = @@SPID
And Status = 'Reading'

@@SPID 应该是唯一的,但如果证明不是唯一的,您可以使用 newid()

使用群集主机

在 BizTalk 服务器管理中 创建新主机时,可以指定该主机是集群的。有关执行此操作的详细信息,请参阅 Kent Weare 的帖子

本质上,您可以像往常一样创建一个主机,在每个服务器上都有主机实例,然后右键单击该主机并选择集群。

然后,您为在该主机下工作的轮询创建一个 SQL 接收处理程序,并在您的接收位置使用该处理程序。

BizTalk 群集主机可确保属于该主机成员的所有项目一次只能在一个主机实例上运行。这将包括您的 SQL 接收位置,因此您在调用过程时不会有任何竞争条件的机会。

The quick answer is that you have two options to fix this problem:

  1. Fix your stored procedure so that is behaves correctly in concurrent situations.
  2. Place your SQL polling receive handler within a clustered BizTalk host.

Below is an explanation of what is going on, and under that I give details of implementations to fix the issue:

Explanation

This is due to the way BizTalk receive locations work when running on multiple host instances (that is, that the receive handler for the adapter specified in the receive location is running on a host that has multiple host instances).

In this situation both of the host instances will run their receive handler.

This is usually not a problem - most of the receive adapters can manage this and give you the behaviour you would expect. For example, the file adapter places a lock on files while they are being read, preventing double reads.

The main place where this is a problem is exactly what you are seeing - when a polling SQL receive location is hitting a stored procedure. In this case BizTalk has no option other than to trust the SQL procedure to give the correct results.

It is hard to tell without seeing your procedure, but the way you are querying your records is not guaranteeing unique reads.

Perhaps you have something like:

Select * From Record 
Where Status = 'Unread'

Update Record 
Set Status = 'Read'
Where Status = 'Unread'

The above procedure can give duplicate records because between the select and the update, another call of the select is able to sneak in and select the records that have not been updated yet.

Implementing a solution

Fixing the procedure

One simple fix to the procedure is to update with a unique id first:

Update Record 
Set UpdateId = @@SPID, Status = 'Reading'
Where Status = 'Unread'

Select * From Record
Where UpdateId = @@SPID
And Status = 'Reading'

Update Record
Set Status = 'Read'
Where UpdateId = @@SPID
And Status = 'Reading'

@@SPID should be unique, but if it proves not to be you could use newid()

Using a clustered host

Within the BizTalk server admin console when creating a new host it is possible to specify that that host is clustered. Details on doing this are in this post by Kent Weare.

Essentially you create a host as normal, with host instances on each server, then right click the host and select cluster.

You then create a SQL receive handler for the polling that works under that host and use this handler in your receive location.

A BizTalk clustered host ensures that all items that are members of that host will run on one and only one host instance at a time. This will include your SQL receive location, so you will not have any chance of race conditions when calling your procedure.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文