天天看点

高性能NIFI设置

NiFi团队发表了一篇关于如何提高NIFI最佳性能的文章。

https://community.hortonworks.com/articles/7882/hdfnifi-best-practices-for-setting-up-a-high-perfo.html

解决方案

HDF最佳实践指南,用于配置系统和NiFi以实现高性能数据流。

        NiFi可以实现极少配置的开箱即用,只需编辑位于conf目录中的nifi.properties文件,添加一个敏感的props属性(用于编码流中的所有敏感属性),就可以开始了。这可能会让您启动并运行,但这种基本配置远非理想的高容量/高性能数据流。虽然NiFi核心本身在内存,磁盘/网络I/O或CPU方面对系统没有太大影响,但是你构建的数据流可能会对这些性能指标产生相当大的影响。一些NiFi处理器可能是CPU,I/O或内存密集型。事实上,一些处理器可能在这三个方面都是密集的。我们已尝试在处理器文档中确定处理器是否在任何这些方面是密集(可通过单击NiFi UI右上角的“帮助”或右键单击实例并选择“使用”来找到处理器文档) 本指南不打算介绍如何优化数据流设计或如何微调各个processor。

       在本指南中,我们将重点关注应用程序本身的初始设置,并通过更改一些现成的默认值来关注可以提高性能的方面。我们将仔细研究nifi.properties和bootstrap.conf文件中的许多属性。我们将指出应该从其默认值更改的属性以及更改这些属性将获得什么。有关我们未在本指南中介绍的属性,请参阅管理员指南。

        在我们深入研究这两个配置文件之前,先对NiFi做一下了解。NiFi是一个Java应用程序,因此在JVM中运行,但这不是全部的内容。该应用程序有许多存储库,每个存储库都有自己非常具体的功能。database repository 跟踪了用户通过UI对数据流所做的所有更改。flowfile repository 包含了有关在使用NiFi UI构建的数据流中处理的每个flowfile 的所有flowfile 属性。这是最重要的存储库之一。如果它损坏或磁盘空间不足,flowfile 的状态可能会丢失(本指南将介绍帮助避免这种情况发生的方法)。此存储库包含flowfile当前位于数据流中的位置信息,指向content repository库中内容位置的指针,以及与内容关联或派生的任何FlowFile属性。正是这个存储库允许NiFi在应用程序重新启动时从中断处拾取(想想意外的断电,无意的用户/软件重启或升级)。

       content repository是NiFi正在处理的文件的所有实际内容所在的地方。 如果已启用数据存档,也可以保存多个历史版本的内容。 根据用户构造的数据流类型,此存储库可能I / O非常密集。最后,我们有了起源库,它可以跟踪当前和过去FlowFiles的谱系。 通过使用原始UI,可以在数据流路径的多个点上下载,重放,跟踪和评估数据。 只有在内容存储库中仍存在内容副本时,才能下载和重播。与任何应用程序一样,整体性能取决于其各个组件的性能。 因此,我们将专注于在本指南中充分利用这些组件。最后我们说provenance repository, 它可以跟踪当前和过去FlowFiles的血缘。

        通过使用provenance UI,可以在数据流路径的多个点上下载,重放,跟踪和评估数据。只有在content repository中仍存在内容副本时,才能下载和重播。 与任何应用程序一样,整体性能取决于其各个组件的性能。

       因此,在本指南中我们将专注于充分利用这些组件。

      nifi.properties file:

      我们将首先查看位于NiFi安装的conf目录中的nifi.properties文件。 该文件分为几个部分(核心属性,状态管理,H2设置,flowfile repository,内容存储库,Provenance存储库,组件状态存储库,站点到站点属性,Web属性,安全属性和群集属性)。 构成每个部分的各种属性都预先配置了默认值。

      # Core Properties #:

