我正在运行一个 Windows Azure Web 角色,在大多数情况下,该角色接收的流量非常低,但有一些(可预见的)事件可能导致必须完成大量后台工作。后台工作由许多数据库调用 (Azure SQL) 和对外部 Web 服务的 HTTP 调用组成,因此它并不是真正的 CPU 密集型工作,但它需要大量等待数据库或 Web 服务响应的线程。后台工作由对 Web 角色的正常 HTTP 请求触发。
我看到有两种选择来协调这一点,但我不确定哪个更好。
- 选项 1,线程:当后台工作请求进来时,Web 角色会根据需要启动尽可能多的线程(或将各个工作项排队到线程池中)。在这个选项中,我会在繁重的工作负载期间配置一个更大的实例,因为这些线程可能需要大量内存。
- 选项 2,自调用:当后台工作的请求进来时,接收它的 Web 角色会为每一项后台工作向自己生成一个 HTTP 请求。在此选项中,我可以配置多个 Web 角色实例,因为 Windows Azure 的负载平衡器会在实例之间平衡 HTTP 请求。
选项 1 稍微简单一些,但它的缺点是只有一个实例可以处理后台工作。如果我希望多个 Azure 实例参与后台工作,除了将 HTTP 请求从角色发送到自身之外,我看不到任何其他选项,以便负载均衡器可以将一些工作委派给其他实例。
也许还有其他选择?
编辑:关于选项 2 的更多想法:当后台工作请求进来时,接收它的实例会将要完成的工作保存在某种队列中(Windows Azure 队列或一些作为任务工作的 SQL 表队列)。然后,它会向自己生成大量 HTTP 请求,以便负载均衡器“激活”所有角色实例。然后每个实例从队列中取出一个任务并执行该任务,然后获取下一个任务等,直到所有任务完成。这就像偶尔将网络角色用作工作者角色一样。
我知道这种方法有一种臭味(滥用 Web 角色作为工作角色,对同一个 Web 角色的 HTTP 请求),但我没有看到真正的缺点。
编辑 2:我看到我应该详细说明应用程序的确切情况:
该应用程序需要一直执行一些小任务。这些任务通常不会超过 1-10 秒,而且它们不需要大量的 CPU 工作。在正常的日子里,我们只有 50-100 个任务要完成,但在“特殊日子”(新年就是其中之一),他们可能会进入几个 10000 个任务,这些任务必须在 1-2 内完成小时窗口。这些任务以 Web 角色完成,我们有一个Cron 作业,它每分钟启动一次任务。因此,Web 角色每分钟都会收到处理新任务的请求,因此它会检查必须处理哪些任务,将它们添加到某种队列中(目前它是一个带有 UPDATE 和 OUTPUT INSERTED 的 SQL 表,但我们打算切换有时到 Azure 队列)。目前,同一个实例处理任务排队后立即,但这不会扩展,因为几个 10'000 任务的串行处理需要太长时间。这就是为什么我们正在寻找一种机制来将事件“任务可用”从初始实例广播到其他实例的原因。