toniq, 简单可靠的Elixir机后台作业处理库

分享于 

16分钟阅读

GitHub

  繁體 雙語
Simple and reliable background job library for Elixir, previously known as "exqueue"
  • 源代码名称:toniq
  • 源代码网址:http://www.github.com/joakimk/toniq
  • toniq源代码文档
  • toniq源代码下载
  • Git URL:
    git://www.github.com/joakimk/toniq.git
    Git Clone代码到本地:
    git clone http://www.github.com/joakimk/toniq
    Subversion代码到本地:
    $ svn co --depth empty http://www.github.com/joakimk/toniq
    Checked out revision 1.
    $ cd repo
    $ svn up trunk
    
    Toniq

    简单可靠的Elixir 工作流程库。

    asciicast

    • 重点是易于使用和处理错误。
    • 将自动重试失败的作业数次。
    • 它实际上对并发作业没有任何限制。
    • 可以使用最大并发选项限制并发性。
    • 将参数传递给工作线程,与排队时完全一样,没有JSON转换。
    • 在运行工作的一边失败,而不是在任何时候。 在下面查看更多内容。
    • 可以在诸如Heroku这样的有限环境下工作,这样你就不能直接连接多个Erlang节点或者执行热代码更新。
    • 使用redis持久化作业,但代价不是 resque/sidekiq兼容。
      • 如果你需要的话,我建议你看一下 Exq。
      • 你可以在同一应用程序中同时运行Exq和 Toniq,以获得不同的工作人员。

    如果关于这个库是如何工作或者错误消息意味着 anything问题( 或者请求请求) 请 file

    - -

    状态: 相对新。 从 1.0 (,2015 ) 开始使用了很多应用程序。 如果你喜欢,ping @joakimk 关于如何使用和应用程序的大小/类型的信息。

    安装

    在 mix.exs file: 中添加为依赖项

    defpdepsdo [
     {:exredis, ">= 0.2.4"},
     {:toniq, "~> 1.0"}
     ]end

    然后运行:

     
    mix deps.get
    
    
    
     

    然后在 mix.exs. 中的应用程序列表中添加 :toniq

    在不同的环境中配置 toniq:

    config :toniq, redis_url:"redis://localhost:6379/0"# config :toniq, redis_url: System.get_env("REDIS_PROVIDER")

    如果有多个应用程序使用相同的redis服务器,那么也不要忘记配置 redis_key_prefix

    动态 redis-url

    如果需要在应用程序启动后动态配置 redis,则可以使用 redis_url_provider 阻止,直到redis_url可用。

    config :toniq, redis_url_provider:fn-> wait_for_redis_url_to_be_available end

    用法

    定义工作线程:

    defmoduleSendEmailWorkerdouseToniq.Workerdefperform(to: to, subject: subject, body: body) do# do workendend

    在应用程序代码中的某个位置进行排序:

    Toniq.enqueue(SendEmailWorker, to:"info@example.com", subject:"Hello", body:"Hello, there!")

    管道

    你还可以使用如下所示的|> 对作业进行排序:

    email = [to:"info@example.com", subject:"Hello", body:"Hello, there!"]
    email|>Toniq.enqueue_to(SendEmailWorker)

    延迟作业

    和延迟作业。

    email = [to:"info@example.com", subject:"Hello", body:"Hello, there!"]# Using enqueue_to:email|>Toniq.enqueue_to(SendEmailWorker, delay_for:1000)# Using enqueue_with_delay:Toniq.enqueue_with_delay(SendEmailWorker, email, delay_for:1000)

    Pattern 匹配

    你可以在工作中 Pattern MATCH。 可以用于清理代码,或者处理来自同一工作线程以前版本的数据 !

    defmoduleSendMessageWorkerdouseToniq.Workerdefperform(message:"", receipient: _receipient) do# don't send empty messagesenddefperform(message: message, receipient: receipient) doSomeMessageService.send(message, receipient)
     endend

    限制并发

    对于某些工人,你可能希望限制同时运行的作业数。 例如如果调用一个 API,最多可能不需要超过 3个连接。

    可以通过在工作表上指定 max_concurrency 选项来设置这里选项。

    defmoduleRegisterInvoiceWorkerdouseToniq.Worker, max_concurrency:10defperform(attributes) do# do workendend

    正在重试失败的作业

    计划了一个管理网络界面,但是在那之前,( 那之后) 可以使用控制台。

    正在重试所有失败的作业:

    iex -S mix
    iex>Toniq.failed_jobs |>Enum.each &Toniq.retry/1

    一次重试一个:

    iex> job =Toniq.failed_jobs |> hd
    iex>Toniq.retry(job)

    或者删除失败的作业:

    iex> job =Toniq.failed_jobs |> hd
    iex>Toniq.delete(job)

    自动重试

    作业失败时自动重试。 可以自定义,甚至通过配置 toniq ( 记住,系统崩溃仍然会导致一个作业在某些情况下运行多次,即使重试已经禁用)的重试策略来禁用。

    默认策略是 ,它将在初始运行时重试作业 5次,并且每次运行时都会增加延迟。 延迟大约为 250毫秒,1秒,20秒,1分钟和 2.5分钟。 在作业标记为失败之前,( + 6 x 作业运行时间)的总时间大约 4分钟。

    另一种方法是 Toniq.RetryWithoutDelayStrategy,它只会在不延迟的情况下重试两次。

    config :toniq, retry_strategy:Toniq.RetryWithoutDelayStrategy# config :toniq, retry_strategy: YourCustomStrategy

    负载平衡

    由于toniq只运行队列中的作业,如果想要在不同的VM中并发运行更多的作业,则取决于。

    如果web服务器在每个web服务器中排队作业,那么这可以能非常简单。

    或者,你可以使用 Toniq.JobImporter 插件将作业传递给随机 VM。 因为作为轮询系统,它有一点延迟。

    identifier =Toniq.KeepalivePersistence.registered_vms |>Enum.shuffle |> hdToniq.JobPersistence.store_incoming_job(Toniq.TestWorker, [], identifier)

    旨在避免复杂性

    使用redis作为消息队列不同,toniq使用它来备份。

    作业在虚拟机所在的虚拟机中运行。 如果虚拟机停止或者崩溃,在另一个虚拟机运行后,将从redis恢复未处理的作业。

    通过在同一个VM内运行作业,我们不必在redis中使用任何锁。 锁定是一个复杂的主题,很难找到。 Toniq应该是简单可靠的,所以我们要避免锁定 !

    请求反馈请求

    我想知道如何使用这个工具为你工作。 有什么问题从文档中很难理解的东西? 你在什么范围内运行作业? 效果不错比以前用的好? 缺少一些你习惯的特性?

    Ping @joakimk 或者打开一个问题。

    常见问题解答

    :为什么所有的作业队列都有

    • 不需要同步运行代码。 比如 在发送电子邮件时不会延迟网络响应。
    • 你不必为作业队列可以处理的事情编写自定义代码。
    • 你得到持久性。重试。故障转移。并发限制等。

    将按顺序运行作业?

    这是一个first-in-first-out队列,但由于重试和并发,无法保证排序。

    :在redis中存储时,作业如何序列化

    作业是使用 erlang序列化插件进行序列化的。 它与分布式节点通信时使用的格式相同。 这意味着你几乎可以把任何东西传递给作业。

    如果序列化格式更改会发生什么?

    有一些代码可以自动迁移到的旧版本。

    如果一个 Erlang VM在它的队列中停止处理,那么这些作业是如何处理的?

    一个 Erlang VM运行后,它就会找到redis中的作业,将它的移动到自己的队列中并运行它们。 在这种情况发生之前可能需要一些时间,这样原始的VM就有机会报告并保留它的工作。

    为什么作业会在少数情况下运行一次?

    如果发生意外事件,并且作业在运行后不能标记为完成,则这里库更喜欢运行两次( 或者更多)。

    意外的事情包括杀死 at,作业 runner 中的意外崩溃,或者在错误的时间内连接到tftp连接。

    你可以通过两种方式解决这里问题:

    • 使用流程:使你的作业可以在没有任何错误的sideeffects的情况下运行多次。 也称为重入。
    • 实现你自己的锁定,或者将一些这样的东西贡献给这个库。

    我倾向于在任何可能的情况下首选。

    如何运行计划作业或者定期作业?

    还没有构建支持,但是你可以使用像 https://github.com/c-rack/quantum-elixir 这样的工具来调度toniq作业。

    config :quantum, cron: [# Every 15 minutes"*/15 * * * *": fn->Toniq.enqueue(SomeWorker) end]

    注释

    这里项目使用 mix format 格式化代码。 在进行更改时确保运行。 一种简单的方法是在保存时让编辑器插件运行它。

    版本控制

    这里库使用 semver 进行版本控制。 API在相同的主要版本中不会以不兼容的方式改变,等等 在 mix.exs 中指定。

    Credits

    演示功能 toniq

    • 2015
      • 在斯德哥尔摩 Elixir"十月 talkfest"演示: 幻灯片

    • 请求请求:
      • 非常欢迎:)
      • 应该有测试
      • 应该具有符合项目风格的重构代码( 最好是这样做)
      • 应该有更新的文档
      • 应该实现或者修复对这个库有意义的东西( 如果你不确定的话,请随意询问)。
      • 仅在满足上述所有条件时才合并。 我一般不会修正你的代码但我会给你反馈。
    • 如果这个项目变得太不活跃了,可以自由地询问作为维护者。

    插件开发

    
    mix deps.get
    
    
    mix test
    
    
    
    

    在开发时,可以使用 mix test.watch --stale 在保存文件时运行测试。

    你还可以使用 Toniq.TestWorker 在开发中尝试 toniq。

    
    iex -S mix
    
    
    iex> Toniq.enqueue(Toniq.TestWorker)
    
    
    iex> Toniq.enqueue(Toniq.TestWorker, :fail_once)
    
    
    
    

    待办事项和 1.0后的想法

    • 处理和/或者帮助其他人处理github问题
    • 查看延迟作业是否可以使用incomming作业导入,这样就不需要 reload_job_list
    • 以更标准的方式报告错误,请参阅 honeybadger-elixir#30 讨论。
    • 说明如何使用Toniq测试应用程序。 比如 使用 toniq。jobevent。订阅服务器等。
    • 管理用户界面( 空闲,正在由 kimfransman 工作)
      • 显示等待和失败的作业
      • 使数据easiliy可以在使用toniq的应用程序中显示
      • 存储/显示创建时间
      • 存储/显示重试次数
      • 可能:针对当前工作状态的JSON API
      • 可能:Webhook推送作业统计信息
    • 一个简单的网页,而不是在 http://toniq.elixir.pm 重定向。
      • 一个使用toniq定期调度工作的凤凰应用程序和触发工作的方法将有趣。 如果管理界面存在,那么你可以看到它们运行。重试等。
    • 自述文件中的文档 JobEvent
    • 添加 CI
      • 在R17中运行测试,因为人们仍然使用
    • 当作业需要"太长"运行时记录错误,设置一个合理的默认值
      • 没有检测到这导致了其他应用程序的生产问题。 一个警告很容易做,而且可以帮助很多人。
    • perform 上数量 Bug的错误比较好,因为它是通用的。 列表需要排序,如果是列表,使用户知道该列表,等等。
    • 能够跳过持久性
    • 简单的基准测试,看看它在不同模式下是否
      • 以微秒为单位编写作业时间?
      • 基准unpersisted作业
      • 基准持久化许多作业( 100k+ )
      • 测试许多长期运行的作业
      • 优化位
      • sidekiq和/或者exq的比较基准?
    • 测试RedisConnection显示好的错误消息
    • 更多日志记录
    • 考虑在测试中不同地启动toniq以更好地隔离单元测试
    • 每个工作线程自定义重试 stategies
    • 根据每个工作人员或者每个排队的基础支持不同的排队策略
      • 延迟持久性:更快,立即运行作业,并将作业保持在同一时间。 如果虚拟机停止,你可能会有一个要恢复的作业列表。
      • 无持久性:最快,立即运行作业。 如果虚拟机停止工作,作业可能会丢失。
    • 为作业( 如果有人需要它) 添加超时。 应该相当简单。
    • 查看使用 exactor 清理代码。
    • 查看使用 redix。 本地 elixir redis。 探索错误处理和 usabillity。 基准。

    许可证

    MIT许可证

    若要在取得该软件副本时免费授予任何人,如有下列条件的软件,请免费授予该软件的副本,并与相关的文档文件("软件") 进行许可,包括不受限制的权利,包括以下条件:

    上述版权声明和本许可声明须包括在所有的副本或实质性部分的软件。

    软件是"是",没有任何保证,表示或者隐含,包括但不限于销售,适合特定用途和 NONINFRINGEMENT。 作者或者版权持有人在合同。侵权或者它的他与软件或者它的他用户交易的行为。


    PROC  REL  后台  job  Elixir  
    相关文章