高性能NIFI设置

       本节中只有一个属性对NiFi和性能有影响。      

       nifi.bored.yield.duration=10 millis

       此属性是用来通过阻止一些processor(在使用timer driven调度策略时)在未运行时使用过多的cpu来提高CPU利用率,默认的10毫秒值已经对降低CPU利用率产生了巨大影响。较小的值等同于较低的延迟,但CPU利用率较高。 因此,根据延迟对整体数据流的重要程度,增加此处的值将进一步降低整体CPU利用率。本节中还有另一个属性可以更改。 它对NiFi性能没有影响,但可能会影响浏览器性能。

      nifi.ui.autorefresh.interval=30 sec

     此属性设置将刷新的最新统计信息,公告和流修订推送到已连接的浏览器会话。 为了重新加载完整的数据流,用户必须触发刷新。 减少刷新之间的时间将允许公告以更及时的方式呈现给用户; 但是,这样做会增加使用的网络带宽。 访问UI的并发用户数量使此更加复杂。 我们建议保留默认值,只有在需要更接近实时公告或UI中的统计报告时才更改默认值。 用户可以随时通过右键单击图表上的任何空白区域并选择“刷新状态”来手动触发刷新。

      # H2 Settings

高性能NIFI设置

     用户数据库(在NiFi配置为安全时跟踪用户登录)和历史数据库(跟踪图表上所做的所有更改)保持相对较小并且需要非常少的硬盘空间。<root-level-nifi-dir> / database_repository的默认安装路径将造成在NiFi安装的根级别创建目录(与conf,bin,lib等目录相同)。 虽然通过将其移动到新位置几乎没有性能提升,但我们建议将所有存储库移动到NiFi安装目录之外的位置。 用户或历史数据库不太可能在NiFi版本之间进行更改,因此将其移出基本安装路径可以简化升级; 允许您在升级后保留用户和组件历史信息。

     # FlowFile Repository

高性能NIFI设置

      这是迄今为止NiFi中最重要的存储库。 它维护当前位于NiFi UI上数据流中任何位置的所有FlowFile的状态。 如果它挂掉了,则可能导致您无法访问NiFi当前正在处理的部分或全部文件的情况。挂掉最常见的原因是磁盘空间不足。 默认配置的存储库位于<root-level-nifi-dir> / flowfile_repository中。

      nifi.flowfile.repository.directory=./flowfile_repository

      出于与database repository相同的原因,我们建议将此存储库移出基本安装路径。您还应该将FlowFile存储库放在磁盘(最好是高性能RAID)上,而不与其他高I/O软件共享。在高性能系统上,如果可能的话,FlowFile存储库绝不应与 content repository或provenance repository位于同一硬盘/ RAID上。

      NiFi不会将物理文件(内容)从处理器移动到处理器,FlowFiles充当从一个处理器到下一个处理器的传输单元。 为了尽可能快地实现这一点,FlowFiles存在于JVM内存中。这是不错的直到你的系统中有这么多FlowFiles,你开始耗尽JVM内存并且性能急剧下降。 为了降低发生这种情况的可能性,NiFi有一个阈值,用于定义在换出磁盘之前,单个连接队列中可以存储多少个FlowFiles。Connection在UI中表示为将两个处理器连接在一起的箭头。 FlowFiles可以在等待后续处理器的同时在这些Connection上排队。

     nifi.queue.swap.threshold=20000

     如果任何one-Connection队列中的总FlowFiles数超过此值,则将发生交换。 根据发生的交换次数,可能会影响性能。 如果具有超过20,000个FlowFiles的队列是常态,而不是偶尔的数据流量,那么增加此值可能是明智之举。 您需要密切监视堆内存使用情况并增加它以处理这些较大的队列。 堆大小在bootstrap.conf文件中设置,稍后将对此进行讨论。

    # Content Repository

