Heroku 替代方案 Render:部署 LINE Bot

用其他免費服務取代 Heroku

因應之前宣布《Heroku’s Next Chapter》表達免費方案僅服務至 2022 年 11 月 28 日,我需要為 LINE Bot 思考一下要改部署到那邊,或者就乾脆付費升級。

其實付費升旗,基本上並不在我的選項之中,因為我開始做產品,短時間內我也會以邊學習邊開發的方式,看起來並不會很快地就可以收回收。所以找尋其他免費的方案就這樣放在心中,剛好趁著最近幾天放假,網路搜尋一下,發現有已經有相關的文章,順勢也做完自己的轉移。

開頭是看到了我平常 RSS 訂閱的部落格,已經有寫到 Heroku 免費服務終止,並且比較了一些方案《 5 個替代 Heroku 的平台》,裡面提供了不少的方案,因為之前有在 Buttondown 作者 Justin 的文章中看到,他轉移到 fly.io 的經驗,本來以為我也會這樣選,但後來我並沒有。

因為,我不喜歡在電腦安裝太多組件,fly.io 好似需要安裝 ctl 在自己的電腦,所以我就放棄了。我個人想要的方向大概是:

  1. 提供免費方案;
  2. 不用安裝任何程序在本機;
  3. 能夠透過 Github 去管理。

在文章中看到了方案有 Railway 跟 Render,作者本來說 Railway 的收費方式比較合理,我本以為我也會採用,但後來在搜尋一下其他的文章,Render 的文章數量明顯比 Railway 還多,還有一篇專針對 Render 跟 LINE Bot 的文章,至此,大致底定在執行沒有遇到困難的情況下,準備轉部署到 Render。

多數的步驟請參考上面文章申請帳號,設定的部分則大致上跟《[Deploy to Render] 用免費方案部署 LINE Bot》這一篇雷同,特別點出一些小地方。

一、部署自己的程式

作者很貼心的把部署的 yaml 檔案(使用 Python 可以點此)已經寫好,我本來直接複製貼上到原本的 Github 之中,部署完後發現,不是我的程式,才發現需要自己改一下裡面的 repo 位置。

services:
- type: web
name: line-bot-python-flask
env: python
repo: https://github.com/line/line-bot-sdk-python.git
buildCommand: cd examples/flask-echo;pip install gunicorn -r requirements.txt
startCommand: cd examples/flask-echo;gunicorn app:app

針對 buildCommandstartCommand 這列的部分,不太需要做太大的修改,畢竟目前大部分的 LINE Bot 應該都是透過 app.py(以 Python 開發為例),前面使用的資料夾名稱,也不會影響。

所有的 Webhook 都還是指向 https://xxx.onrender.com/callback,並不會因位採用哪個資料夾就會有影響,我自己試過如果加上資料夾的名稱在 callback 前面,反而是會變成 404 找不到。

二、需要移除 gunicorn

之前在部署 Heroku 的時候 requirement.txt 有增加 gunicorn 需求,但我看到好幾次部署都不成功,持續顯示錯誤訊息就中止部署。

Render 部署的時候出現錯誤訊息
Render 部署的時候出現錯誤訊息

我就回去看了一下原始碼,發現原來我們已經在 yaml 檔案中呼叫過 gunicorn 了,所以才會反覆地出現 Double requirment given: gunicorn==… 的錯誤訊息。

當我刪除了 requirement.txt 裡面的 gunicorn 字詞後,程序就能正常部署了。

三、LINE BOT API 更新

這個程式我蠻早就已經寫好了,一直都沒有更新過了, 今天卻發現再怎麼不屬都出現錯誤的訊息。

持續顯示的錯誤訊息
持續顯示的錯誤訊息

我大概就在這邊卡了半個小時,不斷地修改、重新部署,都遇到一樣的問題。上網查了一下,發現 Stackoverflow 上有人提出類似的問題。靈機一動,回去察看一下原始檔案,發現原來 LINE API(Messaging API SDKs) 好像更新了。

參考了 LINE 的範本發現 TOKEN 汲取的方式好像跟之前有點不一樣,把下面這一段複製後,覆蓋貼上原本的 channel_secretchannel_access_token 重新部署,就成功了!

# get channel_secret and channel_access_token from your environment variable
channel_secret = os.getenv('LINE_CHANNEL_SECRET', None)
channel_access_token = os.getenv('LINE_CHANNEL_ACCESS_TOKEN', None)
if channel_secret is None:
print('Specify LINE_CHANNEL_SECRET as environment variable.')
sys.exit(1)
if channel_access_token is None:
print('Specify LINE_CHANNEL_ACCESS_TOKEN as environment variable.')
sys.exit(1)
line_bot_api = LineBotApi(channel_access_token)
parser = WebhookParser(channel_secret)

經過兩個小時的研究,到這邊可以算是正式部署完成。

當然因為是免費的服務1,還是有幾個功能上面的限制

  1. 執行時間上線為每個月 750 小時;
  2. 程序會有待命(inactive),再次喚醒最長需要等待 30 秒;
  3. 如果使用 PostgreSQL Databases,最多資料存放時間為 90 天。

不過依照目前的使用情況,要逾越上面的限制,勢必是有一個很重大的進展,到時候當然付款就會成為一個選項。

整體來說,到現在大概一天的時間,使用起來因為是免費的服務,滿意度甚高。

2022-10-14 更新

昨天早上在使用自己 LINE Bot 時,發現沒有收到任何的系統回應,本來以為是因為免費方案會有 Delay 的時間,然而等了很久都沒有成功,遂即進入 Render 的 Dashbaord 查看。忽然發現有個 Server unhealthy 的警示訊息。

忽然出現的錯誤訊息
Render 忽然出現的錯誤訊息

在部署完後,我並沒有更動程式, 也沒有再重新的部署,邊疑惑邊上網尋找相關的訊息,發現也有不少人遇到相同情況,一部份解釋是程序問題,跟我寫信之後 Render Support 回信的情況一致。

不過在官方的社群論壇裡面,剛好找到一篇解答,針對類似的情況 Render 官方人員的回應如下:

This is due to the fact that free tier services run on a machine type that can be restarted on short notice. This doesn’t impact most free services because they usually spin down and get scheduled on newer machines. It appears that your free service is almost always up, so it rarely gets rescheduled and will get restarted more regularly as a result of the machine restarts more regularly.

看起來也是針對免費的使用者才會發生的情況,我認為也算是一種限制,可能會無預警的進行主機維護或者重開機。想來可能是因為怕有人持續佔用資源太久,重開機可以幫助記憶體的釋放。

  1. 詳細內容請參考 Free Plans | Render · Cloud Hosting for Developers

Some rights reserved
Except where otherwise noted, content on this page is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International license.