1

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

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

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

4

5 回答 5

3

我认为memcached是一个不错的选择。

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

PHP 有 memcached 扩展,请在此处查看文档

于 2013-06-14T18:28:59.630 回答
1

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

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

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

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

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

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

于 2013-06-14T22:42:54.470 回答
0

是的,只需使用 HTTP。大多数繁重的工作已经内置到您的 Web 服务器中。

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

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

于 2013-06-14T18:35:06.857 回答
0

缓存功能有多种形式:

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

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

你可以做更复杂的事情,比如在后台预先缓存一些东西,这样就不会出现缓存未命中,或者有一些代码路径可以接受陈旧的数据以便快速返回,但这些通常可以在你的任何东西之上实现'正在用作主要的缓存解决方案。

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

于 2013-06-14T19:08:10.897 回答
0

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

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

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

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

于 2013-06-14T18:53:31.407 回答