【问题标题】:Linux server: Would a cache scheme help reduce hits to 3rd-party server?Linux 服务器:缓存方案是否有助于减少对第 3 方服务器的命中?
【发布时间】:2013-06-15 21:14:06
【问题描述】:

我的 Linux 服务器将运行一个网站,该网站通过 SOAP 接口从第 3 方服务器获取一些数据。数据并不完全是实时的,但它确实每 5 分钟左右更改一次。有人告诉我不要让我们的网站敲打他们的网站来获取数据,我完全可以理解。

所以我想知道这是否是使用某种类型的缓存方案的好候选。当用户访问我们的网页以显示数据时,如果它不到 5 分钟(例如),它将从我们的服务器获取该数据,而不是轮询第 3 方。这样,如果 100 位用户同时访问我们的网站,我们的服务器将不会在给定的时间范围内访问 3rd 方网站 100 次以共享相同的确切数据。

这在 PHP 中是否实用?还是在缓存方面应该用更快的语言编写?他们的缓存包是否可以与 PHP Joomla 应用程序一起使用?谢谢!

【问题讨论】:

    标签: php linux caching


    【解决方案1】:

    我觉得memcached是个不错的选择。

    您可以在将内容存储到 memcached 服务器时设置超时,如果 key-value 丢失,则从 3rd-part 服务器检索数据并再次存储。

    有用于 PHP 的 memcached 扩展,请在此处查看 doc

    【讨论】:

    • 我还要提到不要打扰更快的语言 - 除非您对 添加一层缓存后的速度不满意。
    【解决方案2】:

    有很多方法可以解决问题 - 如果不了解更多有关您正在处理的限制或如何使用服务的信息,我们就无法说哪个是正确的。如果您使用的是 Joomla,那么您显然不会担心性能 - 编写任何对您的 html 生成时间有可衡量影响的东西真的很难。这不需要“用更快的语言编写”,但是....

    1. 您可以安装其他软件吗?
    2. 您可以访问 cron 吗?
    3. 服务的消耗率是多少?
    4. 您有多少台网络服务器在使用该服务 - 它们是否有共享文件系统?它们在同一个子网中吗?
    5. SOAP 响应是否可缓存?
    6. 您如何处理不可用的服务?

    对于一个非常可扩展的解决方案,我建议运行一个简单的转发代理(例如 squid),但请确保它不能从 Internet 访问。 Sven(参见其他地方的评论)关于 POST sometimes 不可缓存是正确的 - 但您可以在您自己的站点上缓存来自代理脚本的响应,该站点通过 GET 返回适当的缓存指令进行访问 - 这可能会返回数据作为一个序列化的 php 数组/对象,处理起来要便宜得多。事实上,无论您选择哪种方法,我都建议缓存解析后的响应——而不是 XML。这还允许您覆盖来自服务的不良缓存信息。

    如果速率低于每分钟 1 次左右,那么 cron 解决方案就过大了。但如果它每分钟超过 20 次,那就很有意义了。如果您无法访问 cron / 无法安装自己的软件,那么您可以考虑简单地缓存响应并按需刷新缓存。除非您已经在使用它,否则不要打扰 memcache。 APC 在单个服务器上更快 - 但内存缓存是分布式的。如果您有多个服务器,则使用您当前共享数据的任何集群存储(分布式文件系统/数据库集群/共享文件系统......)。

    不要尝试在缓存刷新周围使用锁定/互斥锁,除非你真的必须这样做(即,只有每 5 分钟访问一次以上的服务是一种致命的罪过)——这会很快变得非常复杂——太容易了引入错误。

    确保在将响应写入缓存之前缓冲并验证它们。

    【讨论】:

      【解决方案3】:

      是的,只需使用 HTTP。大部分繁重的工作已经内置到您的网络服务器中。

      由于 SOAP 只是一个带有 XML 正文的简单 HTTP POST 请求,因此您可以在 SOAP 端点前面设置您的网站或 HTTP API 以充当常规 HTTP 的转换器,将适当的 HTTP 缓存标头附加到转换后的响应体,然后在它前面配置一个 NGinx 反向代理。

      值得注意的是:如果转换很简单,您可以使用 XSLT 转换来自 SOAP API 的响应主体并完全移除 Web 服务层。

      【讨论】:

      • 我认为不通过专门配置的代理向全世界公开第三方 SOAP 服务要容易得多。此外,除非服务器明确允许,否则 POST 请求通常不会被缓存 - SOAP 响应在 HTTP 级别上是不可缓存的。
      • 忽略代理将做什么和不做什么的含义,这听起来像是一个简单问题的极其复杂的解决方案。与一些用于检查本地缓存是否过时的 PHP 类相比,标头重写反向代理和 XSLT 都不是很容易学习的技术。
      • @Sven:SOAP POST 什么时候不能缓存?来自 RFC 2616:“对此方法的响应不可缓存,除非响应包含适当的 Cache-Control 或 Expires 标头字段。但是,303(请参阅其他)响应可用于指示用户代理检索可缓存资源。”另见pic.dhe.ibm.com/infocenter/wasinfo/v8r0/…
      • @IMSoP 我看不出这有多“难以置信的复杂”。 OP 需要一种将 SOAP 请求转换为根据一些基本规则缓存的响应的方法。这正是 HTTP 擅长的。如果基本的 XSLT 和基本的 Web 服务器配置太复杂而无法实现,那么是什么让您认为用 PHP 来实现会更容易呢?既然 HTTP 已经充分提供了解决方案,为什么还要用整个 Web 应用程序堆栈重新实现它?
      • 请考虑一下“来自第三方的一些数据”只是某个公司的股票市场报价,而网站的其余部分已经存在。您认为将整个现有网站转换为除了股票价格之外还添加到 XSLT 转换中的东西是一个可行的解决方案吗?谁会维护它?似乎有 PHP 方面的知识,XSLT - 没有那么多。
      【解决方案4】:

      您的问题很小,不需要复杂的解决方案。

      您可以编写一个每五分钟执行一次的小型 cron 作业,将请求发送到 SOAP 服务器,并将结果存储在本地文件中。如果任何脚本需要数据,它会读取本地文件。这将导致每天向 SOAP 服务器发出 288 个请求,并且对于任何需要结果的脚本调用都具有出色的性能,因为它们已经在您的服务器上。

      如果您没有可用的 cron 作业并且无法伪造它们,则任何其他缓存都可以。你真的不需要像 Memcached 这样的花哨的东西,除非它已经可用。将结果存储到缓存文件也可以。请注意,如果您必须真正从源中获取 SOAP 结果,这将需要更多时间,并且可能会影响您网站的感知性能。

      有很多框架也提供缓存支持,如果您使用其中一个,您应该调查是否包含支持。我不确定 Joomla 是否有适合你的东西。否则,您可以自己实现一些东西。没那么难。

      【讨论】:

      • 我对 memcached 过于矫枉过正的暗示感到困惑,但是预先缓存数据而不是在数据过期时被动缓存数据的 cron 作业是合理的。
      • 文件系统通常已经可用 - Memcached 通常不可用。是否可以使用 cron 作业取决于所使用的托管类型。
      • 我更多地认为,对于大多数缓存需求,预缓存不仅是不必要的,而且可能是不可取的,所以它似乎是一个奇怪的起点。如果网站一夜之间没有访问者,为什么要每 5 分钟向第三方发送一个或多个请求(我们不知道可能有多少变体调用),而您要丢弃数据?
      • 您可能是对的,但没有信息“数据”是否会根据参数发生变化。如果没有,预取是完全可以的。如果五分钟前没有请求填满缓存,则无关紧要。
      • 当然,这是一个有用的附加想法,我将其添加到我的答案中;我只是不认为预缓存是首先要考虑的事情,因为内联缓存更容易实现。
      【解决方案5】:

      缓存功能有多种形式:

      • 基于内存,服务器上的一个单独进程将数据保存在 RAM 中(或溢出到磁盘),您可以像查询数据库一样查询它;非常高效和强大,并且可以选择管理存储使用和自行清理,但需要在服务器上设置额外的软件;例如memcached, redis
      • 基于文件,只需将数据写入磁盘;效率较低,但可以在“用户级”代码中实现,即纯 PHP;小心使用已过期但未清理的变体缓存填充您的磁盘;许多框架都内置了这个实现
      • 数据库支持,将数据推送到 RDBMS(例如 MySQL、PostgreSQL)或功能齐全的 NoSQL 存储(例如 MongoDB);如果您有大量数据并且可以换取一些性能,这可能是有意义的;与文件一样,您需要确保清理过时的数据

      在每种情况下,基本思想是您创建一个“密钥”,可以将一个请求与另一个请求区分开来(例如,SOAP 调用的名称及其输入参数,序列化),并选择一个“生命周期”(多长时间您想继续使用相同的数据副本)。然后缓存引擎或库使用该键检查缓存,如果它仍在其“生命周期”内,则返回先前缓存的数据。如果存在“缓存未命中”(该键没有缓存,或者它已过期),您将执行代价高昂的操作(在您的情况下为 SOAP 调用)并使用相同的键保存到缓存中。

      你可以做更复杂的事情,比如在后台预先缓存一些东西,这样就不会发生缓存未命中,或者有一些代码路径接受陈旧数据以便快速返回,但这些通常可以在顶部实现无论您使用什么作为主要缓存解决方案。

      编辑 另一个重要的决定是缓存数据的粒度级别,与处理数据相关。在一个极端情况下,您可以缓存每个单独的 SOAP 调用:设置简单,但意味着重复地重新处理相同的数据,如果两个响应相关,则可能会导致问题,但独立缓存并可能不同步。在另一个极端,您可以缓存整个渲染页面:页面在缓存后加载速度非常快,但是基于相同数据创建变体而不重复工作变得很棘手。中间是代码中的各个点,您在这些点处处理数据并将数据组合成有意义的块:如果您的应用程序编写得很好,这些是主要功能的输入和输出,甚至可能是完整的模型对象;这需要更多的工作来实现,因为您必须选择正确的键(避免两个上下文覆盖彼此的缓存,同时忽略对相关数据没有影响的变量)和值(避免重复昂贵的工作而不必存储巨大的 blob反序列化和耗尽缓存存储容量的数据会很慢)。与其他任何事情一样,没有一种方法可以满足所有需求,而且复杂的应用程序可能会涉及到多个级别的缓存以用于不同的目的。

      【讨论】:

        猜你喜欢
        • 2021-12-30
        • 2011-03-21
        • 2013-08-16
        • 2011-08-24
        • 1970-01-01
        • 1970-01-01
        • 2012-10-22
        • 2021-10-03
        • 2022-11-04
        相关资源
        最近更新 更多