0

我正在使用CreateSend API gem,并且在我的本地开发环境中,我能够成功地创建一个草稿活动。

生产(暂存)中,在 Heroku 上,完全相同的代码会返回错误:

310: HTML Content URL Required

我肯定将 HTML 内容 URL 以及所有其他必需的参数传递给Campaign.create(我通过记录变量直观地验证了这一事实)。这是 API 调用:

cm_campaign_id = CreateSend::Campaign.create client_id, subject, name, from_name, from_email, reply_to, html_url, text_url, list_ids, segment_ids

此外,在本地开发中,API 调用在不到 3 秒内返回,而在 Heroku 上,它会超时 30 秒并返回该错误。

为什么这会发生在 Heroku 上?

4

2 回答 2

0

简短回答:查看@kch 的回答

310: HTML Content URL Required运行一个网络测功机时出现错误。

以下是相关日志:

2012-07-04T19:11:13+00:00 heroku[router]: Error H12 (Request timeout) -> POST my-app-1111.herokuapp.com/campaigns dyno=web.1 queue= wait= service=30000ms status=503 bytes=0
2012-07-04T19:11:13+00:00 app[web.1]: cache: [GET /favicon.ico] miss
2012-07-04T19:11:13+00:00 heroku[router]: GET my-app-1111.herokuapp.com/favicon.ico dyno=web.1 queue=0 wait=0ms service=50ms status=304 bytes=0
2012-07-04T19:11:14+00:00 heroku[router]: Error H12 (Request timeout) -> GET my-app-1111.herokuapp.com/newsletters/1?cm=1 dyno=web.1 queue= wait= service=30000ms status=503 bytes=0
2012-07-04T19:11:14+00:00 app[web.1]: [error] CampaignMonitor error: The CreateSend API responded with the following error - 310: HTML Content URL Required

看到Request timeout错误GET my-app-1111.herokuapp.com/newsletters/1?cm=1让我想起了 Campaign Monitor 立即为所有时事通讯资产回调我的应用程序。

当我将网络测功机的数量增加到两个时,有时错误会变为312: Text Content URL Required并且它会超时GET my-app-1111.herokuapp.com/newsletters/1.txt;其他时候(仍然有两个 dynos)API 不会出错(实际上创建了活动草稿),但应用程序在其他资产上超时(并且网站仍然产生股票Application Error)。以下是其中一些资产超时:

2012-07-04T19:20:21+00:00 heroku[router]: Error H12 (Request timeout) -> POST my-app-1111.herokuapp.com/campaigns dyno=web.1 queue= wait= service=30000ms status=503 bytes=0
2012-07-04T19:20:24+00:00 heroku[router]: Error H12 (Request timeout) -> GET my-app-1111.herokuapp.com/assets/video/play.png dyno=web.1 queue= wait= service=30000ms status=503 bytes=0
2012-07-04T19:20:24+00:00 heroku[router]: Error H12 (Request timeout) -> GET my-app-1111.herokuapp.com/assets/video/pause.png dyno=web.1 queue= wait= service=30000ms status=503 bytes=0

当我将网络测功机的数量增加到三个时,仍然存在资产超时。

使用四个 web dyno,整个过程有时会成功完成(即并非总是如此!)——无论如何,即使它总是成功,四个 dyno 仅用于创建 Campaign Monitor 时事通讯就太昂贵了。


CDN 上的资产

由于asset_sync和fog,我已将我的应用程序转换为使用CDN 资产主机(Amazon S3) ,我又回到了这个问题:使用Heroku 的Campaign Monitor。

由于我的应用程序不再提供资产(它们由 Amazon S3 提供服务),因此它基本上只负责返回 HTML。

就 Campaign Monitor 而言,当您查询他们的 API 以根据您的时事通讯创建营销活动,他们会立即给您回电以下载您的时事通讯。这实际上意味着它们发送两个并行请求:一个用于新闻通讯的 HTML 版本,一个用于新闻通讯的 TEXT 版本。如果一个 dyno 被最初调用他们的 API 阻塞,并且所有资产都托管在 CDN 上,你会认为第二个 dyno 可以解决问题。事实上,我已经看到一秒钟的测功机处理“并行”请求(用于新闻通讯的 HTML 和 TEXT 版本)。但它是不可靠的,因为仍然存在随机超时():Error H12 (Request timeout)

2012-08-16T23:00:42+00:00 heroku[router]: Error H12 (Request timeout) -> POST my-app-1111.herokuapp.com/campaigns dyno=web.2 queue= wait= service=30000ms status=503 bytes=0
2012-08-16T23:00:42+00:00 heroku[router]: GET my-app-1111.herokuapp.com/favicon.ico dyno=web.4 queue=0 wait=0ms service=7ms status=304 bytes=0
2012-08-16T23:00:42+00:00 heroku[router]: Error H12 (Request timeout) -> GET my-app-1111.herokuapp.com/newsletters/1?cm=1 dyno=web.2 queue= wait= service=30000ms status=503 bytes=0
2012-08-16T23:00:43+00:00 app[web.2]: [error] CampaignMonitor error: The CreateSend API responded with the following error - 310: HTML Content URL Required

Heroku 的支持说这是因为他们独立地发送每个请求,期望最终接收的测功机能够处理它。这里发生的情况是,在某些情况下,发出帖子的同一个测功机是接收第二个请求的那个,但它似乎需要第二个请求的结果来完成发布请求,所以它死锁了。


解决方案

一种可能的临时解决方案是unicorn为您的应用服务器使用两个 unicorn worker_processes。这样即使 Heroku 派发到繁忙的测功机,第二个独角兽监听器也会响应请求。

最终,除了使用unicornwith two之外worker_processes,正确的解决方案是异步处理请求,通过类似的方式delayed_job,并用于workless根据需要启动 Heroku worker dynos,因此您只需为使用的内容付费。

于 2012-07-04T19:42:21.800 回答
0

因为他们的 API 需要在第一个正在进行的请求中间发生对您的应用程序的第二个请求,所以我建议您将逻辑移至工作进程:

  1. 对创建活动的应用程序的请求不会与活动监视器对话,而只是在表中创建一个作业,并重定向到检查该作业状态的页面
  2. 工作人员 dyno 看到工作并开始工作,发布到 Campaign Monitor API……因为这不是网络 dyno,等待不是问题
  3. 然后 CM API 将请求时事通讯页面并回复工作人员测功机
  4. 然后工人测功机可以更新工作的状态
  5. 一直以来,您在第一步中重定向到的页面可以继续刷新自身以轮询作业的状态,并在发现作业完成后显示最终页面。
于 2012-09-12T22:29:44.913 回答