高性能NIFI设置

      由于NiFi消费的每个FlowFile的内容(由NiFi摄取的物理文件)都放在 content repository中,因此加载此存储库的硬盘将在处理高数据的系统上遇到高I / O。 如您所见,默认情况下,NiFi安装路径中会创建存储库。

      nifi.content.repository.directory.default=./content_repository

      应将content repository移动到其自己的硬盘/ RAID。 有时甚至只有一个专用的高性能RAID是不够的。NiFi允许您在单个NiFi实例中配置多个content repository。 不管定义了多少content repository,nifi将轮询文件。

       设置其他content repository很容易。 首先删除或注释掉上面的行,然后为要添加的每个content repository添加一个新行。 对于每个新行,您需要将“default”更改为其他一些唯一值: 

      nifi.content.repository.directory.contS1R1=/cont-repo1/content_repository

      nifi.content.repository.directory.contS1R2=/cont-repo2/content_repository

      nifi.content.repository.directory.contS1R3=/cont-repo3/content_repository 

      在上面的示例中,您可以看到默认值已更改为contS1R1,contS1R2和contS1R3。 'S'代表System,'R'代表Repo。 用户可以使用他们喜欢的任何名称,只要它们彼此独特即可。 使用上面的示例,每个硬盘/ RAID将映射到/cont-repo1,/cont-repo2或/cont-repo3。 跨多个磁盘的I / O负载划分可以在发生故障时显着提高性能和耐用性。

      在NiFi群集中,每个节点都可以配置为对其各种存储库使用相同的名称,但建议使用不同的名称。 它可以在NiFi UI中更轻松地监控群集中的repo磁盘利用率。 具有相同名称的多个存储库将在系统诊断窗口下汇总在一起。 因此,在群集中,您可以使用contS2R1,contS2R2,contS3R1,contS3R2等。

     # Provenance Repository 

高性能NIFI设置

      与content repository类似,provenance repository可能使用大量磁盘I / O来编写和读取provenance 事件,因为整个数据流中的每个事务都会影响FlowFile或内容创建provenance 事件。UI不限制可以对provenance repository进行同时查询的用户数。I / O随着发生的并发查询数量的增加而增加。 默认配置在NiFi安装路径中创建了provenance repository,就像其他存储库一样。

      nifi.provenance.repository.directory.default=./provenance_repository

      建议provenance repository也位于其自己的硬盘/ RAID上,并且不与任何其他存储库(database,FlowFile或content)共享其磁盘。 就像content repository一样,可以通过提供唯一名称来代替“default”和路径来定义多个来源存储库。    

      nifi.provenance.repository.directory.provS1R1=/prov-repo1/provenance_repository

      nifi.provenance.repository.directory.provS1R2=/prov-repo2/provenance_repository

     在上面的示例中,您可以看到默认值已更改为provS1R1和provS1R2。 'S'代表System,'R'代表Repo。 用户可以使用他们喜欢的任何名称,只要它们彼此独特即可。 使用上面的示例,每个硬盘/ RAID将映射到/prov-repo1或/prov-repo2。 跨处理多个磁盘的I / O负载划分可以显着提高性能,并在处理大量原始数据时出现故障,从而有限的持久性。

     查询文件的出处信息的能力对于各种用户具有很大的价值。 可用于执行来源查询的线程数由以下内容定义:

      nifi.provenance.repository.query.threads=2

      在众多用户可能同时针对provenance repository进行查询的系统上,可能需要增加分配给此进程的线程数。 默认值为2。可以通过编辑以下行来调整用于索引Provenance事件的线程数:

      nifi.provenance.repository.index.threads=1     

      默认值为1.对于在大量FlowFiles上运行的流,Provenance事件的索引可能成为瓶颈。 如果是这种情况,将出现一个公告,指示“数据流的速率超过provenance记录率。减少流量以适应。”如果发生这种情况,增加此属性的值可能会提高Provenance Repository能够处理这些记录的速率,从而提高整体吞吐量。 请记住,当您增加分配给一个进程的线程数时,可以减少另一个进程可用的数量。因此,除非遇到上述错误消息,否则应将其保留为1。    

      执行Provenance 查询时,配置的分片大小会影响该进程使用多少堆:

      nifi.provenance.repository.index.shard.size=500 MB

      在搜索Provenance存储库时,分片大小的较大值将导致更多Java堆使用,但应提供更好的性能。 默认值为500 MB。 这并不意味着使用500 MB的堆。 请记住,如果增加分片的大小,您可能还需要增加整个堆的大小,这在后面讨论的bootstrap.conf文件中配置。***重要信息:配置的分片大小必须小于总provenance配置存储大小的50%(nifi.provenance.repository.max.storage.size < - 默认1 GB)。

      注意:虽然无法关闭NiFi provenance ,但可以将实现从“PersistentProvenanceRepository”更改为“VolatileProvenanceRepository”。 这将所有provenance存储移动到堆内存中。 有一个配置设置了可以使用多少堆:

       nifi.provenance.repository.buffer.size=100000

       该值设置为字节。 当然,通过切换到Volatile,您将拥有非常有限的provenance历史记录,并且在重新启动NiFi JVM时,所有provenance都会丢失,但如果您不需要保留此信息,则会删除一些与provenance相关的开销。

       nifi.provenance.repository.implementation=org.apache.nifi.provenance.WriteAheadProvenanceRepository

       从Apache NiFI 1.8.0开始,WriteAheadProvenanceRepository现在是默认值。 WriteAheadProvenance实现最初是在Apache NIFi 1.2.0和HDF 3.0.0中引入的。 原始的PersistentProvenance实现被证明是一个表现不佳的大型卷,会影响画布上每个数据流的吞吐量。

       ***虽然这个新实现在性能上有很大的提升,但我们在使用Java G1GC垃圾收集器时遇到了这个新实现的问题。 因此,我们建议现在在NiFi bootstrap.conf文件中注释掉G1GC行以避免这种情况。

