使用Heroku上的Python来连接Redis,在Mac开发环境中

由于 Redis to Go 被移除作为附加功能,我一度感到困惑,但终于解决了,现在作为备忘录公开。

这里写了什么内容?

    • Heroku上のPythonからHeroku Data for Redisを使うための方法が書いてある

 

    Macのローカルで同じ環境を実現して開発する方法が書いてある

我们走吧 ba)

如果您想要在Heroku的Python中处理后台任务,官方文档在这里。

 

然而,这是 Redis to Go 存在于附加组件中的信息,因为有些细节可能已经改变,所以需要查看英文版。

 

并且,在worker.py文件中这样写,但是,如果只是这样写的话,它不会运行。

redis_url = os.getenv('REDIS_URL', 'redis://localhost:6379')

conn = redis.from_url(redis_url)

当使用Heroku Data for Redis服务的hobby计划时没有问题,但一旦付费后就会突然停止运行。
原因是因为需要使用TLS。
有关此问题的详细信息请参考此处。

 

import os
from urllib.parse import urlparse
import redis

url = urlparse(os.environ.get("REDIS_URL"))
r = redis.Redis(host=url.hostname, port=url.port, username=url.username, password=url.password, ssl=True, ssl_cert_reqs=None)

然后,不知何故,它就无法运行了。根据urlparse,端口无法正确识别。很奇怪。
因此,最终我将主机、端口和密码放入环境变量中。
以上的原因是因为用户名被包含在内。
通过添加Heroku Data for Redis并查看其URL,可以发现用户名并不存在。
因此,正确的方法是按以下方式进行设置。原本是将主机、密码和端口分别放入环境变量中并使用它们,但是Heroku Data for Redis会定期更改URL。在更改的时候,它就无法使用了,所以我们应该按以下方式进行配置。

2023年1月12日追記:已将修正内容应用于文档页面,
https://devcenter.heroku.com/articles/connecting-heroku-redis#connecting-in-python

import os
import redis
from urllib.parse import urlparse

from rq import Worker, Queue, Connection
import logging
logger = logging.getLogger(__name__)

listen = ["events", 'cursor', 'high', 'default', 'low']

if os.environ.get("ENV") != 'production':
    print("development")
    conn = redis.Redis(host='localhost', port=6379, db=0)
else:
    url = urlparse(os.environ.get("REDIS_URL"))
    conn = redis.Redis(
        host=url.hostname,
        port=url.port,
        password=url.password,
        ssl=True,
        ssl_cert_reqs=None
        )


if __name__ == '__main__':
    with Connection(conn):
        print("worker start")
        worker = Worker(map(Queue, listen))
        worker.work()

将这些内容存入Heroku的环境变量中。

export REDIS_HOST=hostのURL
export REDIS_PORT=REDISのポート番号
export REDIS_PASS=REDISのパスワード

只有在环境变量”ENV”不等于”production”时,才会执行此分支。在Mac上安装Redis后,在终端中输入”$ redis-server”即可启动Redis。如果要连接到这里,可以将环境变量”ENV”设置为”local”,然后使用conn = redis.Redis(host=’localhost’, port=6379, db=0)来连接到本地的Redis。

关于工人

将创建的worker.py放在根目录中。
在ProcFile中写成这样。

worker: python ./worker.py

其实,我一直在按照这里所写的方式为Slack开发应用程序。

 

在这个架构中,使用Python运行的部分被放置在/backend/文件夹下。worker.py也被按照规定的方式放置在/backend/worker.py中。而在ProcFile中,

worker: python ./backend/worker.py

我写的是这样的,但是这样做无法通过路径。将工作程序放在文档根目录中。如果不这样做,工作程序调用函数的路径会出错,无法执行。

我想使用两种类型的工人。

存在着两个处理方式不同的后台任务,其中一个任务较为繁重但不常被使用,而另一个任务需要持续运行,因此不想对其造成影响,所以我们决定设置两个工作人员来处理。
一开始尝试只用一个工作人员,但当运行繁重的任务时,需要持续运行的任务停止了。因此我们决定将它们分开处理。

    • workerのファイルをコピーして若干変更

 

    Redisももう一つadd on追加して2つ起動するように変更
import os
import redis
from urllib.parse import urlparse

from rq import Worker, Queue, Connection
import logging
logger = logging.getLogger(__name__)

listen = ["events", 'cursor', 'high', 'default', 'low']

if os.environ.get("ENV") != 'production':
    print("development")
    conn_c = redis.Redis(host='localhost', port=6379, db=0)
else:
    url = urlparse(os.environ.get(os.environ.get("REDIS_COLLECTOR_KEY")))
    conn_c = redis.Redis(
        host=url.hostname,
        port=url.port,
        password=url.password,
        ssl=True,
        ssl_cert_reqs=None
        )

