【发布时间】:2018-10-08 22:51:05
【问题描述】:
我在控制器中有一个发送大量文本消息的功能。(1000 条消息) 控制器功能看起来像这样..
def send_sms(conn, _params) do
// code is abbreviated
# Spawn new process for sending message and saving to database
spawn(fn -> send_message_and_save(user, recipients, phone_numbers) end)
// code is abbreviated
end
还有这个功能
def send_message_and_save(user, recipients, phone_numbers) do
// code is abbreviated
results = Sms.send_sms_with_messaging_service_async(phone_numbers, recipients.message, msg_sid, status_callback, account, token)
case Sales.confirm_order(recipients, attrs) do
{:ok, %{id: order_id, user_id: user_id}} ->
Messenger.create_message_status(results, order_id, user_id)
# Update Bitly status as Saved
if is_nil(recipients.bitly_id) do
else
bitly = Texting.Bitly.get_bitly_by_id(recipients.bitly_id)
Bitly.confirm_changeset(bitly) |> Bitly.update()
end
{:ok, "Message sent successfully. Your analytics data will be updated shortly."}
{:error, _changeset} ->
{:error, "Can't send message!"}
end
end
在 send_message_and_save 函数中的作业过程是这样的 1.使用外部api请求发送1000条消息。 - 我使用 Task.Supervisor.async_stream/6 做到了这一点 2. confrim_order(将订单模式标记为“已确认”状态并更新(update) 3. create_message_status(创建操作) 4.get_bitly_by_id(获取操作) 5. Bitly.confirm_changeset 和 Bitly.update(更新操作)
在此过程中,总共将发生 5000 次数据库操作。 并且在向外部 api 请求发出请求后,对于每个外部 api 请求,我的网络服务器都会有三个状态回调请求。 这意味着,发送 1000 条消息将对 message_status 架构进行 300 万次更新操作(接受、已交付或未交付)。
所以发送 1000 条消息将结束 8000 次数据库操作,我在此尝试过,我的网站变得缓慢,并且由于超时而丢失了对我的网站的一些状态回调请求(外部 api 说“连接超时的原因有很多发生;常见原因是长时间运行的数据库查询或外部进程以及对外部系统的调用需要很长时间才能返回")
那么我该如何改善这种情况呢?我怎样才能正确设计这个? 请帮忙:(
【问题讨论】:
-
你使用
poolboy创建db连接池了吗? -
使用像
rabbitmq这样的mq来做这个工作怎么样? -
一些数据库支持批量插入,这非常有用。您可以使用 poolboy 或管理您自己的数据库连接池,这样您就不会只使用一个连接。如果它是一个 http api,您仍然可以使用一个池或为每次写入/读取生成一个新进程。
标签: concurrency elixir phoenix-framework ecto