InfoSphere Streams 2.0 特性简介,第 1 部分: 使用度量实现应用程序监控

C++ 和 SPL 度量示例

对于 IBM® InfoSphere® Streams 2.0 的新手,本文将介绍度量组件,度量组件提供了对系统和用户定义的统计数据的运行时访问,您可以使用这些统计数据监视您的 Streams 应用程序的内部工作。本文将概述新的度量系统,并描述如何访问和使用系统与用户定义度量,将它们用作您的 Streams 应用程序的一部分。

Chris Howard, 大数据解决方案架构师,首席技术官办公室, IBM

Chris HowardChris Howard 自 1998 年加入 IBM,目前是一名解决方案架构师,主要关注大数据解决方案(InfoSphere Streams 和 InfoSphere BigInsights),他是首席技术官办公室的一名成员,效力于 IBM Software Group。他以前曾在 Dublin 管理过 EMEA Stream Computing Centre,负责为 IBM 的流处理解决方案 IBM InfoSphere Streams 进行客户端解决方案开发。他还是英国计算机协会的一名学会注册院士。



2012 年 5 月 24 日

免费下载:IBM® InfoSphere Streams V2 试用版
下载更多的 IBM 软件试用版,并加入 IBM 软件下载与技术交流群组,参与在线交流。

简介

本文介绍了 InfoSphere Streams 开发人员可访问的新度量系统的一些功能。介绍了 Streams 2.0 版本,该度量系统提供了对应用程序特定度量的运行时访问,并能够外部监视您感兴趣的应用程序统计数据。我们提供了许多采用 Streams 处理语言和 C++ 的样例。

本文是为那些掌握了一些 Streams 编程语言技巧和 C++ 技巧的 Streams 组件开发人员和应用程序编程人员而撰写的。您可以使用本文作为一个参考,或者可以检查并执行本文中的样例,以演示文中描述的技术。要执行这些样例,则应该掌握 Streams 编程的一般工作知识。

运行这些样例需要一个包含 InfoSphere Streams V2.0 或其更高版本的 Red Hat Enterprise Linux® 工具箱。


度量系统概述

Streams 2.0 运行时提供了查询各种应用程序度量的能力,并使得使用这类数据成为运行 Streams 作业的一部分,或者通过外部工具或程序(比如流工具)使用这些数据。访问这些度量可以提供一定范围的使用,不管是对正在运行的应用程序进行简单的应用程序监控,还是对它们进行复杂的实时改编,例如减载 (load shedding)。

访问这些度量是通过运行时 API 来提供的。这些 API 允许检索与 Streams Operator or Processing Element (PE) 级别的输入端口和输出端口的已处理、已删除或已排队元组数量有关的度量数据范围。

Streams 运行时提供了支持两种主要度量类型的能力:

  • 系统度量:用于 Operators 和 PE 的预定义计数器数据。该数据可能包括类似于通过某个运算符端口提交的 Streams 元组的数量之类的数据。
  • 用户定义的度量:开发人员定义的度量。在运算符级别上实现,用于报告用户感兴趣的所有应用程序值。

以下小节将深入介绍各种度量及其实现的更多细节。

度量数据类型

已记录的 Streams 数据(不管是系统提供的,还是用户定义的)可以属于三种基本度量数据类型之一。这些类型提供了一些与将通过度量展示的计数器数据的类有关的上下文。下方给出了度量数据类型的列表。

  • Counters:用于表示随时间增加(或减少)的度量值,例如,某个运算符输入端口处理的元组数量。
  • Gauges:用于表示实时的某个时间点上的值,可使用该类型设置任何值,比如目前排队的窗口标点符号的数量。
  • Time:用于表示日期/时间戳,可以使用该类型来记录 Streams 应用程序中特殊时间发生的事件。

系统度量由运行时提供,具有固定的数据类型(通常为 counters 或 gauges),而在实现用户定义的度量时,度量数据类型的选择取决于开发人员。


系统度量

