这个问题可能不仅仅特定于Azure功能,但对我来说就是这个场景。我有azure函数,它处理来自服务总线主题订阅的消息。消息用于在sql azure服务器上的表中添加/更新数据。
对于数据库操作,我使用的是Entity framework 6.2
我的消息可以是100个,但可能只有第一条消息是应该在数据库中插入条目的消息,接下来的几条消息是同一条记录的更新。
现在,在我的Azure函数中,我的host.json看起来像这样。
{
"serviceBus": {
"maxConcurrentCalls": 16,
"prefetchCount": 20,
"autoRenewTimeout": "00:05:00"
}
}
这意味着,它应该能够同时处理16条消息,它就是这样做的。
然而,对于并发处理,实体框架上下文不会从并行运行事务更新,我最终有10行,我应该在数据库中只有1行,因为它基本上是相同的记录。
是否有针对此的实体框架特定解决方案?
答案 0 :(得分:1)
您要做的是将属于同一实体的邮件的处理限制为1。有几种方法可以做到这一点:
要在Entity Framework级别解决此问题,您需要使用Serializable隔离级别将读写操作正确地包装到单个事务中。然而,它并没有多大意义:您对消息进行并行处理,但在数据库级别上使用昂贵的锁来限制并行化。
使用数据库级约束(如唯一索引),然后确保每条消息都为同一实体插入具有相同唯一键的行。尝试编写它的第二个操作将获得约束违规异常,将重试将导致更新的操作。
只需将maxConcurrentCalls
限制为1
,并且永远不会运行多个函数实例。这是最简单的方法,但显然它不会为更高的负载进行扩展。
使用基于实体密钥的服务总线会话,即将相同实体的消息发送到同一会话。但坏消息:Azure Functions不支持Service Bus会话,因此您必须回退到手动处理。
使用例如事件中心而不是服务总线订阅。按实体ID对事件进行分区,然后按照In order event processing with Azure Functions。