<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>shanyu</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/shanyu/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/shanyu/feed.xml</link>
    <description />
    <lastBuildDate>Wed, 17 Apr 2019 03:50:40 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>How does Spark determine partitions for an RDD?</title>
      <link>https://docs.microsoft.com/archive/blogs/shanyu/how-does-spark-determine-partitions-for-an-rdd</link>
      <pubDate>Tue, 08 May 2018 05:51:50 GMT</pubDate>
      <dc:creator><![CDATA[Shanyu Zhao]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/shanyu/?p=45</guid>
      <description><![CDATA[The most fundamental data structure in Spark is called RDD (Resilient Distributed Dataset). An RDD...]]></description>
      <content:encoded><![CDATA[The most fundamental data structure in Spark is called RDD (Resilient Distributed Dataset). An RDD can have one or many partitions, and each partition is a subset of data that resides on one node in your Spark cluster. The number of partitions is one of the factors to determine the parallelism of Spark task execution. Most of the time you do not need to worry about partitions. However, if you are tuning performance or investigating the resulting data files (e.g. one RDD partition is written out as one partial file in HDFS), you need to understand how Spark determines the number of partitions for an RDD.

The rule of thumb: the number of partitions of an RDD is usually the same as the parent RDD, except for coalesce(), or reduceByKey() etc. when a shuffle is involved. For RDDs with no parents (e.g. when reading a file from HDFS), the number of partitions is determined by an algorithm very similar to Hadoop's FileInputFormat.getSplits().
<h2>1. How Hadoop calculates splits</h2>
The source code in Hadoop to calculate splits from input data in HDFS (FileInputFormat.java): <a href="https://github.com/apache/hadoop/blob/e30710aea4e6e55e69372929106cf119af06fd0e/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapred/FileInputFormat.java#L319">https://github.com/apache/hadoop/blob/e30710aea4e6e55e69372929106cf119af06fd0e/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapred/FileInputFormat.java#L319</a>

This is pseudo code:
<pre>getSplits(conf, numSplits) =&gt; max(minSize, min(goalSize, blockSize))
   minSize = conf: mapreduce.input.fileinputformat.split.minsize, defaults to 0
   goalSize = totalSize / numSplits</pre>
The blockSize is specific to your distributed file system configuration. For WASB, the default is 512MB, but you can change it by configuration "fs.azure.block.size", as you can see here:

<a href="https://github.com/apache/hadoop/blob/e30710aea4e6e55e69372929106cf119af06fd0e/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azure/NativeAzureFileSystem.java#L687">https://github.com/apache/hadoop/blob/e30710aea4e6e55e69372929106cf119af06fd0e/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azure/NativeAzureFileSystem.java#L687</a>

To put it in simple English, the split size is the smaller of goal size and file system block size. The goal size is the total size of the input files divided by the intended number of splits.
<h2>2. How Spark calculates splits</h2>
<h3>2.1 Unstructured APIs</h3>
SparkContext exposes a few APIs to directly read a Hadoop file from HDFS to an RDD. This is done in HadoopRDD.scala which is basically a wrapper on Hadoop's FileInputFormat class. The source code:

<a href="https://github.com/apache/spark/blob/992447fb30ee9ebb3cf794f2d06f4d63a2d792db/core/src/main/scala/org/apache/spark/rdd/HadoopRDD.scala#L196">https://github.com/apache/spark/blob/992447fb30ee9ebb3cf794f2d06f4d63a2d792db/core/src/main/scala/org/apache/spark/rdd/HadoopRDD.scala#L196</a>

The numSplits parameter when calling FileInputFormat.getSplits() is hardcoded to 2 by Spark, as can be seen here:

<a href="https://github.com/apache/spark/blob/e9f983df275c138626af35fd263a7abedf69297f/core/src/main/scala/org/apache/spark/SparkContext.scala#L2329">https://github.com/apache/spark/blob/e9f983df275c138626af35fd263a7abedf69297f/core/src/main/scala/org/apache/spark/SparkContext.scala#L2329</a>

Let's look at an example in HDInsight cluster (Version 3.6 with Spark 2.2). Let's load an CSV file which is around 200KB. In spark-shell, just type:
<pre>val text = spark.sparkContext.textFile("/HdiSamples/HdiSamples/SensorSampleData/hvac/HVAC.csv")
text.getNumPartitions</pre>
The result is 2. This is because splitSize is the goal size which is totalSize/2 since blockSize is much bigger at 512MB.
<h3>2.2 Structured APIs</h3>
For Dataframe based APIs, one can use DataFrameReader to load a file. Eventually this is handed in DataSourceScanExec.createNonBucketedReadRDD():

<a href="https://github.com/apache/spark/blob/992447fb30ee9ebb3cf794f2d06f4d63a2d792db/sql/core/src/main/scala/org/apache/spark/sql/execution/DataSourceScanExec.scala#L396">https://github.com/apache/spark/blob/992447fb30ee9ebb3cf794f2d06f4d63a2d792db/sql/core/src/main/scala/org/apache/spark/sql/execution/DataSourceScanExec.scala#L396</a>

This is the pseudo code:
<pre>spltiSize = Math.min(defaultMaxSplitBytes, Math.max(openCostInBytes, bytesPerCore))
   defaultMaxSplitBytes = conf: spark.sql.files.maxPartitionBytes, defaults to 128MB
   openCostInBytes = conf: spark.sql.files.openCostInBytes, default to 4MB
   bytesPerCore = totalBytes / defaultParallelism
   defaultParallelism = conf: spark.default.parallelism, defaults to (conf: spark.executor.cores) * (conf: spark.executor.instances)</pre>
The openCostInBytes is an estimated cost of opening a file, expressed as the same amount of time when reading bytes from a file. This is to avoid the situation when the split size is too small. The split size is usually the goal size, which is the total size of all input files divided by the total number of cores for all executors. When the goal size is smaller than the estimated cost of opening a file, we use that estimation as splitSize. We can see that Spark structured API does not quite concern with the HDFS block size, and tries to evenly distribute the input bytes among all the executors.

For example, in HDInsight cluster <span style="float: none;background-color: transparent;color: #333333;cursor: text;font-family: Georgia,'Times New Roman','Bitstream Charter',Times,serif;font-size: 16px;font-style: normal;font-variant: normal;font-weight: 400;letter-spacing: normal;line-height: 24px;text-align: left;text-decoration: none;text-indent: 0px">(Version 3.6 with Spark 2.2)</span>:
<pre>val hvac = spark.read.format("csv").load("/HdiSamples/HdiSamples/SensorSampleData/hvac/HVAC.csv")
hvac.rdd.getNumPartitions()</pre>
The result is 1. This is different from the result from Structured API, why? Because the bytesPerCore is way too small than the openCostInBytes so the splitSize is set to 4MB, therefore, the number of splits is 1.
<h2>3. How to manipulate number of splits for input files in HDInsight</h2>
For Unstructured API, to increase the number of splits, you can lower the blockSize of the file system or lower minSize ; to decrease, increase blockSize or minSize. The minSize is controlled by "mapreduce.input.fileinputformat.split.minsize"; note that you have to use "spark.hadoop" prefix with this configuration. For HDFS, the blockSize is a per file meta data so you cannot manipulate it unless you regenerate the file. For WASB the block size is faked by configuration "fs.azure.block.size" so you can manipulate it at any time. For ADLS the block size is hard-coded to 256MB. Note that the minimum number of partitions is 2 according to the above formula.

For Structured API, to increase the number of splits, you can lower defaultMaxSplitBytes, to decrease, increase defaultMaxSplitBytes. The defaultMaxSplitBytes is controlled by configuration "spark.sql.files.maxPartitionBytes". Note that there is a lower bound for the number of splits, which is equal to the defaultParallelism if the totalSize is not too small (precisely openCostInBytes * defaultParallelism).]]></content:encoded>
    </item>
    <item>
      <title>Understanding and Using HDInsight Spark Streaming</title>
      <link>https://docs.microsoft.com/archive/blogs/shanyu/understanding-and-using-hdinsight-spark-streaming</link>
      <pubDate>Fri, 18 Sep 2015 22:20:00 GMT</pubDate>
      <dc:creator><![CDATA[Shanyu Zhao]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/shanyu/2015/09/18/understanding-and-using-hdinsight-spark-streaming/</guid>
      <description><![CDATA[There are plenty of blogs and materials out there talking about Spark Streaming. Most of them focus...]]></description>
      <content:encoded><![CDATA[<p><span style="font-size: small;">There are plenty of blogs and materials out there talking about Spark Streaming. Most of them focus on the internals of Spark Streaming and how in detail Spark Streaming works. I think those are not best suited for developers or data scientists who want to use Spark Streaming. As I worked to enable Spark Streaming for HDInsight, I found that customers are often confused and clueless on how to use Spark Streaming properly&nbsp;in a production system. I hope this blog can help them better understand Spark Streaming from a user's point of view.</span></p>
<h1><span style="font-size: small;">1. What is Spark Streaming?</span></h1>
<p><span style="font-size: small;">Spark Streaming is the real time data analytics framework provided by Spark. It is a micro-batch system. In a nutshell, you can think it as an additional layer on top of Spark, which reads data from external data source, periodically pushes batch of data to Spark for real time transformation.</span></p>
<h1><span style="font-size: small;">2. How does Spark Streaming work?</span></h1>
<p><span style="font-size: small;">The key concept in Spark Streaming is a receiver. A receiver is the interface to a specific external system. Before we move on, you need to understand a few basic concepts of Spark:</span></p>
<p style="padding-left: 30px;"><span style="font-size: small;">Application: A user application submitted to Spark. It consists of a driver and many executors.</span></p>
<p style="padding-left: 30px;"><span style="font-size: small;">Driver: A program that manages all executors for a Spark application, declares data transformation and actions on RDDs.</span></p>
<p style="padding-left: 30px;"><span style="font-size: small;">Executor: A process running on the worker node for a Spark application, which stays up for the duration of the application.</span></p>
<p style="padding-left: 30px;"><span style="font-size: small;">Job: A parallel computing consisting of multiple tasks that are spawned in response to a spark action (e.g. save, collect, etc.).</span></p>
<p style="padding-left: 30px;"><span style="font-size: small;">Stage: Smaller set of tasks in a Job that depend on one another.</span></p>
<p style="padding-left: 30px;"><span style="font-size: small;">Task: A unit of work that is sent to one executor. Note that one executor can execute multiple tasks at the same time.</span></p>
<p><span style="font-size: small;">When you submit a spark streaming application, a driver is started, which launches many executors on the worker nodes through sparkmaster. The first job submitted to the application is the receiver job (usually with Job ID 1), which lasts the duration of the streaming application. Each task in the receiver job is one instance of the receiver.</span></p>
<p><span style="font-size: small;">This is how data enters Spark system through a receiver:</span></p>
<p style="padding-left: 30px;"><span style="font-size: small;">Data Source -&gt; Receiver -&gt; Block Generator -&gt; Block Manager</span></p>
<p><span style="font-size: small;">Receiver reads data from the Data Source, and hands off the received data to a component called Block Generator. The Block Generator keeps the data in memory. Every block interval (spark.streaming.blockInterval, defaults to 200ms), it sends the block to Spark Block Manager as a new partition of a RDD. Block Manager is a component running on every Spark node that manages data blocks both locally and remotely. Every batch interval (specified when creating StreamingContext), the RDD is closed and a Spark job (data processing job) is submitted to process that newly generated RDD.</span></p>
<p><span style="font-size: small;">You can see the receiver jobs and all the subsequent data processing jobs in Spark UI. As can be seen, the Job 1 is the receiver job, which has only 1 task (1 instance of receiver). Job 2,3,4,5,6 are data processing jobs, about 10 seconds apart. This is because the batch interval is set to 10 seconds.</span></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/50/4452.spark_ui.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-50/4452.spark_5F00_ui.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/50/4452.spark_ui.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-50/4452.spark_5F00_ui.png" alt="" border="0" /></a></p>
<h1><span style="font-size: small;">3. How to use Spark Streaming with Azure Event Hubs in HDInsight?</span></h1>
<p><span style="font-size: small;">A streaming solution consists of not only the Spark Streaming framework, but also the external data source and the persistent store for processed data. For HDInsight, the recommended data source is Azure Event Hubs. Event Hubs is a pub/sub message broker service in the cloud, equivalent to Apache Kafka. For persistent data store, you can use HDFS (in HDInsight this is&nbsp;WASB, basically Azure Storage), HBase, or SQL database. You can find plenty of online examples/tutorials on this topic. Therefore our focus here is Event Hubs.</span></p>
<p><span style="font-size: small;">There is a fantastic tutorial from HDInsight documentation that shows you how to write an end to end Spark Streaming application using Event Hubs:</span></p>
<p><span style="font-size: small;"><a href="https://azure.microsoft.com/en-us/documentation/articles/hdinsight-apache-spark-csharp-apache-zeppelin-eventhub-streaming/">https://azure.microsoft.com/en-us/documentation/articles/hdinsight-apache-spark-csharp-apache-zeppelin-eventhub-streaming/</a></span></p>
<p>This is how you create a DStream from a Event Hubs:</p>
<div style="padding-left: 30px;">val ehParams = Map[String, String](<br />&nbsp; "eventhubs.policyname" -&gt; "&lt;name of policy with listen permissions&gt;",<br />&nbsp; "eventhubs.policykey" -&gt; "&lt;key of policy with listen permissions&gt;",<br />&nbsp; "eventhubs.namespace" -&gt; "&lt;service bus namespace&gt;",<br />&nbsp; "eventhubs.name" -&gt; "&lt;event hub in the service bus namespace&gt;",<br />&nbsp; "eventhubs.partition.count" -&gt; "1",<br />&nbsp; "eventhubs.consumergroup" -&gt; "$default",<br />&nbsp; "eventhubs.checkpoint.dir" -&gt; "/&lt;check point directory in your storage account&gt;",<br />&nbsp; "eventhubs.checkpoint.interval" -&gt; "10"<br />)</div>
<div style="padding-left: 30px;">val ssc =&nbsp; new StreamingContext(sc, Seconds(10))</div>
<div style="padding-left: 30px;">val stream <span class="pun">=</span><span class="typ">EventHubsUtils</span><span class="pun">.</span><span class="pln">createUnionStream</span><span class="pun">(</span><span class="pln">ssc</span><span class="pun">,</span><span class="pln"> ehParams</span><span class="pun">)</span></div>
<p><span style="font-size: small;">This tutorial uses the EventHubsReceiver to receive data from Event Hubs. Event Hubs supports AMQP protocol, which is how the EventHubsReceiver talks to the Event Hubs server. The EventHubsReceiver uses EventHubsClient, which in turn uses the Apache Qpid project as the AMQP library. Note that the Storm EventHubSpout also uses the same EventHubsClient library.</span></p>
<p><span style="font-size: small;">There is a common mistake in running this tutorial. If you don't assign enough cores to the spark streaming application (or Zeppelin if you use Zeppelin notebook), the application will appear stuck and not produce any results. This is because by design each EventHubsReceiver instance only handles one Event Hubs partition. Each receiver instance requires one CPU core to run, and you need to leave&nbsp;some CPU cores to process the received data. So if you set partition count to N in Event Hubs parameters, you need to make sure you assign 2xN CPU cores to the streaming application.</span></p>
<p><span style="font-size: small;">What this means for HDInsight Spark cluster is that for a default configuration, a 4 node cluster can handle at most 8 Event Hubs partitions (each node has 4 cores, and 16 cores can only handle at most 8 partitions).</span></p>
<p><span style="font-size: small;">The "eventhubs.checkpoint.dir" specifies the checkpoint folder to store the message offset.&nbsp;This&nbsp;parameter needs to be an absolute path. You'll see exceptions when you provides a relative path like "mycheckpoint". You need to use "/mycheckpoint" instead.</span>&nbsp;</p>
<p><span style="font-size: small;">The EventHubsReceiver project is submitted to spark-packages repo here:</span></p>
<p><span style="font-size: small;"><a href="https://spark-packages.org/package/hdinsight/spark-eventhubs">https://spark-packages.org/package/hdinsight/spark-eventhubs</a></span></p>
<p><span style="font-size: small;">Spark-packages is a community maintained repository for all third party Spark integration code. The actual source code is shared on github:</span></p>
<p><span style="font-size: small;"><a href="https://github.com/hdinsight/spark-eventhubs">https://github.com/hdinsight/spark-eventhubs</a></span></p>
<p><span style="font-size: small;">The EventHubsClient source code is shared on github:</span></p>
<p><span style="font-size: small;"><a href="https://github.com/hdinsight/eventhubs-client">https://github.com/hdinsight/eventhubs-client</a></span></p>
<h1><span style="font-size: small;">4. Achieving at-least-once semantics</span></h1>
<p><span style="font-size: small;">In general there are two types of receivers, the regular receiver and the reliable receiver. Reliable receiver aims at providing at-least-once semantics, meaning each message is guaranteed to be processed at least once. Regular (or unreliable) receiver do not guarantee at-least once semantics.&nbsp; But with regular receiver you can achieve higher throughput. So if you don't need at-least-once semantics then use the regular receiver.</span></p>
<p><span style="font-size: small;">To the best of my knowledge, the only way to achieve exactly-once semantics in Spark Streaming is to use Kafka as the data source, and use direct stream (DirectKafkaInputDStream.scala) without a receiver.</span></p>
<p><span style="font-size: small;">In HDInsight, we provide both EventHubsReceiver and ReliableEventHubsReceiver so you can choose what you need. The difference in implementation resides in when to do checkpoint. We checkpoint the message offsets in&nbsp;HDFS (in HDInsight this is WASB). Since Block Generator keeps received data in memory for a block interval, it has the risk of losing data when the receiver crashes. ReliableEventHubsReceiver only checkpoints after a block is committed to Block Manager, therefore avoiding data loss. ReliableEventHubsReceiver also needs to work with a Spark Streaming feature called&nbsp;WAL (Write Ahead Log). With WAL enabled, the Block Generator writes a block of data to WAL as well as the Block Manager, avoiding data loss in the later stages of the pipeline. If the&nbsp;driver crashed and restarted, it can reconstruct the RDD partitions from the WAL.</span></p>
<p><span style="font-size: small;">So how do you choose to use the ReliableEventHubsRecriver? You don't need to modify any of the&nbsp;application code (e.g. call EventHubsUtils.createUnionStream() to create a Dstream).&nbsp;You can simply enable WAL (set configuration spark.streaming.receiver.writeAheadLog.enable to true) to enable ReliableEventHubsReceiver.</span></p>
<h1><span style="font-size: small;">5. High Availability (HA)</span></h1>
<p><span style="font-size: small;">The tutorial we mentioned earlier uses Zeppelin notebook to write a Spark Streaming application. This is quick and convenient, however, it is not production ready. Zeppelin runs the driver on the head node, which will fail in the case of head node failover.&nbsp;Production streaming application needs to run 24x7, regardless of arbitrary node crashes in the cluster.</span></p>
<p><span style="font-size: small;">To achieve High Availability in HDInsight Spark cluster, you need to 1) enable driver checkpointing and 2) RDP to the cluster and submit the Spark Streaming application in cluster mode with supervise:</span></p>
<p style="padding-left: 30px;"><span style="font-size: small;">spark-submit.cmd --deploy-mode cluster --supervise &hellip;</span></p>
<p><span style="font-size: small;">This is how HA works in different scenarios:</span></p>
<p><span style="font-size: small;">1) Head node failover</span></p>
<p><span style="font-size: small;">First, we need sparkmaster HA. This means the active sparkmaster saves metadata to Zookeeper, and when head node failover happens, the standby sparkmaster reads metadata from Zookeeper and continue to operate. We have enabled sparkmaster HA by default in HDInsight, so there is no action needed by the user.</span></p>
<p><span style="font-size: small;">Second, we need to submit the application in cluster mode. By default, Spark Streaming driver runs on the head node. During head node failover, the driver is lost and the application is killed. Spark provides a cluster mode in which the driver is shipped to a worker node to run.</span></p>
<p><span style="font-size: small;">2) Worker node failure</span></p>
<p><span style="font-size: small;">If a worker node dies, the tasks assigned to the executors on that worker will be re-assigned somewhere else. There is no problem here. However, if the worker node that runs the driver dies, we need to relaunch the driver. Spark provides a supervise feature in cluster mode&nbsp;that sparkmaster periodically pings the driver and restarts the driver on a different node if it crashed.</span></p>
<p><span style="font-size: small;">Furthermore, the restarted driver should be able to pick up from previous state of the old driver. For this to work we need to enable driver checkpointing. With checkpointing the driver's metadata is stored in HDFS periodically. During startup,&nbsp;the driver&nbsp;tries to read data from the checkpoint folder, and creates StreamingContext from the checkpointed data if found.</span></p>
<p><span style="font-size: small;">For an example of the Spark Streaming application with HA, take a look at this github project:</span></p>
<p><span style="font-size: small;"><a href="https://github.com/hdinsight/hdinsight-spark-examples">https://github.com/hdinsight/hdinsight-spark-examples</a></span></p>
<h1><span style="font-size: small;">6. Storm vs. Spark Streaming</span></h1>
<p><span style="font-size: small;">Since the inception of Spark Streaming, people are trying to compare it with Apache Storm - an existing successful distributed streaming platform. If you search online, you'll find many articles&nbsp;highlighting the difference as Storm being one-message-at-a-time vs. Spark Streaming's micro-batching implementation. This is only partially true. Regular Storm topology processes one message at a time, which results in low latency but also low throughput. Storm Trident, a software layer on top of Storm, can also do micro-batching and a bunch of high level data transformations.</span></p>
<p><span style="font-size: small;">These are my observations after working on both technologies for a while:</span></p>
<p><span style="font-size: small;">1) Storm is more flexible. With Storm, you can specify the exact processing topology and parallelism levels. With Trident, you can easily achieve&nbsp;exactly-once semantics, which is very hard to achieve in Spark Streaming (as of 1.3).</span></p>
<p><span style="font-size: small;">2) Storm is more reliable. We have been running Storm applications for months and they keep running as expected. As of Spark 1.3, we've observed occasional crashes for Spark Streaming.</span></p>
<p><span style="font-size: small;">3) Spark Streaming is easier to use. Spark Streaming provides higher level abstractions and APIs which make it easier to write business logic. In particular, Spark Streaming provides windowing aggregates out of box, which is not available in Storm.</span></p>
<p><span style="font-size: small;">4) Spark Streaming has an ecosystem. The biggest advantage of Spark Streaming is that it is part of Spark ecosystem. You can use the rich Spark core data transformation functions once the data is pushed into Spark. Another benefit is that if you are interested in implementing an Lambda architecture, your real time and batch data processing can share the same code base.</span></p>
<p><span style="font-size: small;">I also want to stress that Spark Streaming is evolving fast.&nbsp;it is still undergoing heavy development. New features are added constantly. E.g. write ahead log is introduced in 1.2 and direct Kafka stream is introduced in 1.3. So it's reasonable to believe that Spark Streaming will become more feature rich and reliable over time.</span></p>
<p><span style="font-size: small;">So when to use what? My&nbsp;recommendation is this: if you are into Spark and you plan to move your data platform to Spark someday in the future, choose Spark Streaming; otherwise stay with Storm. If you need exactly-once semantics in your application, I would recommend you to use Storm Trident.</span></p>]]></content:encoded>
    </item>
    <item>
      <title>Performance Tuning for HDInsight Storm and Microsoft Azure EventHubs</title>
      <link>https://docs.microsoft.com/archive/blogs/shanyu/performance-tuning-for-hdinsight-storm-and-microsoft-azure-eventhubs</link>
      <pubDate>Thu, 14 May 2015 23:19:00 GMT</pubDate>
      <dc:creator><![CDATA[Shanyu Zhao]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/shanyu/2015/05/14/performance-tuning-for-hdinsight-storm-and-microsoft-azure-eventhubs/</guid>
      <description><![CDATA[Apache Storm is a popular real time data processing framework. Microsoft Azure HDInsight provides a...]]></description>
      <content:encoded><![CDATA[<p>Apache Storm is a popular real time data processing framework. Microsoft Azure HDInsight provides a service to deploy a Storm cluster in the cloud. Customers can readily use HDInsight Storm clusters to process data from Azure EventHubs using a Java based spout implementation. The EventHubSpout source code has been integrated into Apache Storm trunk. You can find the code here:<br /><a href="https://github.com/apache/storm/tree/master/external/storm-eventhubs">https://github.com/apache/storm/tree/master/external/storm-eventhubs</a></p>
<p>Note that EventHubSpout won't be available until Storm 0.11.0. Before that we keep the latest and greatest jar here:<br /><a href="https://github.com/hdinsight/hdinsight-storm-examples/tree/master/lib/eventhubs">https://github.com/hdinsight/hdinsight-storm-examples/tree/master/lib/eventhubs</a></p>
<h1>Performance Basics</h1>
<p>One frequently asked question is about the performance capability of the HDInsight Storm + EventHubs solution. Note that the precise performance depends on the specific Storm topology and the business logic of the application. But in most cases, you'll find EventHubs is the bottleneck. Note that you can always increase the cluster size if Storm is the bottleneck.</p>
<p>The throughput of EventHubs is governed by the concept of Throughput Unit (TU), according to (<a href="https://azure.microsoft.com/en-us/pricing/details/event-hubs/">https://azure.microsoft.com/en-us/pricing/details/event-hubs/</a>). 1 TU means 1MB/s or 1000 message/s ingress, 2MB/s or 2000 message/s egress (The message/s limit for egress is not enforced yet as of 5/15/2015). When Storm pulls data from EventHubs, the receive throughput is governed by the EventHubs egress limit. By default your EventHubs has 1 TU and you can change the throughput unit for your EventHubs namespace in Azure portal to up to 20 TU. Note that there are also protocol overhead in the order of 50 bytes per message. So if your message is 100 byte, with 20 TU, you can achieve 350-400K message/s throughput when pulling data into Storm topology today. When message/s egress limit is enforced at EventHubs server side, you can only achieve 40K message/s. In real time scenario, the throughput also depends on the EventHubs ingress limit because the data has to be sent to EventHubs before it can be consumed by Storm. In that case, the maximum throughput you can get is 20MB/s or 20K message/s.</p>
<p>If you need more throughput, you can call EventHubs support to increase the Throughput Unit to up to 1000. This means that you can achieve up to 1GB/s, or 1M message/s throughput using EventHubs.</p>
<p>EventHubs also support the concept of partitions. EventHubs only guarantee sequence delivery of messages within each partition. Messages from different partitions can be processed in parallel. EventHubs also has 5 TU limit on each partition.</p>
<p>For better performance the number of tasks for EventHubSpout should always match the number of partitions. For best performance, we recommend running 1 EventHubSpout task per node.</p>
<p>In some situations, you may find that the Storm cluster is the performance bottleneck. You can verify this by checking the CPU utilization of the worker node while the topology is running. If it is too high, you need to increase your cluster size. But it is rarely useful to increase the cluster size beyond the number of partitions.</p>
<h1>Performance Tuning Tips</h1>
<p>In general, we recommend setting the cluster size to be the same of the number of partitions in EventHubs so that each node is dedicated to 1 partition. Having a larger cluster size than the number of partitions means you can run data processing bolts in dedicated nodes. The downside of this situation is that Storm has to shuffle tuples across nodes when sending tuples from spout to bolt, introducing latency and overhead for serialization and de-serialization. If you are not doing much business logic in your topology, you might be safe to reduce the cluster to half or 1/4 of the number of partitions.</p>
<p>By default, Storm processes 1 message at a time (unless you are looking at Trident which does micro-batching), which should result in pretty low latency. If you want to further reduce latency, you need to optimize processing code in bolts and reduce the number of bolts in your topology. You may also consider choosing A8 or A9 node types when creating HDInsight Storm clusters because they are optimized for network speed.</p>
<p>The same tricks to reduce latency also work to increase throughput in the case of high CPU utilization in your cluster. Furthermore, if you are OK with losing tuples occasionally, you may consider turning off ack. This will greatly reduce CPU utilization. To do this, you can set topology.acker.executors to 0 during cluster creation time or in code do something like this: config.setNumAckers(0).</p>
<p>Another trick to improve performance is to use localOrShuffleGrouping() instead of shuffleGrouping() to connect EventHubSpout to the downstream bolts. What this does is to tell Storm to send a tuple to the bolt instance in the same worker process, eliminating the cost of inter-worker communication. For more info on Storm internal messaging, see:<br /><a href="https://www.michael-noll.com/blog/2013/06/21/understanding-storm-internal-message-buffers/">https://www.michael-noll.com/blog/2013/06/21/understanding-storm-internal-message-buffers/</a></p>
<h1>Benchmark Results</h1>
<p>We wrote a simple benchmark to test the performance of HDInsight Storm with EventHubs. You can find the source code here:<br /><a href="https://github.com/hdinsight/hdinsight-storm-examples/tree/master/EventCountExample">https://github.com/hdinsight/hdinsight-storm-examples/tree/master/EventCountExample</a></p>
<p>Our topology is a simple 3 layer topology that counts the number of messages received from EventHubs.<br />EventHubSpout&nbsp;&nbsp;&nbsp; --(localOrShuffleGrouping)-&gt;&nbsp;&nbsp;&nbsp; PartialCountBolt&nbsp;&nbsp;&nbsp; --(GlobalGrouping)-&gt;&nbsp;&nbsp; &nbsp;GlobalCountBolt</p>
<p>We use an EventHubs entity of 32 partitions, scaled to 20 TU. Message size is 100 bytes. We first pre-populate data in EventHubs using an event generator Storm topology, then stop that topology and start the EventCount topology. Note that using a Storm topology to generate events in high speed is important: if you pre-load data using a single threaded program, you are not going to achieve high throughput in EventCount topology. This is mainly due to the way how EventHubs arrange and store data as they are sent to EventHubs in different speed. Based on our previous discussion, the theoretical limit of throughput is 400K message/s. And once the egress message/s limit is enforced in EventHubs, this will become 40K message/s.</p>
<p>For the EventCount topology, we set the task number of the spout equal to the number of partitions, the number of workers in the topology equals the number of partitions. These are the results:</p>
<p>1) For an 8 node HDInsight Storm cluster, we can achieve 200K message/s. In this case each node is responsible for processing 4 partitions. We observed that the CPU utilization on worker node of Storm cluster is at 100% therefore the Storm cluster is the bottleneck.</p>
<p>2) For a 32 node cluster, we can achieve about 350K message/s, pretty close to the theoretical limit. The CPU utilization is at about 70%.</p>
<p>We also tested with a privately created 128 partition EventHubs with 100 TU. In this test we achieved 1M message/s with 100 node (default node size) HDInsight Storm cluster.</p>
<p>&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>HDInsight Storm Topology Submission Via VNet</title>
      <link>https://docs.microsoft.com/archive/blogs/shanyu/hdinsight-storm-topology-submission-via-vnet</link>
      <pubDate>Tue, 28 Oct 2014 12:12:28 GMT</pubDate>
      <dc:creator><![CDATA[Shanyu Zhao]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/shanyu/2014/10/28/hdinsight-storm-topology-submission-via-vnet/</guid>
      <description><![CDATA[1. Introduction
To submit a Storm topology to an HDInsight cluster, a user can RDP to the headnode...]]></description>
      <content:encoded><![CDATA[<h1>1. Introduction</h1>
<p>To submit a Storm topology to an HDInsight cluster, a user can RDP to the headnode of the cluster and run storm command. This is not always convenient. It is actually possible to submit a Storm topology from outside of an HDInsight cluster. The idea is to create an HDInsight Storm cluster with a configured Virtual Networks (VNet), and submit Storm topology from a machine that is connected to the VNet.</p>
<p>There are many types of VNet so with VNet support we can actually submit topology from Azure VM, other Azure services, on-premises infrastructure or developer boxes.</p>
<p>To show case the idea, I&rsquo;ll show you how to use an Azure VM to submit a Storm topology via VNet.</p>
<h1>2. Step-by-step Instructions</h1>
<p style="margin: 0in 0in 0pt;"><span style="color: black; font-family: 'Calibri',sans-serif; font-size: 11pt;">1) Create a Cloud-Only VNet in Azure portal. You can use the &ldquo;QUICK CREATE&rdquo; button.</span></p>
<p>&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/50/5808.create_vnet.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-50/5808.create_5F00_vnet.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/50/5808.create_vnet.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-50/5808.create_5F00_vnet.png" alt="" border="0" /></a>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="color: black; line-height: 107%; font-family: 'Calibri',sans-serif; font-size: 11pt; mso-fareast-font-family: SimSun; mso-fareast-theme-font: minor-fareast; mso-bidi-font-family: 'Times New Roman'; mso-bidi-theme-font: minor-bidi; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA;">2) Create a VM using the created VNet, this will be the VM from which we submit Storm topology. You need to use &ldquo;FROM GALLERY&rdquo; button and on page 4 you need to choose the VNet that we just created.</span></p>
<p>&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/50/7002.create_vm1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-50/7002.create_5F00_vm1.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/50/7002.create_vm1.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-50/7002.create_5F00_vm1.png" alt="" border="0" /></a></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/50/8836.create_vm2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-50/8836.create_5F00_vm2.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/50/8836.create_vm2.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-50/8836.create_5F00_vm2.png" alt="" border="0" /></a></p>
<p><span style="color: black; font-family: 'Calibri',sans-serif; font-size: 11pt;">3) Create a Storm cluster using the created VNet. Note you need to use &ldquo;custom create&rdquo; and specify the VNet name in Region/Virtual Network section.</span></p>
<p>&nbsp;<a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/50/1220.create_storm.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-50/1220.create_5F00_storm.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/50/1220.create_storm.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-50/1220.create_5F00_storm.png" alt="" border="0" /></a>&nbsp;</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/50/8311.create_storm2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-50/8311.create_5F00_storm2.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/50/8311.create_storm2.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-50/8311.create_5F00_storm2.png" alt="" border="0" /></a></p>
<p style="margin: 0in 0in 0pt;"><span style="color: black; font-family: 'Calibri',sans-serif; font-size: 11pt;">4) Find out the FQDN of the active head node of HDInsight Storm cluster using REST API.</span></p>
<p>This is a Powershell script to help you get the FQDN of the active head node:</p>
<p><span style="color: #0000ff;">function Get-ActiveFQDN(</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; [String]</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; [Parameter( Position=0, Mandatory=$true )]</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; $ClusterDnsName,</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; [String]</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; [Parameter( Position=1, Mandatory=$true )]</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; $Username,</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; [String]</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; [Parameter( Position=2, Mandatory=$true )]</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; $Password)</span><br /><span style="color: #0000ff;">{</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; $DnsSuffix = ".azurehdinsight.net"</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; $ClusterFQDN = $ClusterDnsName + $DnsSuffix</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; $webclient = new-object System.Net.WebClient</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; $webclient.Credentials = new-object System.Net.NetworkCredential($Username, $Password)</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; $Url = "https://" + $ClusterFQDN + "/clusteravailability/status"</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; $Response = $webclient.DownloadString($Url)</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; $JsonObject = $Response | ConvertFrom-Json</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; Write-host $JsonObject.LeaderDnsName</span><br /><span style="color: #0000ff;">}</span></p>
<p>&nbsp;&nbsp;<br />This script will print out something like this:</p>
<p><span style="color: #0000ff;">headnode1.&lt;clusterdnsname&gt;.b1.internal.cloudapp.net</span></p>
<p>5) RDP to the Azure VM we just created. Copy Storm bits from HDInsight head node (c:\apps\dist\storm-xxx or %STORM_HOME%) to Azure VM (let&rsquo;s say we copy to c:\storm folder); Install Java 1.7 runtime (either Oracle or OpenJDK is fine).</p>
<p>6) On the Azure VM, make sure the following configurations (environment variable and Storm configurations) are correctly set:</p>
<p>Environment variable:</p>
<p>&nbsp;&nbsp;&nbsp; <span style="color: #0000ff;">JAVA_HOME = "&lt;your java installation path&gt;"</span></p>
<p>storm.yaml (c:\storm\conf\storm.yaml):</p>
<p>&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;"> nimbus.host: headnode1.&lt;clusterdnsname&gt;.b1.internal.cloudapp.net</span></p>
<p>7) On the Azure VM, submit a Storm topology using storm.cmd command line like this:</p>
<p><span style="color: #0000ff;">C:\storm\bin&gt;storm jar ..\contrib\storm-starter\storm-starter-&lt;version&gt;-jar-with-dependencies.jar storm.starter.WordCountTopology wordcountSampleTopology</span></p>
<p>Then on the Azure VM you can manage topology status using Storm UI web page (start IE and enter the address like this):</p>
<p><span style="color: #0000ff;">https://headnode1.&lt;clusterdnsname&gt;.b1.internal.cloudapp.net:8772/</span></p>
<p>This is how easy it is. Enjoy storming!</p>]]></content:encoded>
    </item>
    <item>
      <title>Hadoop Yarn memory settings in HDInsight</title>
      <link>https://docs.microsoft.com/archive/blogs/shanyu/hadoop-yarn-memory-settings-in-hdinsight</link>
      <pubDate>Thu, 31 Jul 2014 22:29:00 GMT</pubDate>
      <dc:creator><![CDATA[Shanyu Zhao]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/shanyu/2014/07/31/hadoop-yarn-memory-settings-in-hdinsight/</guid>
      <description><![CDATA[(Edit: thanks Mostafa for the valuable feedback, I updated this post with explanation about the...]]></description>
      <content:encoded><![CDATA[<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">(Edit: thanks Mostafa for the valuable feedback, I updated this post with explanation about the relationship between Yarn base and Java base memory settings)</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">There are several related memory settings for jobs running in HDInsight cluster which most customers need to pay close attention to. When not correctly set, it will cause obscure failures in Hive/Pig/Mapreduce/Tez jobs.</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">Note that HDInsight service provides default memory&nbsp;settings, however, the defaults may be subject to change as we tune the service for various workloads or as we move to different VM types and hardware. It is advised that customers explicit set these settings once they know the right settings for their specific jobs. There are two ways to apply these settings: 1) provide it when creating HDInsight cluster using SDK. or 2) set it on a per job basis. E.g. use "-Define" option in Powershell SDK, or&nbsp;"set property=value" in a hive script, or set it in mapreduce code directly. Note that the Yarn level settings can only be changed during cluster creation.</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;"><strong>1. Yarn memory settings:</strong></p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">HDInsight 3.x service deploys Hadoop 2.x clusters. Hadoop 2.x (Yarn) introduced the concept of containers. Unlike Hadoop 1.x where each node is assigned a fixed number of "slots", in Hadoop 2.x each Yarn task (mapper, reducer or Tez task) is assigned a container which has an memory limit. This affects 1) how many containers can run in parallel in any given node; and 2) Yarn Node Manager will monitor the memory usage of the task and kill a container when the memory usage exceeds that limit.</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">Yarn&nbsp;defines how much memory is available for allocation and what is the minimum and maximum container size:</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">yarn.nodemanager.resource.memory-mb = 5376</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">yarn.scheduler.minimum-allocation-mb = 768</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">yarn.scheduler.maximum-allocation-mb = 5376</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">Note that you can only ask for container size of multiples of minimum-allocation-mb. In the above example settings, if you ask for a container of size 1024MB, you will actually get a container of 1536MB.</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;"><strong>2. Mapreduce memory settings:</strong></p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">These are the default Yarn container memory settings in HDInsight for the mapper, reducer and AM(Application Master):</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">mapreduce.map.memory.mb = 768</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">mapreduce.reduce.memory.mb = 1536</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">yarn.app.mapreduce.am.resource.mb = 1536</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">This is a typical error message in your job attempt log, if these limits are exceeded:</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; padding-left: 30px; font-family: Calibri; font-size: 11pt;"><em>Container[pid=container_1406552545451_0009_01_000002,containerID=container_1406552545451_0009_01_000002] is running beyond physical memory limits. Current usage: 519.1 MB of 512 MB physical memory used; 770.1 MB of 1.0 GB virtual memory used. Killing container. Dump of the process-tree for container_1406552545451_0009_01_000002 : |- PID </em><em>CPU_TIME(MILLIS) VMEM(BYTES) WORKING_SET(BYTES) |- 4912 15 667648 2502656 |-4712 9546 232022016 97697792 |- 6000 78 1867776 2605056 |- 4780 50234 571166720 </em><em>438947840 |- 4516 31 1810432 2588672 Container killed on request. Exit code is 137</em></p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">Aside from the memory monitoring, each Java process has its own heap space settings. These are the default settings for the mapper, reducer and AM:</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">mapreduce.map.java.opts = "-Xmx512m"</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">mapreduce.reduce.java.opts = "-Xmx1024m"</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">yarn.app.mapreduce.am.command-opts = "-Xmx1024m"</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">This is a typical error message in your job attempt log if these limits are exceeded:</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; padding-left: 30px; font-family: Calibri; font-size: 11pt;"><em>Error: java.lang.RuntimeException: java.lang.OutOfMemoryError: GC overhead limit exceeded</em></p>
<p style="margin: 0in; padding-left: 30px; font-family: Calibri; font-size: 11pt;"><em>or</em></p>
<p style="margin: 0in; padding-left: 30px; font-family: Calibri; font-size: 11pt;"><em>Error: java.lang.RuntimeException: java.lang.OutOfMemoryError: Java heap space</em></p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">The Yarn based and Java based&nbsp;settings are related. The Java heap settings should be smaller than the Yarn container memory limit because we need reserve memory for Java code. The best practice is to reserve 20% memory&nbsp;for code.&nbsp;So if settings are correct,&nbsp;theoretically pure Java-based Hadoop tasks should never get killed by Yarn Node Manager unless there is a bug in your Java code somewhere. If the Yarn based error is seen, the cure is to either increase the Yarn container&nbsp;memory or decrease Java heap space. If the Java heap error is seen, you can either increase both memory settings (in which case you'll get fewer tasks running in parallel), or bring down the memory usage if possible.</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">For streaming jobs, the developer needs to make sure the streaming program don't&nbsp;exceeds&nbsp;Yarn container memory settings. This might require trial run and iterative&nbsp;tuning.</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">Eventually the memory usage depends on the job you are doing. For example, if you are doing hive query "CREATE TABLE AS SELECT" on huge tables&nbsp;your mapper may demand more memory than 512MB. To increase memory settings for the mapper, you can overwrite these settings in Mapreduce configuration:</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">mapreduce.map.memory.mb = 1536</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">mapreduce.map.java.opts = "-Xmx1024m"</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">There is another memory setting that depends on the container memory size:</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">mapreduce.task.io.sort.mb = 307</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">This is the max memory a mapreduce task can use to sort data in buffer during the shuffle stage. This value should be 1/3 to 1/2 of the task heap size.</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">This is an illustration of various memory&nbsp;settings&nbsp;for Mapreduce to help you visualize the relative size of them:</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/50/7652.HadoopConfigurations_mr.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-50/7652.HadoopConfigurations_5F00_mr.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/50/7652.HadoopConfigurations_mr.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-50/7652.HadoopConfigurations_5F00_mr.png" alt="" border="0" /></a></p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;"><strong>3. Tez memory settings</strong></p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">These are the default Tez memory settings for Tez AM:</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">tez.am.resource.memory.mb = 1536</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">tez.am.java.opts = 1024</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">For tez container, it uses mapper's memory settings:</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">mapreduce.map.memory.mb = 768</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">mapreduce.map.java.opts = "-Xmx512m"</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">This is an illustration of various memory&nbsp;settings&nbsp;for Tez:</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/50/2335.HadoopConfigurations_tez.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-50/2335.HadoopConfigurations_5F00_tez.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/50/2335.HadoopConfigurations_tez.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-50/2335.HadoopConfigurations_5F00_tez.png" alt="" border="0" /></a></p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;"><strong>4. Hive memory settings for Tez:</strong></p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">When using Tez for Hive, you can specify Tez task's memory settings, these are default values:</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">hive.tez.container.size = -1</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">hive.tez.java.opts = ""</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">The default&nbsp;settings mean that the actual Tez task will use the mapper's memory setting:</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">hive.tez.container.size = mapreduce.map.memory.mb</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">hive.tez.java.opts = mapreduce.map.java.opts</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">If you want to have&nbsp;Tez&nbsp;use different memory setting from the Mapreduce framework, you can modify these settings for Hive configuration.</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">There is another important memory setting in hive that depends on Tez container size:</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">hive.auto.convert.join.noconditionaltask.size = 159519866</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">This is memory used for caching smaller joining table. During hive join operation, if the smaller one of the&nbsp;two joined tables is smaller than this value, hive will perform map side join, which is significantly faster. This&nbsp;value should fit in the container memory along with the io.sort.memory, as shown in this illustration for Hive on Tez:</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/50/2538.HadoopConfigurations_hiveontez2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-50/2538.HadoopConfigurations_5F00_hiveontez2.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/66/50/2538.HadoopConfigurations_hiveontez2.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-66-50/2538.HadoopConfigurations_5F00_hiveontez2.png" alt="" border="0" /></a></p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;"><strong>5. WebHCat memory settings:</strong></p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">WebHCat(also known as Templeton) uses Mapreduce job (the LaunchMapper) to submit user's Hadoop job. So the Mapreduce memory settings are also applicable to WebHCat's LaunchMapper. However, usually the LaunchMapper will need more memory than the default mapper memory limit of 512MB. For example, for a user's Hive job submitted through WebHCat, LaunchMapper will call hive command line which may start local task that requires close to 1GB memory. In this case you can use this&nbsp;configuration to set LaunchMapper's memory limit to 1GB:</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">templeton.mapper.memory.mb&nbsp;= 1024</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;">&nbsp;</p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;"><strong>References:</strong></p>
<p style="margin: 0in; font-family: Calibri; font-size: 11pt;"><a href="https://docs.hortonworks.com/HDPDocuments/HDP2/HDP-2.0.9.1/bk_installing_manually_book/content/rpm-chap1-11.html">https://docs.hortonworks.com/HDPDocuments/HDP2/HDP-2.0.9.1/bk_installing_manually_book/content/rpm-chap1-11.html</a></p>]]></content:encoded>
    </item>
  </channel>
</rss>