在默认情况下,系统度量是作为 Streams 运行时的一部分提供的,系统度量允许访问许多值,提供了对 Stream 应用程序的内部操作的洞察。在应用程序级别上,API 可用于对与运算符和包含该运算符的处理元素均有关的度量的运算符访问,度量范围的访问仅限于本地。

如果提供了对某个运算符和容器处理元素的内部工作的这种级别的洞察,则允许应用程序基于度量值潜在地改编其行为。在应用程序内部,基于过度数据比率来减载元组的机会或基于已处理元组数量来核查操作状态的机会都是可能的选择。在应用程序外部,脚本或程序可能轮询更多的应用程序或系统级的可用度量,不管是将它们用于基本监视,还是在系统级别上将它们用于度量系统记录的事件。

系统度量提供了两种变体:运算符级别的度量和 PE 级别的度量。在下面的小节中,我们将探索这两种度量中的每种度量。

运算符度量 — 输入和输出端口度量

线程端口

线程端口 允许运算符输入端口执行自己的单独线程。元组用一个单独的执行线程到达每个指定的输入端口,即使该运算符与其他运算符是融入在一起的。这允许并行执行更多的运算符,尤其是在同一个分区/PE 中。关于仅可用于线程端口的那些度量的列表,参见 表 1

运算符级的系统度量允许仔细检查某个特定运算符执行的处理。您可以查询各种度量值,获得与某个运算符相关的每个输入和输出端口,查询范围从数据元组(已处理、已删除或已排队元组)的计数到标点符号元组的详细信息,比如数量、类型(window 和 final)以及状态 (processed 和 queued)。

如果拥有访问单独某个运算符的这个级别的详细信息的访问权,则允许使用大量的诊断功能。这允许您通过监视线程端口(请参阅侧栏中的 “线程端口”)上的已删除或已排队元组,诊断某个应用程序的问题,比如性能瓶颈。

图 1. PE 级别的度量
图像显示了一个包含两个输入端口和一个输出端口的 Streams 运算符

获得对运算符级别的度量的访问是通过 OperatorContext 类及其 getMetrics() 方法函数实现的,该函数会返回一个 OperatorMetrics 对象。访问运算符上下文首先需要调用该运算符的 getContext() 成员函数。

SPL::Metric

SPL::Metric 类用于表示某个度量对象,除了获得当前值之外,它还提供了许多成员函数来访问度量名称、描述和类型。有关 SPL Operator Runtime C++ API 文档的链接,请参阅 参考资料

调用 getInputPortMetric(port, metric)getOutputPortMetric(port, metric) 方法,这两个方法都属于 OperatorMetrics 类,分别允许您访问个别输入端口度量和个别输出端口度量。在这里,port 是端口的索引号,而 metric 是将返回的度量的名称(使用 OperatorMetrics::InputPortMetricName 或 OperatorMetrics::OutputPortMetricName,具体取决于请求的度量类型)。

清单 1. 声明度量的头文件 (_h.cgt)
    ...
  
    private:
      // Members 
    
        // Note const required for getInputPortMetric and getOutputPortMetric
        Metric const & numTuplesProcessed; 

    ...
清单 2. 通过原始运算符 (_cpp.cgt) 访问度量
    // Constructor
    MY_OPERATOR::MY_OPERATOR()
      : numTuplesProcessed(getContext().getMetrics()\
          .getInputPortMetric(0, OperatorMetrics::nTuplesProcessed))
    {
    }    
	    
    // Tuple processing for non-mutating ports
    void MY_OPERATOR::process(Tuple const & tuple, uint32_t port)
    {

        // Declare variable to store the metrics current value    
        int64_t nProcessedValue;

        ...

        nProcessedValue = numTuplesProcessed.getValueNoLock();
    
        ...
    }

注:注意执行 getInputPortMetric() 调用的方式,是将它作为构造函数初始化列表的一部分来执行的,并且没有将它放入构造函数正文中。这是因为成员函数返回了一个 const 值,并且必须在初始化期间执行该调用,不得在赋值期间调用。