-----------------------------------------------------------------

       以下仅是高性能Linux系统的示例系统配置。 在NiFi群集中,每个节点都将以相同的方式配置。 (其他操作系统的硬件规格相同;但磁盘分区会有所不同)

      CPU: 24 - 48 cores

      Memory: 64 -128 GB

      硬盘配置:

           (1个硬件RAID 1阵列)

           (2个或更多硬件RAID 10阵列)

      RAID 1阵列(也可以是RAID 10)逻辑卷:

  • -/
  • -/boot
  • -/home
  • -/var
  • -/var/log/nifi-logs <-- point all your NiFi logs (logback.xml) here
  • -/opt <-- install NiFi here under a sub-directory
  • -/database-repo <-- point NiFi database repository here
  • -/flowfile-repo <-- point NiFi flowfile repository here

     第一个RAID 10阵列逻辑卷:

     - / cont-repo1 < - 指向NiFi   content repository

     第二个RAID 10阵列逻辑卷:

      - / prov-repo1 < - 指向NiFi provenance repository

     第3个RAID 10阵列逻辑卷(推荐):

      - / cont-repo2 < - 指向第2个NiFI  content repository

     第4个+ RAID阵列逻辑卷(可选):

     ***使用其他RAID阵列来增加NiFi实例可用的content 和/或 provenance库的数量。

      Bootstrap.conf file:

      conf目录中的bootstrap.conf文件允许用户配置NiFi应该如何启动的设置。 这包括参数,例如Java堆的大小,要运行的Java命令以及Java系统属性。 此文件预先配置了默认值。 我们将重点关注在安装NiFi时应更改的属性,以实现高容量/高性能数据流。 bootstrap.conf文件就像nifi.properties文件一样被分成几部分。 由于NiFi是Java应用程序,因此需要安装Java。 NiFi需要Java 7或更高版本。 某些推荐设置仅适用于使用Java 7的情况。我们仅突出显示需要更改的部分。

      # JVM内存设置