if __name__ == '__main__':
    with Connection(conn_c):
        worker = Worker(map(Queue, listen))
        worker.work()

几乎一样,但我将Redis的连接地址更改为另一个。我会添加环境变量。

    • REDIS_C_HOST

 

    • REDIS_C_PORT

 

    REDIS_C_PASS

我还在ProcFile中添加了一行。

worker: python ./worker.py
collect: python ./workerc.py

在Python中调用的形式如下

from rq import Queue
from worker import conn
from workerc import conn_c
from .collect import start_collect
q = Queue(connection=conn,default_timeout=100)
c = Queue(connection=conn_c,default_timeout=1000000000)
@bolt_app.view("collect_past_posts_submit")
def collect_past_posts_submit(ack, body, logger, client, view, context):
    ack()
    result = c.enqueue(start_collect, body['team']['id'], context['user_id'])

@bolt_app.event("message")
def handle_message_events(client, body, logger, context):
    user_id = context['user_id']
    try:
        userinfo = client.users_info(
            user=user_id,
            include_locale=True
        )
    except SlackApiError as e:
        print("Error fetching conversations: {}".format(e))
    post = q.enqueue(handleMessage,client,body,context,logger,userinfo,job_timeout=36000)

def handleMessage(client,body,context,logger,userinfo):
    print('handle_message_events ■□■□■□■□■□■□■□■□■□■□■□')
    #何かしらの処理----

由于我没有调查启动两个本地Redis的方法,所以如果你想在本地创建相同的环境,你需要再多做一些研究。
如果尝试将两个worker连接到同一个Redis上,处理过程可能无法分离,但我认为这对于验证而言并不成问题。

要查看Heroku的worker日志需要怎么做?

您可以使用以下命令查看

以下是对提供的英文句子的中文翻译:
第一个是以ProcFile中指定的worker调用形式执行的命令:heroku logs -t -d worker -a 应用名称。

第二个是以ProcFile中指定的collect调用形式执行的命令:heroku logs -t -d collect -a 应用名称。

使用以下命令查看应用程序的所有动态进程日志:
heroku logs -t -a 应用程序名称
为了确认处理是否正确传递到指定的工作进程,请添加 -d 选项以查看工作进程日志。

需要从控制台进行连接。

使用以下命令连接到Heroku Redis:

heroku redis:cli -a 应用名称

如果一个应用关联了多个REDIS实例,使用以上命令将无法连接。在添加REDIS时,需要指定连接名称,所以我们需要使用以下命令访问:

heroku redis:cli -a 应用名称 HEROKU_REDIS_xxxx

登录到Redis并开始操作

要确认key

你可以用这个来查看所有的键。

如果要删除密钥

清空数据库

获取未设置TTL的键

> 查看键空间信息

以上

介绍正在开发的Slack应用。

如果您方便的话,请安装并尝试使用一下!使用这个TIPS的是TimeLine。

    • TASUKARU-TaskALL- https://lne.st/3x1u

TimeLine for Slack https://lne.st/wr21

OYASUMI bot https://lne.st/oyasumilink

TIPS https://lne.st/tips

YOKOKU for Slack https://lne.st/4cdy

给予援助

你是否在Slack上收到很多人的提及而感到困惑?可能你记得应该有人请求你做某事,但又想不起来了……我们来为你解救。TASUKARU是专门为Slack设计的任务管理工具。在默认的讨论和提及页面上,你无法将已处理完的帖子存档,但是使用TASUKARU就可以做到。你可以将注意力集中在需要行动的事项上,这就是TASUKARU的优势。\nhttps://lne.st/3x1u

Slack的时间线

这个应用程序可以创建一个时间线频道,将所有公开频道的帖子汇总到一个频道中。
通过创建一个混合频道,只包括所需的频道,您可以生成只包含自己需要的时间线。
作为可选功能,您可以在消息转发时使用DeepL翻译。

晚安机器人

如果Google日历的日程中包含“休假”等休假判定关键词,则自动将Slack设置为静音状态。
如果有提及,将在提及的对方处添加一条回复,告知对方今天是休假日。
这是一个旨在让员工度过愉快假期的应用程序。https://lne.st/oyasumilink

小费

这是一个专为Slack设计的提醒应用程序。
默认的提醒功能只能设置单个消息到一个日程安排中。
而这个应用程序可以在一个日程安排中注册多个消息,并在随机的时间发布。
通过在频道特定的日程安排中注册相关的知识或技巧,可以自然地传播信息。

Slack的预告

以下是对 OYASUMI bot 的应用进行的本地化汉语解释的一个选项:

你是否想过要提取只包含关键词“営業”的日程安排?
每次都要去搜索日历很麻烦。
通过使用这个应用程序,你可以将包含特定关键词的日程安排传送到特定的频道中。https://lne.st/4cdy

bannerAds