下面给出了 SPL 中的一个示例,这次提供了某个输入端口上的已排队元组的数量。因为是作为 SPL 自定义运算符中的 onTuple 事件的一部分实现的,所以允许基于输入端口上的过多的元组排队采取替代措施。

清单 3. SPL 运算符的 getInputPortMetric 示例
    // Declare metric value
    mutable int64 nQueuedValue = 0; 	
	
    // Return the number of Tuples Queued for input port 0
    getInputPortMetricValue(0u, Sys.nTuplesQueued, nQueuedValue);

下表给出了每个可用运算符级度量的详细信息,并列出了度量名称、范围和描述。

表 1. 系统提供的运算符级度量
名称范围描述
nTuplesProcessed每输入端口已处理元组的数量(Counter 类型)
nTuplesDropped*每输入端口已删除元组的数量(Counter 类型)
nTuplesQueued*每输入端口已排队元组的数量(Gauge 类型)
nWindowPunctsProcessed每输入端口已处理的窗口标点符号的数量(Counter 类型)
nFinalPunctsProcessed每输入端口已处理的最终标点符号的数量(Counter 类型)
nWindowPunctsQueued*每输入端口已排队的窗口标点符号的数量(Gauge 类型)
nFinalPunctsQueued*每输入端口已排队的最终标点符号的数量(Gauge 类型)
queueSize*每输入端口端口的排队规模,如果没有队列,则为 0(Gauge 类型)
nTuplesSubmitted每输出端口已提交元组的数量(Counter 类型)
nWindowPunctsSubmitted每输出端口已提交窗口标点符号的数量(Counter 类型)
nFinalPunctsSubmitted每输出端口已提交最终标点符号的数量(Counter 类型)

带有 * 标记的度量仅可用于使用 threadedPort 配置的输入端口。对于非 threadedPorts,调用 getInputPortMetric() 会返回 0。

PE 度量 — 输入和输出端口度量

处理元素级别上的度量类似于运算符级别的度量。在处理运算符级别的度量时,我们关心的是特定于上下文中的运算符的值,但是处理元素级别上的度量与实现跨 PE 边界的流的所有运算符均有关。

图 2 详细说明了这种边界概念。因此,我们展示了一个包含 4 个运算符的处理元素。每个运算符都有许多输入和输出端口。在处理 PE 级别的度量时,只有跨 PE 边界的输入和输出端口可用于查询(例如,除了在输出端口 0 上提交的元组数量之外,还可以查询输入端口 0、1 和 2 上处理的元组的数量)。尽管 PE 输入端口 1 提供了运算符 1 和运算符 2,但在查询 PE 输入端口 1 的已处理元组的数量时,仅对这些元组进行了一次计数。

图 2. PE 级别的度量
图像展示了包含多个运算符的 Streams 处理元素

表 2 提供了运算符和 PE 级别的度量之间的映射。请注意,没有跨 PE 边界的内部端口仅可以在运算符级别上使用。

表 2. 运算符和 PE 端口的映射
运算符运算符端口PE 端口访问范围
运算符 1输入端口 0输入端口 0运算符和 PE
输入端口 1输入端口 1运算符和 PE
输出端口 0n/a仅运算符
运算符 2输入端口 0输入端口 1运算符和 PE
输入端口 1输入端口 2运算符和 PE
输出端口 0n/a仅运算符
运算符 3输入端口 0n/a仅运算符
输出端口 0n/a仅运算符
运算符 4输入端口 0n/a仅运算符
输出端口 0输出端口 0运算符和 PE

为了达到 PE 处理的元组的总数,必须合计每个 PE 输入端口(端口 0、1 和 2)单个元组的数量。仅包含一个运算符(例如,使用分区外置放置)的元组将对 PE 级别和运算符级别的度量返回相同的结果。

