如何在 Heroku 上 运行 InfluxDB?

How to run InfluxDB on Heroku?

这可能吗?如果可能的话,怎么做?我希望能够从我现有的 Heroku 基础设施访问它。

我需要 Procfile 吗?据我了解,它只是一个用 Go 编写的独立二进制文件!所以部署它不应该那么难,我只是很好奇如何部署它,因为我认为我不了解 Heroku 部署的来龙去脉。

我认为在使用自定义 buildpack 时在 Heroku 节点上一切皆有可能,但是在使用 Heroku 托管时有一些注意事项:

  • ops,例如备份、监控(是否需要安装额外的服务、打开额外的端口等 - Heroku 可能会妨碍到这里)
  • 性能,考虑到 dyno size
  • 如果您需要更大的测功机,成本就成了问题。当您选择 IaaS 路线时,您将获得更多收益。
  • 其他 "features" 测功机,例如磁盘短暂性

我强烈推荐 hosted InfluxDB 或在 VPS 上启动你自己的,所有这些你都可以将你现有的基于 Heroku 的应用指向。然后,假设数据库和应用程序堆栈之间需要低延迟,它将有助于使这些实例尽可能靠近(即同一区域,或者如果可能的话位于同一地点)。

Heroku Dynos 应该用于部署像 InfluxDB 这样的数据库应用程序。

Dynos 是临时服务器。数据不会在测功机重启之间持续存在,也无法与其他测功机共享。实际上,部署在 dyno 上的任何数据库应用程序本质上都是无用的。这就是为什么 Heroku 上的数据库(例如 Postgres)都是附加组件。 InfluxDB 应该在不同的平台(例如 AWS EC2 或 VPS)上设置,因为 Heroku 附加组件不可用。


也就是说,可以 将 InfluxDB 部署到 Heroku dyno。

首先,了解 'slug' 的概念很重要。 Slugs 是容器(类似于 Docker 图像),它包含 运行 Heroku 基础设施上的程序所需的一切。要部署 InfluxDB,需要创建一个 InfluxDB slug。* 有两种方法可以为 Go 库创建一个 slug:

  1. 按照 here 所述直接从 Go 可执行文件创建 slug。**
  2. 使用 Heroku Go buildpack(在下面解释)从源代码构建 slug。

要使用构建包从源代码构建 slug,首先克隆 InfluxDB Github 存储库。然后在 repo 的根目录添加一个 Procfile,当 dyno 启动时,它告诉 Heroku 命令 运行。

echo 'web: ./influxd' > Procfile

Go buildpack 要求目录中包含所有依赖项。使用 godep 依赖工具将 vendor 所有依赖项放入目录中。

go get github.com/tools/godep
godep save

接下来,将上面所做的更改提交到 git 存储库。

git add -A .
git commit -m dependencies

最后,创建一个新应用并告诉它使用 Go buildpack 进行编译。

heroku create -b https://github.com/kr/heroku-buildpack-go.git
git push heroku master
heroku open    // Open the newly created InfluxDB instance in the browser.

Heroku 将显示一个错误页面。 将显示一个错误,因为 Heroku 的 'web' 进程类型需要一个应用程序来侦听端口描述的传入请求$PORT 环境变量,否则会杀死dyno。 InfluxDB 的 API 和管理面板 运行 分别在端口 80868083 上。

不幸的是,InfluxDB 不允许从环境变量中设置这些端口,只能通过配置文件 (/etc/config.toml)。在 InfluxDB 启动之前执行的一个小 bash 脚本可以在 InfluxDB 启动之前在配置文件中设置正确的端口。

另一个问题,Heroku 只为每个 dyno 暴露一个端口,所以 API 和管理面板不能同时暴露在互联网上。智能反向代理可以使用 Heroku 的 X-Forwarded-Port request header.

解决该问题

底线,不要使用 Heroku dynos 运行 InfluxDB。


* 这意味着在部署到 Heroku 时失去了独立 Go 可执行文件的优势,因为它需要为 Heroku 的堆栈重新编译。

** 直接从 InfluxDB 可执行文件创建一个 slug 是行不通的,因为没有内置的方法来监听 Heroku 在 $PORT 环境变量中给出的正确端口。