【问题标题】:Using a remote, external web service instead of a database使用远程的外部 Web 服务而不是数据库
【发布时间】:2010-11-09 13:56:35
【问题描述】:

我正在构建一个将部署到 4 节点网络场的 ASP.NET Web 应用程序。

我的网络应用程序场位于加利福尼亚。

我计划使用一组从纽约数据中心提供的 Web 服务,而不是用于后端数据的数据库。

我有一个页面 /show-web-service-result.aspx 像这样工作:

1) 用户请求页面/show-web-service-result.aspx?s=foo

2) 页面的代码隐藏查询由第三方在纽约托管的 Web 服务。

3) 当web服务返回时,返回的数据被格式化并在页面响应中显示给用户。

这种架构是否存在潜在的可扩展性问题?假设我每秒获得数百个独特的点击,例如

/show-web-service-result.aspx?s=foo1

/show-web-service-result.aspx?s=foo2

/show-web-service-result.aspx?s=foo3

等等……

农场中的 Web 服务器通常使用 Web 服务来获取数据而不是数据库吗?有什么亲身经历?

我应该对架构进行哪些更改以提高可扩展性?

【问题讨论】:

    标签: asp.net web-services architecture scalability data-access-layer


    【解决方案1】:

    您肯定遇到了可扩展性问题:第三方 Web 服务。除非您与该服务签订了服务级别协议(就每秒可以提交的请求数量达成一致),否则您很有可能使该服务因预期负载而超载。你自己有四个节点对你没有帮助。

    因此,您应该 a) 与第三方达成协议,b) 测试他们可以承受的实际负载。

    此外,您需要确保您的框架可以使用并行连接来访问远程服务。假设您从加利福尼亚到纽约的往返时间为 20 毫秒(这将是相当不错的),您不能通过单个 TCP 连接发出超过 50 个请求。同样,为每个请求启动新的 TCP 连接也会降低性能,因此您需要在这些并行连接上进行池化。

    【讨论】:

    • 您说单个 TCP 连接上的请求数限制为 50 个。这是特定于操作系统的限制吗?我将使用 Windows Server 2008。另外,您能否建议如何在这些连接上使用池 - 知道如何使用 .NET 应用程序来完成吗?
    • 请尝试按照我的数学计算。 如果您的往返时间为 20 毫秒,那么您只能期望每秒发出 50 个请求,因为 50*20 毫秒 == 1000 毫秒 == 1 秒。写。 WCF 支持:WCF 本身似乎没什么可提供的。然而,人们已经建立在它之上,参见例如weblogs.asp.net/pglavich/archive/2007/05/07/…
    • 好的,我明白了。所以这不是全局最大值,它只适用于特定线程。因此,如果 5 个 Web 用户请求我在后端调用 Web 服务的页面,则这些后端连接中的每个连接将每秒最多有 50 个 Web 服务请求(假设 20 毫秒往返)。对吗?
    • 除非 WS 正在为您处理安全性(它不应该这样),否则将客户端多路复用到不相等数量的 WS 连接上会更有意义。也就是说,不要为每个客户端保持到 WS 服务器的单个连接 - 如果您的用户数量不可忽略,您将很快超载(更不用说恶意 DoS 攻击)。然而,Martin 所指的问题是单个连接上的请求是同步和顺序的。如果您有任何需要 20 毫秒的操作,则无论用户数量如何,您都不能在一秒钟内执行超过 50 次
    • AviD - 是的,如果我的请求是顺序的和异步的,我将有每秒 50 个请求的限制。但是,这些后端请求是并行发出的。每个客户端页面请求都在自己的线程中运行(对吗?),因此在后端,出站 WS 请求将与所有其他请求并行完成。 AFAIK,出站 WS 连接不会互相阻塞......
    【解决方案2】:

    我认为这种方法没有问题,我们在我工作的地方经常使用它。但是,这里有一些事情需要考虑:

    在等待 Web 服务响应时,您的页面呈现是否会被阻止? 如果没有响应,即服务停止,该怎么办?

    对于第一个问题,我会考虑在您从 Web 服务获得响应后使用 AJAX 更新页面。您还需要考虑如何处理无响应或超时情况。

    最后,您应该真正考虑一下如何在本地缓存 Web 服务数据。例如,如果您正在调用股票报价服务,那么除非您有实时提要,否则没有理由在收到每个请求时都调用 Web 服务。将数据在本地存储一段时间,然后将其返回,直到它变得陈旧。

    【讨论】:

    • 在性能方面,将数据缓存到本地是一个很好的建议。
    【解决方案3】:

    您可能会遇到可扩展性问题,但其中大部分问题都可以精心设计。

    我建议你使用 ASP.NET 的异步任务,这样 web 服务就排队,在请求等待 web 服务响应时释放线程,然后另一个线程在 web 服务完成完成时接起关闭请求。

    MSDN Magazine - Wicked Code - Asynchronous Pages in ASP.NET 2.0

    本地缓存是绝对必须的。从加利福尼亚到纽约的次数越少越好。您可能想查看 Microsoft 的 Velocity(尽管它仍在 CTP 中)或 NCache,或另一个分布式缓存,这样您的 4 个 Web 服务器中的每一个都不必从 Web 服务中生成和缓存相同的数据 - 一次服务器得到它,它应该可供所有人使用。

    您应该解决的其他可能出错的问题:

    • Web 服务已关闭(显然)并且数据超出缓存,您无法将其取回。尝试做到这一点,以便在您确定有可用更新之前,实际上不会从缓存中删除数据。那么唯一的风险是如果服务关闭并且您的应用程序池被重置,所以不要将其重置为一线故障排除策略!
    • Web 请求有两种不同的超时,连接超时和整体超时。确保两者都设置得非常低,并且你处理它们都超时。如果服务的 DNS 出现故障,这看起来可能是完全不同的故障。
    • 监视 ASP.NET 排队请求的性能。如果服务中断并且您没有正确覆盖,这个数字会迅速上升。
    • 研究和调整 ASP.NET 性能注册表设置,以便您拥有高度优化的 ASP.NET 线程池。我不记得具体细节,但我似乎记得 IO 完成端口和其他类似性质的限制对于我假设您手头上的强大硬件来说低得离谱。

    【讨论】:

      【解决方案4】:

      流行的答案是 REST。任何 GET 请求都可以缓存 HTTP 响应(有很多关于如何配置的选项),并且它会被 Internet 本身(本质上是您的 ISP)缓存。

      【讨论】:

        【解决方案5】:

        您的项目的架构反映了 Microsoft 和 SOA 世界中的许多其他人希望我们采取的方向。也就是说,许多人试图避免这种由 Web 服务引入的实时风险。

        您的系统将非常依赖以高效方式运行的 Web 服务。如果它不起作用或速度很慢,人们只会看到您的页面无法正常工作。

        至少,我会得到一个 Web 压力工具,并将您的 Web 服务的性能测试至少达到您期望在峰值时达到的流量水平,并且可能会超过这个水平。它什么时候破裂(如果有的话?),它什么时候开始减速?这些都是值得了解的好指标。

        其他可供选择的选项:也许您可以将每天一批的数据从 Web 服务获取到本地数据库,然后点击您网站的数据库。然后,如果由于某种原因 Web 服务出现故障或速度变慢,您可以使用最近获得的数据(如果这对您的数据可行)。

        总体而言,它应该是可行的,但您想了解和衡量风险,并探索任何可能的选项以最大限度地降低这些风险。

        【讨论】:

          【解决方案6】:

          没关系。存在一些可扩展性问题。主要是允许您每秒对外部 Web 服务进行的调用次数。某些网络服务(例如雅虎购物)会限制您调用其服务的频率,如果您调用太频繁,则会锁定您的帐户。如果您有一个大型农场和大量流量,您可能需要限制您的请求。

          此外,在这些情况下,通常会使用一个插页式页面,该页面会派生一个工作线程去执行 Web 服务调用,并在调用返回时重定向到结果页面。 (当您进行搜索时,请考虑一个旅游网站,当他们调用外部源以获取航班数据时,您会获得一个插页式页面,然后在调用完成时您会被重定向到结果页面)。如果您的 Web 服务调用快速返回,这可能是不必要的。

          【讨论】:

            【解决方案7】:

            我建议您一定要使用 WCF,而不是传统的 ASMX Web 服务技术作为客户端。使用“添加服务引用”而不是“添加 Web 引用”。

            【讨论】:

              【解决方案8】:

              您需要考虑的另一个问题取决于您要提取的应用程序和/或数据的类型:安全性。

              具体来说,我指的是身份验证和授权,包括您的最终用户以及 Web 应用程序本身。这些东西在哪里处理?全部在网络应用程序中?由WS?或者前端应用程序正在对用户进行身份验证,并将用户的身份流向后端 WS,从而验证用户是否被允许?你如何验证这一点?由于这里的许多其他响应者提到了前端应用程序上的本地数据缓存(一个优秀的想法,顺便说一句),这变得更加复杂:您是否缓存了允许用户 A 但不允许用户 B 的数据?如果是这样,您如何验证 userB 无法访问缓存中的数据?如果授权被WS检查了,那你如何缓存权限呢?

              另一方面,您如何验证仅允许您的 Web 应用程序访问 WS(例如,攻击者不会直接通过 Internet 访问您的 WS 数据)?就此而言,您如何确保您的 Web 应用程序与正确的 WS 服务器联系,而不是虚假的?当然,我假设所有到 WS 的连接都只是通过 TLS/SSL ......(当然也以编程方式验证证书适用于访问的服务器......)

              简而言之,它很复杂,需要考虑的因素很多......但它并非不可克服。

              (就输入验证而言,这实际上不是问题,因为这应该由 BOTH 前端应用程序和后端 WS 完成... )


              正如@Martin 所提到的,这里的另一个方面是,无论您为 NY WS 提供什么提供商/托管服务,都需要 SLA,不仅是为了性能,还包括可用性。 IE。如果服务器无法访问,他们承诺以多快的速度恢复服务器会发生什么情况,如果服务器长时间停机会发生什么情况等。这是合法转移风险的唯一方法受外部性控制。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2015-04-25
                • 2012-08-17
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多