除了在运算符级别提供的元组和标点符号计数之外,还可以扩展 PE 度量,使其包含输入和输出端口上的元组字节率,以及输出端口的连接状态的详细信息(比如断开连接的数量) 。这种类型的度量 对于查找 PE 之间的失败链接可能很有用,用户可能需要对这些链接予以一定程度的注意。PE 级别的度量遵循与运算符度量相同的访问机制,但不是通过运算符上下文完成查询,而是使用 getPE() 将一个句柄返回给 PE。

下表给出了每个可用 PE 级度量的详细信息,并列出了度量名称、范围和描述。

表 3. 系统提供的 PE 级度量
名称范围描述
nTuplesProcessed每输入端口已处理的元组的数量(Counter 类型)
nTupleBytesProcessed每输入端口已通过端口处理的节点数(Counter 类型)
nWindowPunctsProcessed每输入端口已处理的窗口标点符号的数量(Counter 类型)
nFinalPunctsProcessed每输入端口已处理的最终标点符号的数量(Counter 类型)
nTuplesSubmitted每输出端口已提交元组的数量(Counter 类型)
nTupleBytesSubmitted每输出端口已提交的元组字节的数量(Counter 类型)
nWindowPunctsSubmitted每输出端口已提交的窗口标点符号的数量(Counter 类型)
nFinalPunctsSubmitted每输出端口已提交的最终标点符号的数量(Counter 类型)
nBrokenConnections每输出端口端口上出现的断开连接的数量(Counter 类型)
nRequiredConnecting每输出端口端口上目前正连接的所需连接的数量(Gauge 类型)
nOptionalConnecting每输出端口端口上目前正连接的可选连接的数量(Gauge 类型)

用户定义的度量

除了 Streams 运行时提供的内置度量之外,还可以添加自定义度量。这些度量表现得与系统度量类似,但它们允许您外部展示您感兴趣的值和一些重要的值。

在使用自定义度量时

自定义度量提供了一个出色的机制,可用该机制来展示可能深藏在您的 Streams 运算符代码中的用户感兴趣的一些项。无论何时您想知道缓冲区的大小、已链接列表的长度或运算符最后的检验点的时间戳,都可以使用自定义度量。自定义度量提供了一个替代方法来获得某个变弱的运算符或调试日志。

定义自定义度量

自定义度量可以通过运算符模型进行静态声明,也可以在运行时动态创建。运算符模型中定义的度量可由 SPL 语言运行时在执行时自动实例化。要在运行时创建自定义度量,可以使用 createCustomMetric(name, description, kind) 成员函数。

不管用哪种方式声明自定义度量,都可以通过 OperatorMetric 类的 getCustomMetricByName(name) 成员函数来访问它。在创建自定义度量后,您可以随时任意更新自定义度量的值。自定义度量的值是通过使用 setValue(newValue)incrementValue(incValue) 函数来完成更新的。有关的更多详细信息可在 IBM Streams Processing Language Runtime API Documentation 中找到。

将自定义度量定义为 Streams 运算符模型的一部分

运算符模型是用来描述 C++ 原始运算符或 Java™ 原始运算符的 XML 文档。该文档由 4 个主要元素组成:

  • 上下文
  • 参数
  • 输入端口
  • 输出端口

上下文元素描述了可应用于没有与特定参数和运算符端口链接的运算符的全局属性。该元素还捕获可在后面的运算符模型条目中引用的通用定义。

编辑运算符模型是通过使用树视图或源 XML 模式中的 Streams Studio Editor 来执行的。图 3 显示了树视图,清单 4 显示了自定义运算符的对应 XML 代码片段。

图 3. 编辑运算符模型树视图
Operator Model Editor 的图像
清单 4. 运算符模型中的样例 XML(部分)
  ...        
  <metrics>
    <metric>
      <name>myCount</name>
      <description>A new metric defined via the operator model</description>
      <kind>Counter</kind>
    </metric>
  </metrics>
  ...

如上所示,访问自定义度量是一个很简单的操作,使用 OperatorContext 类及其 getMetrics() 成员函数即可完成此操作。下面的示例显示了您可以如何访问您新建的自定义度量 MyCount,并为其分配一个值。