高性能NIFI设置

       此部分用于控制运行NiFi的JVM使用的堆内存量。 Xms定义了初始内存分配,而Xmx定义了JVM的最大内存分配。 如您所见,默认值非常小,不适合任何实际大小的数据流。 我们建议将初始和最大堆内存分配增加到至少4 GB或8 GB用于启动器。 

      java.arg.2=-Xms8g

      java.arg.3=-Xmx8g

        如果您的NiFi应用程序日志中遇到任何“内存不足”错误,则表明您有内存泄漏或内存分配不足以支持您的数据流。使用大堆分配时,垃圾收集可能是性能杀手(当针对Old Generation对象发生Major Garbage Collection时最明显)。当使用更大的堆大小时,建议使用更高效的垃圾收集器来帮助减少主要垃圾收集发生时对性能的影响。请注意,设置极大的heap尺寸可能有其优点和缺点。 它为您提供了更多空间来同时处理大批量的FlowFiles,但如果您的流程有垃圾收集问题,则完成垃圾收集可能需要相当长的时间。 如果这些stop the world(垃圾收集)花费的时间比在NiFi群集设置中心跳阈值长,则最终会使节点从群集中断开连接。

       您可以通过取消注释以上行来配置您的NiFi以使用G1垃圾收集器。 (在HDF 2.x版本中,G1GC为默认)

       #java.arg.13=-XX:+UseG1GC

       由于在使用Apache NIFi 1.2.0(HDF 3.0.0)中引入的推荐writeAheadProvenance实现时观察到的问题,我们不再推荐使用G1GC作为垃圾收集器。 从这些版本开始,这一行应该被注释掉。

     #Java 7及以下版本(仅适用于HDF 1.x或NiFi 0.x版本)

       bootstrap.conf文件中有一个部分,其中包含几个已注释掉的Java参数,如果您运行的是Java 7版本,则可以提高性能。(本节仅适用于HDF 1.x版本)我们不设置这些值默认情况下,因为Java 8使用稍微不同的值,并且PermGen设置不适用于Java 8。

      JAVA 8 tuning:

       #Java 8(这适用于使用Java 8运行时所有版本的HDF 1.x,HDF 2.x,NiFi 0.x和NiFi 1.x.     HDF 2.x和NiFi 1.x最少需要Java8)

高性能NIFI设置

      java.arg.7 = -XX:ReservedCodeCacheSize=256m

      java.arg.8=-XX:CodeCacheMinimumFreeSpace=10m

      java.arg.9=-XX:+UseCodeCacheFlushing

      您可以将以上行添加到NiFi bootstrap.conf文件中,以便在运行Java 8版本时提高性能。

      通过取消注释此行来增加代码缓存大小:java.arg.7=-XX:ReservedCodeCacheSize=256m

     代码高速缓存是与堆分开的内存,其中包含编译为本机代码的方法的所有JVM字节码。 如果代码缓存填满,编译器将关闭,不会再次重新打开。 这将影响NiFi的长期运行性能。 恢复性能的唯一方法是重启JVM(重启NiFi)。 因此,通过删除此行上的注释,代码缓存大小将增加到256m,这应足以防止缓存填满。 默认代码缓存由您运行的Java版本定义,但可以低至32m。

     通过删除以下2行的注释来获得额外的保护:

     java.arg.8=-XX:CodeCacheMinimumFreeSpace=10m

     java.arg.9=-XX:+UseCodeCacheFlushing

     此参数建立了一个边界,可以在刷新代码缓存之前使用多少代码缓存,以防止填充并导致编译器停止。

结论:

       此时,您应该配置一个环境,以支持使用NiFi构建高容量/高性能数据流。 虽然本指南为可靠的系统性能奠定了基础,但性能也可能受到数据流本身配置的显著控制。 了解每个处理器上的各种配置参数意味着什么以及如何读取处理器在运行时提供的信息(In,Read / Write,Out和Tasks / Time)非常重要。 通过对提供的信息的解释,用户可以调整参数以便也优化数据流,但这是另一指南的信息。

继续阅读