清单 5. 声明度量的头文件 (_h.cgt)
    ...
  
    private:
        // Members 
    
        Metric & myCountStatic;
    ...
清单 6. 通过原始运算符 (_cpp.cgt) 访问度量
    // Constructor
    MY_OPERATOR::MY_OPERATOR()
      : myCountStatic(getContext().getMetrics().getCustomMetricByName("myCount"))
    {
    }    
	    
    // Tuple processing for non-mutating ports
    void MY_OPERATOR::process(Tuple const & tuple, uint32_t port)
    {

        ...

        // Set the Custom Metric to an arbitrary value
        myCountStatic.setValue(someValue);

        // Increment the Metric by 10
        myCountStatic.incrementValue(10);
    
        ...
    }

其他两个对 SPL::OperatorMetrics 类有用的成员函数是 hasCustomMetric(name)getCustomMetricNames(),它们允许您查询运算符模型中定义的所有自定义度量是否存在,并返回它们的名称。

在运行时创建一个自定义度量

作为将某个自定义度量预定义为运算符模型的一部分的替代方法,还可以使用 createCustomMetric(name, description, kind) 函数动态创建新的度量,请使用以下函数之一:

  • Metric::Counter
  • Metric::Gauge
  • Metric::Time

我们最后一个示例展示了如何在运行时动态创建一个新的度量,不必预先将它定义为运算符模型的一部分。在定义了新的度量之后,就可以使用相同的机制来设置或增加新度量的值。

清单 7. 声明度量的头文件 (_h.cgt)
    ...
  
    private:
      // Members 
    
        Metric & myCountDynamic;
    ...
清单 8. 通过原始运算符 (_cpp.cgt) 访问度量
    // Constructor
    MY_OPERATOR::MY_OPERATOR()
      : myCountDynamic(getContext().getMetrics().createCustomMetric("myCountDynamic",\
          "A description for a dynamic metric", Metric::Counter))
    {
    }    
	    
    // Tuple processing for non-mutating ports
    void MY_OPERATOR::process(Tuple const & tuple, uint32_t port)
    {

        ...

        // Set the Custom Metric to an arbitrary value
        myCountDynamic.setValue(someValue);

        // Increment the Metric by 10
        myCountDynamic.incrementValue(10);
    
        ...
    }

注:尽管我们提供了对上述度量的描述,但在检查 Streams Studio 的实例图中的 Operator/PE 时,不会选取并显示该值。通过运算符模型创建的度量有它们自己的描述,这些描述被添加到应用程序描述语言 (.adl),然后用于创建生动的图形。这种情况不适合在运行时创建的客户度量。


访问度量

在本文的最后一部分中,我们将查看在不必求助于自定义开发和各种运行时 API 的情况下检查度量数据的可用技术的范围。

通过 streamtool capturestate 命令访问度量

除了用于这些主机和作业的性能度量除外,还可以使用 streamtool capturestate 命令捕获系统主机的当前状态和 Streams 实例中的作业。对于引用,该命令会以 XML 格式返回输出,因此可以在您自己的脚本内解析和使用该数据,从而根据需要采取更进一步的措施。

该模式可在以下文件中使用:streams-install-directory/schema/streamsInstanceState.xsd

使用以下命令捕获正运行在 Streams 实例中的作业的性能度量信息,该实例是 streamtool capturestate --select jobs=metrics

当您请求性能度量信息时,命令输出中包含其他有关 PE、运算符和端口的信息。清单 9 显示了一个运算符度量信息样例。

清单 9. streamtool capturestate 中的样例 XML 输出
  ...
  <operator name="PrimOp">
    <metric name="myCountDynamic" lastChangeObserved="1329912395" userDefined="true">
      <metricValue xsi:type="streams:longType" value="65"/>
    </metric>
    <metric name="myCount" lastChangeObserved="1329912395" userDefined="true">
      <metricValue xsi:type="streams:longType" value="1065"/>
    </metric>
    <inputPort index="0" name="BeaconStream">
      <metric name="nTuplesProcessed" lastChangeObserved="1329912395" userDefined="false">
        <metricValue xsi:type="streams:longType" value="782"/>
      </metric>

    ...
    </inputPort>
    ...
  </operator>

注意我们的自定义度量与其当前值的显示方式。lastChangeObserved 字段基于自某个时间点后经过的秒数来给出时间。有关命令使用以及如何解释输出的更多信息,请参阅 Streams Administration and Installation Guide(第 10 章 “Monitoring and managing IBM InfoSphere Streams”)中关于性能度量的小节。

通过 Streams Studio 访问度量 — 度量视图

Streams Studio 包含一个度量视图,允许您监视与某个正在运行的实例有关的度量。该度量视图可分为两个主要组成部分:

  • 左窗格中的基于树的导航视图,您可以从中选择您想查看哪些度量的元素
  • 右窗格中基于表的度量视图,其中包含用于左边的已选定元素的度量

在左窗格中按树进行导航,您可以选择要检查的主机、作业、PE、运算符以及输入和输出端口,并提供了右窗格,在其中反映已选定条目的捕获度量的详细信息。下图显示了正显示的自定义度量的两个度量示例,然后在运算符输入端口级别上显示它们。

图 4. 运算符自定义度量
显示了自定义度量的度量视图的图像,其中显示了时间、警报、myCountDynamic 和 myCount
图 5. 运算符输入端口度量
显示了输入端口度量的度量视图的图像,其中显示了时间、nTuplesProcessed、nTuplesDropped 和 nTuplesQueued

这只是通过度量视图查看可用信息健康情况的一个小示例。详细描述该视图已超出了本文的讨论范围,但 InfoSphere Streams Studio Installation and User's Guide 在第 9 章 “Monitoring running SPL applications” 中提供了详细的遍历指导。

通过 Streams Studio 访问度量 — 实例图

查看运行时度量的最后一个选项是通过 Streams Studio 的实例图视图提供的。实例图视图显示了运行在 Streams 实例之上的 SPL 应用程序的动态拓扑。可以通过定制该视图来更改显示正运行的应用程序的拓扑的方式。

收集度量信息

要开始收集度量信息,请单击 Collect Metrics Information 图标 Collect metrics Information 图标

您可以选择 Streams 元素的类型(比如运算符、PE 和作业),以便将它们包含在图中,还可以选择如何对这些元素分组以及如何为它们上色。针对 Instance Graph 视图中的运算符和 PE 启用和配置运行时度量信息的收集也是有可能的。

在 图 6 中,您可以看见一个运行时度量的示例,将鼠标悬停在某个给定运算符上时,就会显示该度量。一掠而过的窗口显示了运算符名称、度量(比如元组内和元组外的度量),后跟早先声明的自定义度量。请注意,在运行时创建的度量没有与之相关的描述。

再次声明,这只是通过度量视图获得可用信息的一个小示例。有关在实例图下监视度量的更多信息,请参阅 InfoSphere Streams Studio Installation and User's Guide

图 6. 显示了运算符运行时度量的一掠而过的窗口
图像显示了运算符运行时度量

结束语

我们希望本文能让您了解如何使用度量和 InfoSphere Streams。无论您是想获得您正在运行的应用程序的洞察,还是对显示关键计数器有特定要求,度量系统都可以为您提供一个挖掘这方面数据的灵活方法。

掌握这方面的更多知识的最简单方法就是自己去尝试。您可以利用这些代码片段构建自己的运算符,并尝试使用提供的系统范围和可用的自定义度量。如果您想获得更多的信息,或者对本文任何部分的介绍内容有疑问,请在 Streams 论坛上贴出您的问题(参阅 参考资料)。

致谢

非常感谢 Mark Mendell 对本文提供的帮助和审阅。

参考资料

学习

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Information Management
ArticleID=818106
ArticleTitle=InfoSphere Streams 2.0 特性简介,第 1 部分: 使用度量实现应用程序监控
publish-date=05242012