Heron-新一代实时流处理

来源:互联网 发布:分布式算法导论 pdf 编辑:程序博客网 时间:2024/05/21 18:07
<div id="main">
                <div class="main">
                        <div class="ad_class">
<div class="notice tracking-ad" data-mod="popu_3"> 




<a href="http://blog.csdn.net/blogdevteam/article/details/62217619" target="_blank">
<font color="red">CSDN日报20170315——《年近 30 ------职业回顾与思考》</font></a>


&nbsp;&nbsp;&nbsp;&nbsp;


<a href="http://blog.csdn.net/turingbooks/article/details/58072986" target="_blank">
<font color="blue">程序员2月书讯
</font></a>


&nbsp;&nbsp;&nbsp;


<a href="http://edu.csdn.net/huiyiCourse/detail/284" target="_blank">
<font color="red">【直播】用面向协议的思想简化网络请求
</font></a>
&nbsp;&nbsp;&nbsp;


<a href="http://blog.csdn.net/blogdevteam/article/details/60961185" target="_blank">
<font color="blue">博客一键搬家活动开始啦
</font></a>


</div>                        </div>
                        






  
<link href="http://static.blog.csdn.net/css/comment1.css" type="text/css" rel="stylesheet">
<link href="http://static.blog.csdn.net/css/style1.css" type="text/css" rel="stylesheet">
<script language="JavaScript" type="text/javascript" src="http://download.csdn.net/js/jquery.cookie.js"></script>
<script type="text/javascript" src="http://c.csdnimg.cn/rabbit/search-service/main.js"></script>
<link rel="stylesheet" href="http://static.blog.csdn.net/public/res-min/markdown_views.css?v=1.0">
<link rel="stylesheet" href="http://static.blog.csdn.net/css/category.css?v=1.0">
<script type="text/javascript" src="http://static.blog.csdn.net/public/res/bower-libs/MathJax/MathJax.js?config=TeX-AMS_HTML"></script>
<script type="text/javascript" src="http://static.blog.csdn.net/scripts/web-storage-cache.min.js"></script>
<script type="text/javascript" src="http://static.blog.csdn.net/scripts/replace.min.js"></script>








  <script type="text/ecmascript">
      window.quickReplyflag = true;
           
            var isBole = false;
            
      
      var fasrc="http://my.csdn.net/my/favorite/miniadd?t=Heron+%e6%96%b0%e4%b8%80%e4%bb%a3%e6%b5%81%e5%a4%84%e7%90%86%e6%a1%86%e6%9e%b6%e8%af%a6%e8%a7%a3&u=http://blog.csdn.net/u013573133/article/details/49180543"


    </script>
<div id="article_details" class="details">
    <div class="article_title">   
         <span class="ico ico_type_Original"></span>




    <h1>
        <span class="link_title"><a href="/u013573133/article/details/49180543">
        Heron 新一代流处理框架详解            
        </a></span>
    </h1>
</div>


   


        <div class="article_manage clearfix">
        <div class="article_l">
            <span class="link_categories">
            标签:
              <a href="http://www.csdn.net/tag/Architecture" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">Architecture</a><a href="http://www.csdn.net/tag/%e5%a4%a7%e6%95%b0%e6%8d%ae" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">大数据</a><a href="http://www.csdn.net/tag/storm" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">storm</a><a href="http://www.csdn.net/tag/heron" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">heron</a><a href="http://www.csdn.net/tag/%e6%9e%b6%e6%9e%84" target="_blank" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">架构</a>
            </span>
        </div>
        <div class="article_r">
            <span class="link_postdate">2015-10-16 16:36</span>
            <span class="link_view" title="阅读次数">328人阅读</span>
            <span class="link_comments" title="评论次数"> <a href="#comments" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_pinglun'])">评论</a>(0)</span>
            <span class="link_collect tracking-ad" data-mod="popu_171"> <a href="javascript:void(0);" onclick="javascript:collectArticle('Heron+%e6%96%b0%e4%b8%80%e4%bb%a3%e6%b5%81%e5%a4%84%e7%90%86%e6%a1%86%e6%9e%b6%e8%af%a6%e8%a7%a3','49180543');return false;" title="收藏" target="_blank">收藏</a></span>
             <span class="link_report"> <a href="#report" onclick="javascript:report(49180543,2);return false;" title="举报">举报</a></span>


        </div>
    </div>
    <div class="embody" style="display:none" id="embody">
        <span class="embody_t">本文章已收录于:</span>
        <div class="embody_c" id="lib" value="{&quot;err&quot;:0,&quot;msg&quot;:&quot;ok&quot;,&quot;data&quot;:[]}"></div>
    </div>
    <style type="text/css">        
            .embody{
                padding:10px 10px 10px;
                margin:0 -20px;
                border-bottom:solid 1px #ededed;                
            }
            .embody_b{
                margin:0 ;
                padding:10px 0;
            }
            .embody .embody_t,.embody .embody_c{
                display: inline-block;
                margin-right:10px;
            }
            .embody_t{
                font-size: 12px;
                color:#999;
            }
            .embody_c{
                font-size: 12px;
            }
            .embody_c img,.embody_c em{
                display: inline-block;
                vertical-align: middle;               
            }
             .embody_c img{               
                width:30px;
                height:30px;
            }
            .embody_c em{
                margin: 0 20px 0 10px;
                color:#333;
                font-style: normal;
            }
    </style>
    <script type="text/javascript">
        $(function () {
            try
            {
                var lib = eval("("+$("#lib").attr("value")+")");
                var html = "";
                if (lib.err == 0) {
                    $.each(lib.data, function (i) {
                        var obj = lib.data[i];
                        //html += '<img src="' + obj.logo + '"/>' + obj.name + "&nbsp;&nbsp;";
                        html += ' <a href="' + obj.url + '" target="_blank">';
                        html += ' <img src="' + obj.logo + '">';
                        html += ' <em><b>' + obj.name + '</b></em>';
                        html += ' </a>';
                    });
                    if (html != "") {
                        setTimeout(function () {
                            $("#lib").html(html);                      
                            $("#embody").show();
                        }, 100);
                    }
                }      
            } catch (err)
            { }
            
        });
    </script>
    <script type="text/javascript" src="http://static.blog.csdn.net/scripts/category.js"></script>  
        <div class="bog_copyright">         
            <p class="copyright_p">版权声明:本文为博主原创文章,未经博主允许不得转载。</p>
        </div>


  


  
  
     


<div style="clear:both"></div><div style="border:solid 1px #ccc; background:#eee; float:left; min-width:200px;padding:4px 10px;"><p style="text-align:right;margin:0;"><span style="float:left;">目录<a href="#" title="系统根据文章中H1到H6标签自动生成文章目录">(?)</a></span><a href="#" onclick="javascript:return openct(this);" title="展开">[+]</a></p><ol style="display:none;margin-left:14px;padding-left:14px;line-height:160%;"><li><a href="#t0">
</a></li><ol><li><a href="#t1">Topology Submit Sequence</a></li></ol></ol></div><div style="clear:both"></div><div id="article_content" class="article_content">


<h1 align="center" style="text-align:left"><a name="t0"></a><br>
</h1>
<div>&nbsp; &nbsp; &nbsp; 最近公司需要开发新的流式ETL框架,我负责调研和测试Storm/Heron框架。Storm已经是非常成熟的流式处理框架了,在很多公司都在用,但是它在设计上也有诸多诟病,于是Twiter又开发了新的框架来代替Strom,这就是Strom2.0的Heron框架。&nbsp;</div>
<div>&nbsp; &nbsp;&nbsp;</div>
<div>&nbsp; &nbsp; &nbsp; 既然是要深入研究一个新的框架,于是我这花了一个星期将Heron和Strom的官方文档翻译了一遍,以及一篇非常重要的流式处理论文(来自Twiter,Twiter Heron: Stream Processing at Scale),将内容整理如下。</div>
<div><br>
</div>
<div><br>
</div>
<ol style="margin-top:0mm; margin-bottom:0mm; margin-left:0mm; padding-left:0pt">
<li style="margin-left:61pt; margin-right:0pt; padding-left:-46pt; text-indent:0pt; font-family:����; font-size:14pt; font-weight:Bold">
<span style="font-family:����; font-size:18px"><span style="font-size:14pt">Storm介绍</span></span></li></ol>
<div align="left" style="margin-left:6mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Strom是一个流式数据实时计算系统,Strom的组件如下:</span></span></div>
<div align="left" style="text-indent:26.4567px; margin:0mm 0mm 0mm 6mm; min-height:15pt">
<span style="font-size:10pt; font-family:����; text-indent:0pt">&nbsp; &nbsp; &nbsp; 1. Nimbus:负责资源分配和任务调度。</span></div>
<ol start="2" style="margin-top:0mm; margin-bottom:0mm; margin-left:0mm; padding-left:0pt">
<li style="margin-left:59pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-size:12px"><span style="font-size:10pt">Supervisor:负责接受nimbus分配的任务,启动和停止属于自己管理的worker进程。</span></span></li><li style="margin-left:59pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Worker:运行具体处理组件逻辑的进程。</span></span></li><li style="margin-left:59pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Task:worker中每一个spout/bolt的线程称为一个task.</span></span></li><li style="margin-left:59pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Executor:在storm0.8之后,task不再与线程对应,同一个spout/bolt的task可能会共享一个线程,默认情况下,一个线程对应一个task。</span></span></li><li style="margin-left:59pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Topology:storm中运行的一个实时应用程序,因为各个组件间的消息流动形成逻辑上的一个拓扑结构。</span></span></li><li style="margin-left:59pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Spout:在一个topology中产生源数据流的组件。通常情况下spout会从外部数据源中读取数据,然后转换为topology内部的源数据。</span></span></li><li style="margin-left:59pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Bolt:在一个topology中接受数据然后执行处理的组件。Bolt可以执行过滤、函数操作、合并、写数据库等任何操作。</span></span></li><li style="margin-left:59pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Tuple:一次消息传递的基本单元,是一个value list.</span></span></li><li style="margin-left:59pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Stream:源源不断传递的tuple就组成了stream。</span></span></li></ol>
<div><span style="font-family:����"><span style="font-size:13.3333px"><img src="http://img.blog.csdn.net/20161218182505415?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzU3MzEzMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt=""><br>
</span></span></div>
<div><span style="font-family:����"><span style="font-size:13.3333px"><br>
</span></span></div>
<div><span style="font-family:����"><span style="font-size:13.3333px"><br>
</span></span></div>
<div><span style="font-family:����"><span style="font-size:13.3333px"><br>
</span></span></div>
<ol start="2" style="margin-top:0mm; margin-bottom:0mm; margin-left:0mm; padding-left:0pt">
<li style="margin-left:61pt; margin-right:0pt; padding-left:-46pt; text-indent:0pt; font-family:����; font-size:14pt; font-weight:Bold">
<span style="font-family:����; font-size:18px"><span style="font-size:14pt">Storm存在的缺陷</span></span>
<ol style="margin-top:0mm; margin-bottom:0mm; margin-left:0mm; padding-left:0pt">
<li style="margin-left:39pt; margin-right:0pt; text-indent:0pt; font-size:12pt"><span style="font-family:����">Woker进程设计上的缺陷</span></li></ol>
</li></ol>
<div align="left" style="margin-left:7mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">一台Supervisor运行着多个worker进程,每个worker进程跑着多个executor线程,而每个executor线程执行一个或多个task,storm有一套自己的优先算法来调度这一个executor线程在某个时间点应该run哪个task。但是,存在以下缺陷:</span></span></div>
<ol style="margin-top:0mm; margin-bottom:0mm; margin-left:0mm; padding-left:0pt">
<li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt; font-family:����">很难定位一个executor线程中的某个task的性能。</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Storm的worker就是一个JVM进程,每个worker可以跑多个executor线程,目前根据Storm现有的调度机制,我们无法确定那个task被分配到了哪个worker进程上,哪台物理机器上。由于不知道task被分配到哪个worker上,有可能是同一个,考虑join的情况,一个join task和一个output 到 DB Store或其他存储的task被分配到同一个worker,这样性能可能存在问题。</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt; font-family:����">一个executor线程会输出一个log文件,里面所有执行的task的信息都在里面,不好定位其中某个task的问题。</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt; font-family:����">当前正在跑的topology如果重启的话,之前分派在同一个worker的task由于toplogy重启,可能不会再被分配到同一个worker进程上,这给debug带来了困难。</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt; font-family:����">如果某个task有exception中断进程,整个worker进程被终止</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt; font-family:����">在实际的项目中,一个execuotr线程执行多个不同的task使得垃圾回收的问题很难 track down.</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Storm默认每个worker进程的资源都是一样的。例如,一个worker需要5G,一个worker需要10G,那么我们就需配10G,这两个worker进程都是10G,浪费5G空间。</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt; font-family:����">如果对一个worker进程进行heap dump时,可能会阻塞worker hearbeats的发送,导致supervisor认为该worker心跳超时,kill 和重启了该worker&nbsp;Debugging problems becomes quite challenging as a result of this behavior.</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Strom的worker进程使用线程来处理数据在task与worker进程之间的数据传输。在Strom中,每个tuple从进入storm到走出storm,在一个worker进程中需要通过四个线程的处理,这种设计很容易到达瓶颈,也很容易有Queue资源争夺的问题。 ( worker用thread和queue来做tuple的接收和发送,每个worker有一个receive-thread接收上游tuple,一个全局send-thread负责往下游发送tuple,然后executor有一个logic-thread来执行用户的代码逻辑,最后有一个本地的send-thread来做logic-thread和全局send-thread做数据通信,到这里,一个tuple需要从进入一个worker到出来总共要通过4个thread转发,效率很低。)</span></span></li></ol>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:13mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����"><span style="font-size:12pt"><strong>2.2&nbsp; Storm Nimbus的设计缺陷</strong></span></span></div>
<ol style="margin-top:0mm; margin-bottom:0mm; margin-left:0mm; padding-left:0pt">
<li style="margin-left:72pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Storm的Nimbus任务很多,包括调度,监听,分发JAR等等,topology非常多的时候,Nimbus将变成瓶颈。</span></span></li><li style="margin-left:72pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Nimbus不支持 worker进程细粒度的resource reservation和isolation。跑着不同Topology的worker进程在同一台Supervior上面运行,这会有抢资源相互影响的情况。Storm on YARN能够部分解决这种问题。</span></span></li><li style="margin-left:72pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Storm使用Zookeeper来管理supervisor和worker的心跳,这种方式限制了每个Topology的worker进程数,也限制了集群中topology的总数。 如果topology很多,每个topology的并发很多,这样Zookeeper就是瓶颈。</span></span></li><li style="margin-left:72pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Nimbus不是HA,Nimbus存在单点问题,一旦宕机,客户端将不能提交新的topology,也不能kill掉当前正在运行的topology。 Nimbus不是HA。</span></span></li></ol>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:13mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����"><span style="font-size:12pt"><strong>2.3&nbsp; 缺少Backpressure的机制</strong></span></span></div>
<div align="left" style="margin-left:7mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Storm没有backpressure机制,如果下游接收数据的bolt没有及时处理数据的话,上游发送者就会drop message。这是一种fail-fast机制,但是存在一些问题:</span></span></div>
<ol style="margin-top:0mm; margin-bottom:0mm; margin-left:0mm; padding-left:0pt">
<li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt; font-family:����">如果是一个已知的问题,某个bolt已经停止响应,这种机制将会无限制的 tuple drops,当处于production环境时,而我们却很难发现这些 tuple drops.</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Work done by upstream components is lost.</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<div style="margin-top:0pt; margin-bottom:14pt"><span style="font-family:宋体; font-size:12px"><span style="font-size:10pt; font-family:����">系统的行为变得不可预知.</span></span></div>
</li></ol>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:13mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����"><span style="font-size:12pt"><strong>2.4&nbsp; 效率的缺陷</strong></span></span></div>
<div align="left" style="margin-left:7mm; margin-right:0mm; text-indent:11mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">在Production环境中,我们会遇到各种各样的问题导致topology执行失败,导致 tuple&nbsp;failures, tuple replays, and execution lag。最常见的原因:</span></span></div>
<ol style="margin-top:0mm; margin-bottom:0mm; margin-left:0mm; padding-left:0pt">
<li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt; font-family:����">一个tuple的失败会导致整个tuple tree的失败,这个topology会重新跑一次这个tuple tree。效率很低。</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">topology会消耗大量的RAM来应对worker进程遇到GC超过一分钟的时刻,这会导致tuple失败的可能性</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt; font-family:����">当一个worker进程跑多个executor线程的时候,transfer queues里面会有很多tuple。</span></span></li></ol>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:10mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:18pt">
<span style="font-family:����; font-size:18px"><span style="font-size:14pt"><strong>3. Heron 介绍</strong></span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:11mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����"><span style="font-size:12pt"><strong>3.1&nbsp; Heron的设计目标</strong></span></span></div>
<div align="left" style="margin-left:7mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">(1) 完全兼容Strom API</span></span></div>
<div align="left" style="margin-left:7mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">(2) 在性能、稳定性和监控等方面,Heron将会高于Strom,在data model方面,Heron使用process-based model 代替Strom的thread-based model。</span></span></div>
<div align="left" style="margin-left:7mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">(3) 解决以上Storm存在的问题</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:13mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����"><span style="font-size:12pt"><strong>3.2&nbsp; Heron设计简介</strong></span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Heron是Storm的威力加强版,从架构的角度来看,Heron与Strom有着显著的不同,但是它却可以完美的兼容Strom API。用户通过Heron API发布topoloy到Scheduler。</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt"><img src="" alt=""><img src="http://img.blog.csdn.net/20161218182628303?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzU3MzEzMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt=""><br>
</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:10pt; font-family:宋体; text-indent:7mm">每一个topology都作为一个Aurora的job在运行。每一个job会在多个container去执行,这些container由Aurora来分配和调度。第一个container作为Topology Master,</span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体"><span style="font-size:10pt">其他的多个container中。每个container都会run一个Stream Manager,一个Metrics Manager和多个Heron Instances进程(spouts和bolts)。多个container可以运行在一个物理节点上。Aurora将会根据每个节点的资源去调度每个container。Standby Topology Master能够作为HA。所有的元数据信息包括谁提交的job,job的运行信息,启动时间等等都会保存在Zookeeper中。&nbsp;每个Heron
 Instance都是用java写的,且都是JVM进程。Heron进程之间用protocol buffers进行通信。</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:12pt; font-family:����; text-indent:8mm"><strong><img src="" alt=""><img src="http://img.blog.csdn.net/20161218182713747?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzU3MzEzMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" width="900" height="600"><br>
</strong></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:12pt; font-family:����; text-indent:8mm"><strong><br>
</strong></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:12pt; font-family:����; text-indent:8mm"><strong>3.3&nbsp; Topology</strong></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����"><span style="font-size:10pt">You can think of a Heron cluster as a mechanism for managing the lifecycle of stream-processing entities called&nbsp;topologies. More information can be found in the</span></span><a target="_blank" href="http://twitter.github.io/heron/docs/concepts/topologies"><span style="font-family:����; font-size:12px"><span style="font-size:10pt">Heron
 Topologies</span></span></a><span style="font-family:����; font-size:12px"><span style="font-size:10pt">&nbsp;document. (我们可以把Heron集群看作是一个用来管理流式处理实体的生命周期的一种机制,这种流式处理实体被叫做Topology)</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">topology是一个有向非闭环图(</span></span><a target="_blank" href="https://en.wikipedia.org/wiki/Directed_acyclic_graph"><span style="font-family:����; font-size:12px"><span style="font-size:10pt">directed
 acyclic graph</span></span></a><span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">),它被用来处理流式的数据. topologogy由三个基本部分组成:</span></span><a target="_blank" href="http://twitter.github.io/heron/docs/concepts/topologies/%20/l%20spouts"><span style="font-family:����; font-size:12px"><span style="font-size:10pt">spouts</span></span></a><span style="font-family:����; font-size:12px"><span style="font-size:10pt">&nbsp;and&nbsp;</span></span><a target="_blank" href="http://twitter.github.io/heron/docs/concepts/topologies/%20/l%20bolts"><span style="font-family:����; font-size:12px"><span style="font-size:10pt">bolts</span></span></a><span style="font-family:����; font-size:12px"><span style="font-size:10pt">,&nbsp;</span></span><a target="_blank" href="http://twitter.github.io/heron/docs/developers/data-model"><span style="font-family:����; font-size:12px"><span style="font-size:10pt">tuples</span></span></a><span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">,如下图:</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:10pt; font-family:����; text-indent:7mm"><img src="" alt=""><br>
</span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:10pt; font-family:����; text-indent:7mm"><img src="http://img.blog.csdn.net/20161218182814436?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzU3MzEzMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" width="900" height="600"><br>
</span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:10pt; font-family:����; text-indent:7mm">spout的作用是发送tuple到topology中,bolt的作用是处理这些tuple。在上面的图中,spout&nbsp;S1&nbsp;产生tuples供给给bolts&nbsp;B1&nbsp;和 B2&nbsp;来处理,bolt&nbsp;B1处理tuple后将结果供给给B3&nbsp;和 B4, 同样的, bolt&nbsp;B2处理tuple将结果供给给 B4.</span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����"><span style="font-size:10pt"><strong>3.3.1&nbsp; Topology 的生命周期</strong></span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">当部署好一个Heron集群后,我们可以通过Heron Client来提交一个topology到Heron集群中,我们可以使用这个Heron Client来管理整个Heron的生命周期,topology的生命周期包括以下几个阶段:</span></span></div>
<ol style="margin-top:0mm; margin-bottom:0mm; margin-left:0mm; padding-left:0pt">
<li style="margin-left:36pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<a target="_blank" href="http://twitter.github.io/heron/docs/operators/heron-cli%20/l%20submitting-a-topology"><span style="font-family:����; font-size:12px"><span style="font-size:10pt; color:rgb(0,0,0)">submit</span></span></a><span style="font-family:����; font-size:12px"><span style="font-size:10pt">topology:提交topology到Heron集群.
 此时,topology还没有进行流式处理,但是已经被激活.</span></span></li><li style="margin-left:36pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<a target="_blank" href="http://twitter.github.io/heron/docs/operators/heron-cli%20/l%20activating-a-topology"><span style="font-family:����; font-size:12px"><span style="font-size:10pt; color:rgb(0,0,0)">activate</span></span></a><span style="font-family:����; font-size:12px"><span style="font-size:10pt">topology.
 Topology即将开始流式处理,topology的处理架构已经创建.</span></span></li><li style="margin-left:36pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<a target="_blank" href="http://twitter.github.io/heron/docs/operators/heron-cli%20/l%20restarting-a-topology"><span style="font-family:����; font-size:12px"><span style="font-size:10pt; color:rgb(0,0,0)">restart</span></span></a><span style="font-family:����; font-size:12px"><span style="font-size:10pt">&nbsp;
 topology,当修改topology的配置后,需要重启topology</span></span></li><li style="margin-left:36pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<a target="_blank" href="http://twitter.github.io/heron/docs/operators/heron-cli%20/l%20deactivating-a-topology"><span style="font-family:����; font-size:12px"><span style="font-size:10pt; color:rgb(0,0,0)">deactivate</span></span></a><span style="font-family:����; font-size:12px"><span style="font-size:10pt">&nbsp;topology.
 当反激活topology后,topology将不会再处理流式数据,但是进程依然存在在集群中。</span></span></li><li style="margin-left:36pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<div style="margin-top:0pt; margin-bottom:14pt"><a target="_blank" href="http://twitter.github.io/heron/docs/operators/heron-cli%20/l%20killing-a-topology"><span style="font-family:����; font-size:12px"><span style="font-size:10pt; color:rgb(0,0,0)">kill</span></span></a><span style="font-family:����; font-size:12px"><span style="font-size:10pt">&nbsp;
 topology. 将topology从heron集群中彻底删除.</span></span></div>
</li></ol>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt"><strong>3.3.2&nbsp; Spouts</strong></span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">spout是流式数据的来源,其作用是把tuple数据供给给topology. spout可以读取Kafka、hdfs等数据源,将流式数据输出给一个或多个bolt.</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt"><strong>3.3.3&nbsp; Bolts</strong></span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">bolt会消费从spout传过来的tuple流,执行一系列自定义的流式处理的操作,bolt的流式处理操作包括performing complex stream transformations, performing storage operations, aggregating multiple streams into one, emitting tuples
 to other bolts within the topology, and much more.</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt"><strong>3.3.4&nbsp; Logical Plan</strong></span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">topology的逻辑计划(logic plan)有点类似与数据库查询的执行计划. 上图就是一个logicial plan的例子.</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt"><strong>3.3.5 Physical Plan</strong></span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">topology的物理计划(physical plan)是针对逻辑计划而言的, 物理计划(physical plan)是一个实际执行topology时候的拓扑计划图,其中包括 machines running each spout or bolt and more. 下图是一个物理计划:</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:12pt; font-family:����; text-indent:8mm"><strong><img src="" alt=""><img src="http://img.blog.csdn.net/20161218182858570?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzU3MzEzMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt=""><br>
</strong></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:12pt; font-family:����; text-indent:8mm"><strong>3.3&nbsp; Scheduler</strong></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体"><span style="font-size:10pt">这里的Scheduler是一个抽象的概念,我们可以使用Aurora调度器作为Scheduler。Aurora是一个通用的service调度器。Aurora的设计理念和Nimbus是一样的。当前Heron Scheduler支持Aurora,Local,Slurm,YARN。</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:8mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����"><span style="font-size:12pt"><strong>3.4&nbsp; State Manager</strong></span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Heron State Manager会跟踪与监控每个正在运行的topology,每个topology包括logical plan, physical plan和topology的执行状态,当前Heron State Manager支持Local File System, Zookeeper。</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:8mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����"><span style="font-size:12pt"><strong>3.5&nbsp; Uploader</strong></span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Heron uploader会分发topology的jar到各个服务器上来执行,Heron Uploader现在支持:HDFS,Local File System,Amazon S3</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:11mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����"><span style="font-size:12pt"><strong>3.6 Container</strong></span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">每个topology都会有多个containers,每个container里面又有多个Heron Instance进程, 和一个Stream Manager, 和一个 Metrics Manager. Containers会和Topology Master进行通信,以此来确保topology能够形成一个充分connected的拓扑图.</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:11mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����"><span style="font-size:12pt"><strong>3.7 Topology Master</strong></span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">TM(Topology Master)主要负责topology的throughout,在startup的时候,TM把信息存放在Zookeeper上,以便其他进程能够发现TM。所以TM有如下两个目的:</span></span></div>
<ol style="margin-top:0mm; margin-bottom:0mm; margin-left:0mm; padding-left:0pt">
<li style="margin-left:36pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt; font-family:����">阻止多个TM的产生</span></span></li><li style="margin-left:36pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt; font-family:����">允许其他属于该topology的进程发现该TMTopology Master管理topology,它会关注每个topology的status。</span></span></li><li style="margin-left:36pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">TM(Topology Master)作为一个gateway for topology metircs through an endpoint</span></span></li></ol>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Topology Master (TM) 管理着整个生命周期,从这个Topology被提交到Topology Master上,直到我们Kill掉这个Topology为止。</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">当客户端提交一个topology到Heron后, 一个Topology Master和多个container将会处理这个topology. Topology Master会在Zookeeper上创建一个临时的node来保存这个topology的相关信息来确保当前这个topology只有一个Topology Master来管理。通过Zookeeper上面的这个临时节点,这个topology的其他进程也能很容易的找到当前的Topology
 Master。Topology Master会为Topology创建一个</span></span> <a target="_blank" href="http://twitter.github.io/heron/docs/concepts/topologies%20/l%20physical-plan">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">physical plan</span></span></a><span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">,这个physical plan会被转发到各个topology component上,如下图:</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:10pt; font-family:����; text-indent:7mm"><img src="" alt=""><img src="http://img.blog.csdn.net/20161218182946742?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzU3MzEzMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt=""><br>
</span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:10pt; font-family:����; text-indent:7mm"><br>
</span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:10pt; font-family:����; text-indent:7mm">Topology Master有一系列的配置参数可以调节一个topology的生命周期的每个阶段.</span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:8mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����"><span style="font-size:12pt"><strong>3.7&nbsp; Stream Manager</strong></span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Stream Manager的作用是管理每个tuple应该被哪个Heron Instance进程处理,每个tuple在各个topology components之间的路由,也被称作是tuple的路由(routing)。每个Heron Instance连接本地的Stream Manager来发送和接收tuple。在一个container中,一个tuple从一个Heron
 Instance到另外一个Heron Instance使用的是 local short-circuiting的机制。每个Stream Manager也会去连接其他所有的Stream Manager来形成一个network. 如下图就是一个Stream Manager Network:</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:10pt; font-family:����; text-indent:7mm"><img src="" alt=""><img src="http://img.blog.csdn.net/20161218183028033?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzU3MzEzMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt=""><br>
</span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:10pt; font-family:����; text-indent:7mm"><br>
</span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:10pt; font-family:����; text-indent:7mm">Heron使用了backpressure的机制来动态的调节topology的流量通过率。这样可以让不同的task部分以不同的速度执行。例如,在后面阶段的任务处理速度slow down,这个时候如果前面的任务依然很快的执行,这就会导致数据的倾斜。因此Heron提供了这样的功能。</span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����"><span style="font-size:10pt">Heron提供一种背压机制来动态调整数据流动的速率。这种机制可以让topology中的各个components以不同speed来跑。也可以动态更改它的speed。</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">以下是几种实现Backpressure的策略:</span></span></div>
<p style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:3.38mm; margin-bottom:3.38mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">1. TCP Backpressure</span></span></p>
<p style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:4.64mm; min-height:2pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">这个策略利用TCP窗口的机制来梳理HI(Heron Instance)和其他Component的backpressure。所有的消息都是通过TCP sockets来做通信,如果某个HI处理缓慢,那么它的本地接收buffer就会被装满,在这个HI上游和数据通信的SM也会发现这个然后填满发送的buffer,这样该HI的处理速度就加快了。</span></span></p>
<p style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:3.38mm; margin-bottom:3.38mm; min-height:11pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">2. Spout backpressure</span></span></p>
<p style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:4.64mm; min-height:2pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">这个Backpressure策略是和TCP Backpressure策略协同使用的,当SM发现它本地的HI运行慢时,SM就会通知本地的Spout停止读取数据,那么往该Spout发送数据的SM的buffer就会阻塞以致fill up,这是受影响的SM就会发送一条start backpressure的message到其他与之相连的SM,当其他SM收到该message时就会告诉他们本地的Spout不再读取数据,当上游缓慢的HI速度赶上来之后,SM再发一个stop
 backpressure的message到下游,然后停止backpressure。</span></span></p>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Stream Manager作为一个数据的路由引擎(routing engine), 它propagating</span></span><a target="_blank" href="https://en.wikipedia.org/wiki/Back_pressure"><span style="font-family:����; font-size:12px"><span style="font-size:10pt"><u>back
 pressure</u></span></span></a><span style="font-family:����; font-size:12px"><span style="font-size:10pt">within the topology在实际生产环境中是非常重要的. 下图是一个Stream Manager实现backpressure的图:</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:10pt; font-family:宋体; text-indent:7mm"><img src="" alt=""><br>
</span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:10pt; font-family:宋体; text-indent:7mm"><img src="http://img.blog.csdn.net/20161218183058617?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzU3MzEzMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt=""><br>
</span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:10pt; font-family:宋体; text-indent:7mm">在上面图中可以看到, ContainerA中的Bolt3接收所有的来自Spout1的输入. 当Bolt3的处理速度变慢的时候,ContainerA中的Stream Manager将会拒绝来自其他Stream Manager的数据输入,这将会使得在其他container的socket buffers填满,而导致整个崩溃。</span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体"><span style="font-size:10pt">在这种情况下,Heron的backpressure机制出现了,ContainerA中的Stream Manager将会发送一条message到其他的Stream Manager上,其他的Stream Manager在收到这条message后会检查自己的container的</span></span><a target="_blank" href="http://twitter.github.io/heron/docs/concepts/topologies%20/l%20physical-plan"><span style="font-family:����; font-size:12px"><span style="font-size:10pt"><u>physical
 plan</u></span></span></a><span style="font-family:宋体; font-size:12px"><span style="font-size:10pt"><u>,并从spout断去切断向Bolt3输入</u></span><span style="font-size:10pt">,如下图.</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:10pt; font-family:宋体; text-indent:7mm"><img src="" alt=""><img src="http://img.blog.csdn.net/20161218183132206?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzU3MzEzMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt=""><br>
</span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:10pt; font-family:宋体; text-indent:7mm"><br>
</span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:10pt; font-family:宋体; text-indent:7mm">当containerA中的Bolt3恢复后,containerA中的Stream Manager会再发送以条message去通知其他的Steam Manager去恢复topology.</span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:8mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����"><span style="font-size:12pt"><strong>3.8&nbsp; Heron Instance</strong></span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Heron Instance是一个java 进程,每个HI都是</span></span><span style="font-family:宋体; font-size:12px; color:#FF0000"><span style="font-size:10pt"><strong>只跑一个task</strong></span></span><span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">,即要么是spout要么是bolt。这样有利于debug。&nbsp;这种设计也为以后数据的复杂性考虑,当以后数据复杂性变高的时候,我们还可以考虑用其他语言来实现HI。</span></span></div>
<p style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:4.64mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">HI的设计有以下两种:</span></span></p>
<p style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:4.64mm; min-height:15pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt"><strong>(1) Single-threaded approach</strong></span></span></p>
<p style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:4.64mm; min-height:2pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">主线程有一个TCP channel与本地的SM通信,等待tuple的到来,一旦tuple来了,就会调用用户的逻辑代码来执行,如果需要输出,该线程就会缓存数据,直到达到阈值,然后输出到downstream的SM。</span></span></p>
<p style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:4.64mm; min-height:15pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">这种设计简单,但是也有一些缺点,由于某些原因,用户的逻辑可能被block:</span></span></p>
<ul style="margin-top:0mm; margin-bottom:0mm; margin-left:0mm; padding-left:0pt">
<li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Invoking the sleep system call for a finite duration of time</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Using read/write system calls for file or socket I/O</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-size:10pt">
<div style="margin-top:0pt; margin-bottom:4pt"><span style="font-family:����; font-size:12px"><span style="font-size:10pt">Calling thread synchronization primitives</span></span></div>
</li></ul>
<p style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:3.38mm; margin-bottom:3.38mm; min-height:11pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt"><strong>(2) Two-threaded approach</strong></span></span></p>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">顾名思义,两个thread:Gateway thread 和Task Execution thread,如下图:</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:10pt; font-family:����; text-indent:7mm"><img src="" alt=""><img src="http://img.blog.csdn.net/20161218183215895?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzU3MzEzMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt=""><br>
</span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:10pt; font-family:����; text-indent:7mm"><br>
</span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:10pt; font-family:����; text-indent:7mm">Gateway thread负责数据的输入输出和通信</span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����"><span style="font-size:10pt">Task Execution thread则负责运行用户逻辑代码</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Gateway thread要和Task Execution thread要进行数据通信,他们之间通过如上图的三种queue来通信。Gateway thread用data-in往Task Execution thread输入数据,Task Execution thread用data-out往Gateway thread,metrics-out是用Task Execution
 thread用来收集metric然后往Gateway thread发送。</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:8mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����"><span style="font-size:12pt"><strong>3.9&nbsp; Metrics Manager</strong></span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Metrics Manager从每个task任务中收集并导出metrics。这里的metrics包括系统级别的metrics和用户自定义的topology metrics.</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">每个container都有一个Metrics Manager,向这个container里面的Stream Manager和Heron Instance去report metrics。</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">每个container中,Metrics Manager发送metrics到monitoring system。Metrics Manager也会发送metrics到Topology Master,Topology Master会提供外部的UI页面展示。</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Heron执行期间会收集一些metircs,这些metircs可以存下来做离线分析。当前的Heron支持以下集中sinks:</span></span></div>
<ul style="margin-top:0mm; margin-bottom:0mm; margin-left:0mm; padding-left:0pt">
<li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt; background:rgb(249,242,244)">File Sink</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt; background:rgb(249,242,244)">Graphite Sink</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-size:10pt">
<div style="margin-top:0pt; margin-bottom:14pt"><span style="font-family:����; font-size:12px"><span style="font-size:10pt; background:rgb(249,242,244)">Scribe Sink</span></span></div>
</li></ul>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">每个topology都会有一个MM服务在运行来收集metrics,并将metircs信息导出给当前container下的所有topology component. MM也会路由这些metrics信息给Topology Master和external collectors。Metrics我们可以自定义并实现。</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:11mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����"><span style="font-size:12pt"><strong>3.10 执行流程</strong></span></span></div>
<h2><a name="t1"></a><span style="font-family:����; font-size:12px"><span style="font-size:10pt">Topology Submit Sequence</span></span></h2>
<p><span style="font-family:����; font-size:12px"><span style="font-size:10pt">Topology的生命周期描述了topology每个阶段的状态. 以下的序列图描述了当topology被提交到Heron集群后的一些列action。</span></span></p>
<p><span style="font-size:10pt; font-family:宋体; text-indent:7mm"><img src="" alt=""><img src="http://img.blog.csdn.net/20161218183543275?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzU3MzEzMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" width="800" height="600"><br>
</span></p>
<p><span style="font-size:10pt; font-family:宋体; text-indent:7mm">当Heron CLI提交一个topology到Heron集群:</span></p>
<ol style="margin-top:0mm; margin-bottom:0mm; margin-left:0mm; padding-left:0pt">
<li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-size:12px"><span style="font-size:10pt">Aurora scheduler 为这个topology分发必要的资源,安排对应的topology container(TM和container)。</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Topology Master作为第一个container出现,把信息同步到Zookeeper上,以便其他进程能够发现TM。</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Stream Manager去Zookeeper同步信息去并找到Topology Master</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Stream Manager连接Topology Master并周期性的发送心跳</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt; font-family:����">当所有的Stream Manager都已经连接到Topology Master后,Topology Master会根据Heron的分配算法把Topology的所有任务分配到包不同的container上。这个过程叫做</span></span><span style="font-family:Calibri; font-size:12px"><span style="font-size:10pt">“</span></span><span style="font-family:����; font-size:12px"><span style="font-size:10pt">physical
 plan”,为了确保安全,Topology Master会把“physical plan”写到Zookeeper中。</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt; font-family:����">当</span></span><span style="font-family:Calibri; font-size:12px"><span style="font-size:10pt">“</span></span><span style="font-family:����; font-size:12px"><span style="font-size:10pt">physical
 plan”完成后, Stream Manager会从Topology Master那里接收到完整的</span></span><span style="font-family:Calibri; font-size:12px"><span style="font-size:10pt">“</span></span><span style="font-family:����; font-size:12px"><span style="font-size:10pt">physical plan”,这个"physical
 plan"能够帮助Stream Manager发现其他的Stream Manager。这些Stream Manager相互连接形成一个fully-connected network。</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt; font-family:����">在此时,Heron Instance进程会发现它们本地的Stream Manager,下载</span></span><span style="font-family:Calibri; font-size:12px"><span style="font-size:10pt">“</span></span><span style="font-family:����; font-size:12px"><span style="font-size:10pt">physical
 plan”中对应它自己的那一部分,并开始执行。</span></span></li><li style="margin-left:57pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt; font-family:����">以上的步骤完成后,data/tuples starts flowing through the topology</span></span></li></ol>
<ol start="11" style="margin-top:0mm; margin-bottom:0mm; margin-left:0mm; padding-left:0pt">
<li style="list-style-type:none">
<ol start="11" style="margin-top:0mm; margin-bottom:0mm; margin-left:0mm; padding-left:0pt">
<li style="margin-left:42pt; margin-right:0pt; padding-left:8pt; text-indent:0pt; font-family:����; font-size:12pt; font-weight:Bold">
<span style="font-family:����">&nbsp;失败场景处理</span></li></ol>
</li></ol>
<div align="left" style="margin-left:4mm; margin-right:0mm; text-indent:7mm; margin-top:4.75mm; margin-bottom:4.75mm; min-height:2pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">当一个topology在执行过程中,会有很多中情况导致失败,例如进程fail,container fail或是服务器宕机等,这些失败会影响topology的一部分或是整个topology。</span></span></div>
<div align="left" style="margin-left:4mm; margin-right:0mm; text-indent:7mm; margin-top:4.75mm; margin-bottom:4.75mm">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">当这个Topology Master进程死掉后,这个container会重启这个failed的进程,这个Topology Master会根据Zookeeper的数据来恢复宕机之前的状态。此时,standby Topology Master会继续处理topology的业务,刚刚重启的Topology Master将会成为standby。 与此同时,这些Stream
 Manager将会发现这个新的Topology Master,并去连接这个新的Topology Master。</span></span></div>
<div align="left" style="margin-left:4mm; margin-right:0mm; text-indent:7mm; margin-top:4.75mm; margin-bottom:4.75mm">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">类似地,当Stream Manager死掉后,在这个container中,这个Stream Manager会被restart,这个Stream Manager会重新发现当前的Topology Master,初始化一个connection去Topology Master获取最新的</span></span><span style="font-family:Calibri; font-size:12px"><span style="font-size:10pt">“</span></span><span style="font-family:����; font-size:12px"><span style="font-size:10pt">physical
 plan”。其他的Stream Manager刚刚丢失了宕机的那个Stream Manager的connection,此时,这个Stream Manager被重启并且拿到了最新的</span></span><span style="font-family:Calibri; font-size:12px"><span style="font-size:10pt">“</span></span><span style="font-family:����; font-size:12px"><span style="font-size:10pt">physical
 plan”,它们也会去这个Stream Manager得到一份指明了这个新的Stream Manager位置的</span></span><span style="font-family:Calibri; font-size:12px"><span style="font-size:10pt">“</span></span><span style="font-family:����; font-size:12px"><span style="font-size:10pt">physical plan",并且创建一个和一个新的Stream
 Manager位置的的连接。</span></span></div>
<div align="left" style="margin-left:4mm; margin-right:0mm; text-indent:7mm; margin-top:4.75mm; margin-bottom:4.75mm">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">当一个container里面的Heron Instance进程死掉了,这个Heron Instance会被重新restart,并重新连接它本地的Stream Manager,而后这个Heron Instance进程将会从这个Stream Manager中拿到一份</span></span><span style="font-family:Calibri; font-size:12px"><span style="font-size:10pt">“</span></span><span style="font-family:����; font-size:12px"><span style="font-size:10pt">physical
 plan”的copy,通过这个</span></span><span style="font-family:Calibri; font-size:12px"><span style="font-size:10pt">“</span></span><span style="font-family:����; font-size:12px"><span style="font-size:10pt">physical plan”可以让这个Heron Instance知道自己是一个spout还是bolt。然后继续执行。</span></span></div>
<div align="left" style="margin-left:4mm; margin-right:0mm; text-indent:7mm; margin-top:4.75mm; margin-bottom:4.75mm">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">当一个container被移动位置或rescheduled的时候,这个重启的Stream Manager会重新发现当前的Topology Master,然后就是以上#3,#4的流程。</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:8mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����"><span style="font-size:12pt"><strong>3.12 Heron Topology Demo</strong></span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">以下是一段Heron Topology的Example:</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:12pt; font-family:����; text-indent:8mm"><strong><img src="" alt=""><br>
</strong></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-size:12pt; font-family:����; text-indent:8mm"><strong>3.13 Heron监控</strong></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体"><span style="font-size:10pt">当Heron集群在Production环境的时候,监控往往是最重要的部分,Heron提供以下功能:</span></span></div>
<ol style="margin-top:0mm; margin-bottom:0mm; margin-left:0mm; padding-left:0pt">
<li style="margin-left:36pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">ability for users to interact&nbsp;with their topologies</span></span></li><li style="margin-left:36pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">ability for users to view metrics and&nbsp; trends for their topologies</span></span></li><li style="margin-left:36pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">ability for users to view&nbsp;exceptions that occurs in the Heron Instances</span></span></li></ol>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">为了实现以上的功能,Heron增加了以下组件:Heron Tracker,Heron UI and Heron Viz</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt"><strong>3.13.1&nbsp; Heron Tracker</strong></span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Heron Tracker是一个web服务,它提供了一套清晰完整的REST API,可以让我们很容易的扩展Heron的监控与Debug工具. 这套API提供了查询topology信息的途径,包括logical plan和physical plan,各种metircs指标,用户自定义的metircs和系统的metrics,以及log信息,也可以连接到Aurora
 job的页面。The tracker runs as an Aurora service, and typically is run in several instances for fault tolerance. The API requests are load balanced across these instances.</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt"><strong>3.13.3&nbsp; Heron UI</strong></span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt">用户可以通过这个UI界面去和topology进行交互,展示topology的信息,包括 logical and physical plan,log信息,内存使用情况,metircs等。这个UI界面会使用Heron Tracker API</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt"><img src="" alt=""></span></span></div>
<img src="http://img.blog.csdn.net/20161218183633495?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzU3MzEzMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:宋体; font-size:12px"><span style="font-size:10pt"><br>
</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt"><strong>3.13.4&nbsp; Heron Viz</strong></span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Heron Viz是一个service服务,用于创建一个dashboard,通过这个dashboard可以查看由Metrics Manager统计的某个topology的metrics,这个Heron Viz会周期性的连接Heron Tracker查看是否有新的topology。当有新的Topology的时候,他会调用一个画图的API(Viz)去创建一个graphs
 dashboard,被称作 Heron Viz dashboard。这个dashboard里面会有这个topology的详细信息。Heron Viz dashboard也会根据为当前的Topology去创建一个health metrics, resource metrics, component metrics and&nbsp;stream manager (SM) metrics.</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:7mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:15pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt"><img src="" alt=""><img src="http://img.blog.csdn.net/20161218183729418?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzU3MzEzMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt=""><br>
</span></span></div>
<div align="left" style="margin-left:0mm; margin-right:0mm; text-indent:10mm; margin-top:0.00mm; margin-bottom:0.00mm; min-height:18pt">
<span style="font-family:����; font-size:18px"><span style="font-size:14pt"><strong>4. 总结</strong></span></span></div>
<ol style="margin-top:0mm; margin-bottom:0mm; margin-left:0mm; padding-left:0pt">
<li style="margin-left:72pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">First, the provisioning of resources (e.g. for containers and even the Topology Master) is cleanly abstracted from the duties of the cluster manager, thereby allowing Heron to “play
 nice” with the rest of the (shared) infrastructure.</span></span></li><li style="margin-left:72pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Second, Isolation, topologies should be process based rather than thread based, since each Heron Instance is executing only a single task (e.g. running a spout or bolt), and each process
 should run in isolation.it is easy to debug that instance by simply using tools like jstack and heap dump with that process, to profile and to troubleshoot.</span></span></li><li style="margin-left:72pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Third, the design makes it transparent as to which component of the topology is failing or slowing down, as the metrics collection is granular, and lets us easily map an issue unambiguously
 to a specific process in the system.</span></span></li><li style="margin-left:72pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Fourth, by allowing component-level resource allocation, Heron allows a topology writer to specify exactly the resources for each component, thereby avoiding unnecessary over-provisioning.</span></span></li><li style="margin-left:72pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Fifth, having a Topology Master per topology allows each topology to be managed independently of each other (and other systems in the underlying cluster). In additional, failure of
 one topology (which can happen as user-defined code often gets run in the bolts) does not impact the other topologies.</span></span></li><li style="margin-left:72pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Sixth, In a distributed system like Heron, there are no guarantees that all system components will execute at the same speed. Heron has built-in back pressure mechanisms to ensure that
 topologies can self-adjust in case components lag. The backpressure mechanism allows us to achieve a consistent rate of delivering results, and a precise way to reason about the system. It is also a key mechanism that allows migrating topologies from one set
 of containers to another (e.g. to an upgraded set of machines).</span></span></li><li style="margin-left:72pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Finally, we now do not have any single point of failure.</span></span></li><li style="margin-left:72pt; margin-right:0pt; padding-left:-39pt; text-indent:0pt; font-family:����; font-size:10pt">
<span style="font-family:����; font-size:12px"><span style="font-size:10pt">Heron is fully API and data model compatible with Apache Storm</span></span></li></ol>
<p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; max-width:100%; clear:both; min-height:1em; white-space:pre-wrap; color:rgb(62,62,62); font-family:'Helvetica Neue',Helvetica,'Hiragino Sans GB','Microsoft YaHei',Arial,sans-serif; font-size:18px; line-height:28.7999992370605px; word-wrap:break-word!important">
</p>
   
</div>








<!-- Baidu Button BEGIN -->








<div class="bdsharebuttonbox tracking-ad bdshare-button-style0-16" style="float: right;" data-mod="popu_172" data-bd-bind="1489664378616">
<a href="#" class="bds_more" data-cmd="more" style="background-position:0 0 !important; background-image: url(http://bdimg.share.baidu.com/static/api/img/share/icons_0_16.png?v=d754dcc0.png) !important" target="_blank"></a>
<a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间" style="background-position:0 -52px !important" target="_blank"></a>
<a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博" style="background-position:0 -104px !important" target="_blank"></a>
<a href="#" class="bds_tqq" data-cmd="tqq" title="分享到腾讯微博" style="background-position:0 -260px !important" target="_blank"></a>
<a href="#" class="bds_renren" data-cmd="renren" title="分享到人人网" style="background-position:0 -208px !important" target="_blank"></a>
<a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信" style="background-position:0 -1612px !important" target="_blank"></a>
</div>
<script>window._bd_share_config = { "common": { "bdSnsKey": {}, "bdText": "", "bdMini": "1", "bdMiniList": false, "bdPic": "", "bdStyle": "0", "bdSize": "16" }, "share": {} }; with (document) 0[(getElementsByTagName('head')[0] || body).appendChild(createElement('script')).src = 'http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion=' + ~(-new Date() / 36e5)];</script>
<!-- Baidu Button END -->


   <link rel="stylesheet" href="http://static.blog.csdn.net/css/blog_detail.css">


    
<!--172.16.140.12-->


<!-- Baidu Button BEGIN -->
<script type="text/javascript" id="bdshare_js" data="type=tools&amp;uid=1536434" src="http://bdimg.share.baidu.com/static/js/bds_s_v2.js?cdnversion=413796"></script>


<script type="text/javascript">
    document.getElementById("bdshell_js").src = "http://bdimg.share.baidu.com/static/js/shell_v2.js?cdnversion=" + Math.ceil(new Date()/3600000)
</script>
<!-- Baidu Button END -->


 




        <div id="digg" articleid="49180543">
            <dl id="btnDigg" class="digg digg_enable" onclick="btndigga();">
               
                 <dt>顶</dt>
                <dd>0</dd>
            </dl>
           
              
            <dl id="btnBury" class="digg digg_enable" onclick="btnburya();">
              
                  <dt>踩</dt>
                <dd>0</dd>               
            </dl>
            
        </div>
     <div class="tracking-ad" data-mod="popu_222"><a href="javascript:void(0);" target="_blank">&nbsp;</a>   </div>
    <div class="tracking-ad" data-mod="popu_223"> <a href="javascript:void(0);" target="_blank">&nbsp;</a></div>
    <script type="text/javascript">
                function btndigga() {
                    $(".tracking-ad[data-mod='popu_222'] a").click();
                }
                function btnburya() {
                    $(".tracking-ad[data-mod='popu_223'] a").click();
                }
            </script>


   <ul class="article_next_prev">
                <li class="prev_article"><span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_shangyipian']);location.href='/u013573133/article/details/49180457';">上一篇</span><a href="/u013573133/article/details/49180457" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_shangyipian'])">mysql大数据量下的操作以及优化</a></li>
                <li class="next_article"><span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_xiayipian']);location.href='/u013573133/article/details/49180599';">下一篇</span><a href="/u013573133/article/details/49180599" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_xiayipian'])">Quartz集群配置与原理解析</a></li>
    </ul>


    <div style="clear:both; height:10px;"></div>




      
</div>


     <div>
             <div class="J_adv" data-view="true" data-mod="ad_popu_206" data-mtp="43" data-order="114" data-con="ad_content_1901" style="width: 960px; height: 90px;"><script src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><ins class="adsbygoogle" style="display:inline-block;width:960px;height:90px" data-ad-client="ca-pub-8990951720398508" data-ad-slot="8267689356/3776917242" data-adsbygoogle-status="done"><ins id="aswift_0_expand" style="display:inline-table;border:none;height:90px;margin:0;padding:0;position:relative;visibility:visible;width:960px;background-color:transparent"><ins id="aswift_0_anchor" style="display:block;border:none;height:90px;margin:0;padding:0;position:relative;visibility:visible;width:960px;background-color:transparent"><iframe width="960" height="90" frameborder="0" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" scrolling="no" allowfullscreen="true" onload="var i=this.id,s=window.google_iframe_oncopy,H=s&amp;&amp;s.handlers,h=H&amp;&amp;H[i],w=this.contentWindow,d;try{d=w.document}catch(e){}if(h&amp;&amp;d&amp;&amp;(!d.body||!d.body.firstChild)){if(h.call){setTimeout(h,0)}else if(h.match){try{h=s.upd(h,i)}catch(e){}w.location.replace(h)}}" id="aswift_0" name="aswift_0" style="left:0;position:absolute;top:0;"></iframe></ins></ins></ins><script>(adsbygoogle=window.adsbygoogle || []).push({});</script></div> 
    </div>


<div id="suggest">


</div>
         <script language="javascript" type="text/javascript">     
             $(function(){
                 $.get("/u013573133/svc/GetSuggestContent/49180543",function(data){
                     $("#suggest").html(data);
                 });     
             });             
         </script>  




<style>
.blog-ass-articl dd {
color: #369;
width: 99%; /*修改行*/
float: left;
overflow: hidden;
font: normal normal 12px/23px "SimSun";
height: 23px;
margin: 0;
padding: 0 0 0 10px;
margin-right: 30px;
background: url(http://static.blog.csdn.net/skin/default/images/blog-dot-red3.gif) no-repeat 0 10px;
}
</style>


 <link rel="stylesheet" href="http://static.blog.csdn.net/css/replace.css">


<div id="relate" data-mod="popu_218" class="tracking-ad" style="display: block;">
        <div class="relate_t">
            <h3><span>参考知识库</span></h3>
        </div>
        <div class="relate_c"><dl class="relate_list"><dt><a target="_blank" href="http://lib.csdn.net/base/javase"><img src="http://img.knowledge.csdn.net/upload/base/1453169124297_297.jpg" alt="img"></a></dt><dd><h4><a target="_blank" href="http://lib.csdn.net/base/javase">Java SE知识库</a></h4><p><label><span>24339</span><em>关注</em><i>|</i><span>477</span><em>收录</em></label></p></dd></dl><dl class="relate_list"><dt><a target="_blank" href="http://lib.csdn.net/base/mysql"><img src="http://img.knowledge.csdn.net/upload/base/1454051093684_684.jpg" alt="img"></a></dt><dd><h4><a target="_blank" href="http://lib.csdn.net/base/mysql">MySQL知识库</a></h4><p><label><span>20771</span><em>关注</em><i>|</i><span>1447</span><em>收录</em></label></p></dd></dl><dl class="relate_list"><dt><a target="_blank" href="http://lib.csdn.net/base/javaee"><img src="http://img.knowledge.csdn.net/upload/base/1456818035722_722.jpg" alt="img"></a></dt><dd><h4><a target="_blank" href="http://lib.csdn.net/base/javaee">Java EE知识库</a></h4><p><label><span>16339</span><em>关注</em><i>|</i><span>1265</span><em>收录</em></label></p></dd></dl><dl class="relate_list"><dt><a target="_blank" href="http://lib.csdn.net/base/java"><img src="http://img.knowledge.csdn.net/upload/base/1453701371636_636.jpg" alt="img"></a></dt><dd><h4><a target="_blank" href="http://lib.csdn.net/base/java">Java 知识库</a></h4><p><label><span>24104</span><em>关注</em><i>|</i><span>1450</span><em>收录</em></label></p></dd></dl><dl class="relate_list"><dt><a target="_blank" href="http://lib.csdn.net/base/docker"><img src="http://img.knowledge.csdn.net/upload/base/1452500466484_484.jpg" alt="img"></a></dt><dd><h4><a target="_blank" href="http://lib.csdn.net/base/docker">Docker知识库</a></h4><p><label><span>6107</span><em>关注</em><i>|</i><span>237</span><em>收录</em></label></p></dd></dl><dl class="relate_list"><dt><a target="_blank" href="http://lib.csdn.net/base/softwaretest"><img src="http://img.knowledge.csdn.net/upload/base/1467193268346_346.jpg" alt="img"></a></dt><dd><h4><a target="_blank" href="http://lib.csdn.net/base/softwaretest">软件测试知识库</a></h4><p><label><span>4021</span><em>关注</em><i>|</i><span>310</span><em>收录</em></label></p></dd></dl><dl class="relate_list"><dt><a target="_blank" href="http://lib.csdn.net/base/datastructure"><img src="http://img.knowledge.csdn.net/upload/base/1461035533512_512.jpg" alt="img"></a></dt><dd><h4><a target="_blank" href="http://lib.csdn.net/base/datastructure">算法与数据结构知识库</a></h4><p><label><span>14376</span><em>关注</em><i>|</i><span>2320</span><em>收录</em></label></p></dd></dl><dl class="relate_list"><dt><a target="_blank" href="http://lib.csdn.net/base/architecture"><img src="http://img.knowledge.csdn.net/upload/base/1458091865915_915.jpg" alt="img"></a></dt><dd><h4><a target="_blank" href="http://lib.csdn.net/base/architecture">大型网站架构知识库</a></h4><p><label><span>8055</span><em>关注</em><i>|</i><span>708</span><em>收录</em></label></p></dd></dl></div>
</div>
 


<dl class="blog-ass-articl" id="res-relatived"> 
    <div class="embody embody_b" id="libkeyparent" style="display:none">
            <span class="embody_t">更多资料请参考:</span>
            <div class="embody_c" id="libkey"></div>
    </div>




     <dt><span>猜你在找</span></dt>    




   




    <div id="adCollege" style="width: 42%;float: left;"> 
        <script src="http://csdnimg.cn/jobreco/job_reco.js" type="text/javascript"></script> 
        <script type="text/javascript">
            csdn.position.showEdu({
                sourceType: "blog",
                searchType: "detail",
                searchKey: "49180543",
                username: "zouluquniuyue1314",
                recordcount: "5",
                containerId: "adCollege" //容器DIV的id。 
            });
            
            setEduLoc();


            function setEduLoc() {               
                var edus = $("#adCollege div dd a");
                if (edus.length == 0) {
                    setTimeout(function () {
                        setEduLoc();
                    }, 500);
                }
                else {
                    var eduLoc = "?ref=blog&loc=0";
                    $.each(edus, function (index,item) {
                        var href = $(this).attr("href") + eduLoc;
                        $(this).attr("href", href);
                    });
                }
            }


        </script> 
    <div class="tracking-ad" data-mod="popu_84"><dd style="background:url(http://static.blog.csdn.net/skin/default/images/blog-dot-red3.gif) no-repeat 0 10px; white-space: nowrap;"><a href="http://edu.csdn.net/course/detail/1203?ref=blog&amp;loc=0" title="Hadoop生态系统零基础入门" strategy="v4:hot" target="_blank">Hadoop生态系统零基础入门</a></dd><dd style="background:url(http://static.blog.csdn.net/skin/default/images/blog-dot-red3.gif) no-repeat 0 10px; white-space: nowrap;"><a href="http://edu.csdn.net/course/detail/535?ref=blog&amp;loc=0" title="8小时学会HTML网页开发" strategy="v4:hot" target="_blank">8小时学会HTML网页开发</a></dd><dd style="background:url(http://static.blog.csdn.net/skin/default/images/blog-dot-red3.gif) no-repeat 0 10px; white-space: nowrap;"><a href="http://edu.csdn.net/course/detail/207?ref=blog&amp;loc=0" title="韦东山嵌入式Linux第一期视频" strategy="v4:hot" target="_blank">韦东山嵌入式Linux第一期视频</a></dd><dd style="background:url(http://static.blog.csdn.net/skin/default/images/blog-dot-red3.gif) no-repeat 0 10px; white-space: nowrap;"><a href="http://edu.csdn.net/course/detail/1152?ref=blog&amp;loc=0" title="Swift视频教程(第四季)" strategy="v4:hot" target="_blank">Swift视频教程(第四季)</a></dd><dd style="background:url(http://static.blog.csdn.net/skin/default/images/blog-dot-red3.gif) no-repeat 0 10px; white-space: nowrap;"><a href="http://edu.csdn.net/course/detail/335?ref=blog&amp;loc=0" title="JavaScript for Qt Quick(QML)" strategy="v4:hot" target="_blank">JavaScript for Qt Quick(QML)</a></dd></div></div>  


    
     <div id="res" data-mod="popu_36" class="tracking-ad" style="width: 42%; float: left; margin-right: 30px; display: block;"><dd style="background:url(http://static.blog.csdn.net/skin/default/images/blog-dot-red3.gif) no-repeat 0 10px;"><a href="http://blog.csdn.net/cserchen/article/details/21866449" title="新一代Hadoop大数据挖掘平台和生态介绍" strategy="SearchAlgorithm" target="_blank">新一代Hadoop大数据挖掘平台和生态介绍</a></dd><dd style="background:url(http://static.blog.csdn.net/skin/default/images/blog-dot-red3.gif) no-repeat 0 10px;"><a href="http://blog.csdn.net/yangbutao/article/details/12648209" title="新一代mapreduce体系架构介绍-YARN" strategy="SearchAlgorithm" target="_blank">新一代mapreduce体系架构介绍-YARN</a></dd><dd style="background:url(http://static.blog.csdn.net/skin/default/images/blog-dot-red3.gif) no-repeat 0 10px;"><a href="http://blog.csdn.net/yu616568/article/details/50993491" title="新一代列式存储格式Parquet" strategy="SearchAlgorithm" target="_blank">新一代列式存储格式Parquet</a></dd><dd style="background:url(http://static.blog.csdn.net/skin/default/images/blog-dot-red3.gif) no-repeat 0 10px;"><a href="http://blog.csdn.net/u013306940/article/details/51168452" title="Spring Boot开发新一代Spring Java应用" strategy="SearchAlgorithm" target="_blank">Spring Boot开发新一代Spring Java应用</a></dd><dd style="background:url(http://static.blog.csdn.net/skin/default/images/blog-dot-red3.gif) no-repeat 0 10px;"><a href="http://blog.csdn.net/dongliqiang2006/article/details/3501663" title="在Ubuntu 810 中安装使用新一代输入法ibus Deb包下载_UbuntuLinuxibus输入法拼音五笔搜狗" strategy="SearchAlgorithm" target="_blank">在Ubuntu 810 中安装使用新一代输入法ibus Deb包下载_UbuntuLinuxibus输入法拼音五笔搜狗</a></dd></div>
   
</dl>




<script type="text/javascript">
    $(function () {
        setTimeout(function () {
            var searchtitletags = 'Heron 新一代流处理框架详解' + ',' + $("#tags").html();
            searchService({
                index: 'blog',
                query: searchtitletags,
                from: 5,
                size: 5,
                appendTo: '#res',
                url: 'recommend',
                his: 2,
                client: "blog_cf_enhance",
                tmpl: '<dd style="background:url(http://static.blog.csdn.net/skin/default/images/blog-dot-red3.gif) no-repeat 0 10px;"><a href="#{ url }" title="#{ title }" strategy="#{ strategy }">#{ title }</a></dd>'
            });
        }, 500);
    });    


 </script>  




    <div id="ad_cen">        
                      <div class="J_adv" data-view="true" data-mod="ad_popu_199" data-mtp="43" data-order="114" data-con="ad_content_1843" style="width: 960px; height: 90px;"><script src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><ins class="adsbygoogle" style="display:inline-block;width:960px;height:90px" data-ad-client="ca-pub-8990951720398508" data-ad-slot="8267689356/3115746762" data-adsbygoogle-status="done"><ins id="aswift_1_expand" style="display:inline-table;border:none;height:90px;margin:0;padding:0;position:relative;visibility:visible;width:960px;background-color:transparent"><ins id="aswift_1_anchor" style="display:block;border:none;height:90px;margin:0;padding:0;position:relative;visibility:visible;width:960px;background-color:transparent"><iframe width="960" height="90" frameborder="0" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" scrolling="no" allowfullscreen="true" onload="var i=this.id,s=window.google_iframe_oncopy,H=s&amp;&amp;s.handlers,h=H&amp;&amp;H[i],w=this.contentWindow,d;try{d=w.document}catch(e){}if(h&amp;&amp;d&amp;&amp;(!d.body||!d.body.firstChild)){if(h.call){setTimeout(h,0)}else if(h.match){try{h=s.upd(h,i)}catch(e){}w.location.replace(h)}}" id="aswift_1" name="aswift_1" style="left:0;position:absolute;top:0;"></iframe></ins></ins></ins><script>(adsbygoogle=window.adsbygoogle || []).push({});</script></div>
    </div>  


    <!-- 广告位开始 -->
    <div class="J_adv" data-view="true" data-mod="ad_popu_72" data-mtp="62" data-order="40" data-con="ad_content_2072"><script id="popuLayer_js_q" src="http://ads.csdn.net/js/popuLayer.js" defer="" type="text/javascript"></script><div id="layerd" style="position: fixed; bottom: 0px; right: 0px; line-height: 0px; z-index: 1000; width: 300px; height: 278px; display: none;"><div class="J_close layer_close" style="display:;background-color:#efefef;padding:0px;color:#333;font:12px/24px Helvetica,Tahoma,Arial,sans-serif;text-align:right;">关闭</div><!-- 广告占位容器 --><div id="cpro_u2895327"><iframe id="iframeu2895327_0" src="http://pos.baidu.com/vcum?rdid=2895327&amp;dc=3&amp;di=u2895327&amp;dri=0&amp;dis=0&amp;dai=1&amp;ps=492x1222&amp;dcb=___adblockplus&amp;dtm=HTML_POST&amp;dvi=0.0&amp;dci=-1&amp;dpt=none&amp;tsr=0&amp;tpr=1489664378669&amp;ti=Heron%20%E6%96%B0%E4%B8%80%E4%BB%A3%E6%B5%81%E5%A4%84%E7%90%86%E6%A1%86%E6%9E%B6%E8%AF%A6%E8%A7%A3%20-%20%E6%88%91%E6%98%AFAlvin%E5%AE%B6%E9%B8%A1%E9%B8%AD%E9%B1%BC%E7%9A%84%E5%B0%8F%E7%B1%B3%E7%B1%B3%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET&amp;ari=2&amp;dbv=2&amp;drs=3&amp;pcs=1522x746&amp;pss=1605x18647&amp;cfv=0&amp;cpl=5&amp;chi=2&amp;cce=true&amp;cec=UTF-8&amp;tlm=1489664378&amp;rw=760&amp;ltu=http%3A%2F%2Fblog.csdn.net%2Fu013573133%2Farticle%2Fdetails%2F49180543&amp;ecd=1&amp;uc=1920x1040&amp;pis=-1x-1&amp;ccd=24&amp;cja=false&amp;cmi=7&amp;col=zh-CN&amp;cdo=-1&amp;sr=1920x1080&amp;tcn=1489664379&amp;qn=2012ea89f062a731&amp;tt=1489664378651.21.21.23" width="300" height="250" align="center,center" vspace="0" hspace="0" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" style="border:0;vertical-align:bottom;margin:0;width:300px;height:250px" allowtransparency="true"></iframe></div></div><script>  document.getElementById('popuLayer_js_q').onload=function(){      var styObjd=styObj={width:'300px','height':parseInt(250)+28};window.CSDN.Layer.PopuLayer('#layerd',{storageName:'layerd',styleObj:styObjd,total:50,expoire:1000*60});  }</script><!-- 投放代码 --><script type="text/javascript">   /*服务器频道首页置顶Banner960*90,创建于2014-7-3*/    (window.cproArray = window.cproArray || []).push({        id: 'u2895327'      });  </script>  <script src="http://cpro.baidustatic.com/cpro/ui/c.js" type="text/javascript"></script></div>
    <!-- 广告位结束 -->


<div class="comment_class">
    <div id="comment_title" class="panel_head">
        <span class="see_comment">查看评论</span><a name="comments"></a></div>
    <div id="comment_list"><br>&nbsp;&nbsp;暂无评论<br><br><div class="clear"></div></div>
    <div id="comment_bar">
    </div>
    <div id="comment_form"><a name="commentbox"></a><a name="reply"></a><a name="quote"></a><form action="/u013573133/comment/submit?id=49180543" method="post" onsubmit="return subform(this);"><div class="commentform"><div class="panel_head">发表评论</div><ul><li class="left">用 户 名:</li><li class="right">zouluquniuyue1314</li></ul><ul><li class="left">评论内容:</li><li class="right" style="position:relative;"><div id="ubbtools"><a href="#insertcode" code="code"><img src="http://static.blog.csdn.net/images/ubb/code.gif" border="0" alt="插入代码" title="插入代码"></a></div><div id="lang_list" style="position: absolute; top: 28px; left: 0px; display: none;"><a class="long_name" href="#html">HTML/XML</a><a class="long_name" href="#objc">objective-c</a><a class="zhong_name" href="#delphi">Delphi</a><a class="zhong_name" href="#ruby">Ruby</a><a href="#php">PHP</a><a class="duan_name" href="#csharp">C#</a><a style=" border-right: none;" class="duan_name" href="#cpp">C++</a><a style=" border-bottom:none;" class="long_name" href="#javascript">JavaScript</a><a style=" border-bottom:none;" class="long_name" href="#vb">Visual Basic</a><a style=" border-bottom:none;" class="zhong_name" href="#python">Python</a><a style=" border-bottom:none;" class="zhong_name" href="#java">Java</a><a style="border-bottom:none;" class="duan_name" href="#css">CSS</a><a style="border-bottom:none;" class="duan_name" href="#sql">SQL</a><a style="border:none;" class="duan_name" href="#plain">其它</a></div><textarea class="comment_content" name="comment_content" id="comment_content" style="width: 400px; height: 200px;"></textarea></li></ul><ul><input type="hidden" id="comment_replyId" name="comment_replyId"><input type="hidden" id="comment_userId" name="comment_userId" value="521203"><input type="hidden" id="commentId" name="commentId" value=""><input type="submit" class="comment_btn" value="提交">&nbsp;&nbsp;<span id="tip_comment" style="color: Red; display: none;"></span></ul></div></form></div>
    <div class="announce">
        * 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场<a name="reply"></a><a name="quote"></a></div>
</div>


<script type="text/javascript">
    var fileName = '49180543';
    var commentscount = 0;
    var islock = false
</script>
<script type="text/javascript" src="http://static.blog.csdn.net/scripts/comment.js"></script>
    <div id="ad_bot">
    </div>
<div id="report_dialog">
</div>


<div id="d-top" style="bottom:60px;">


        <a id="quick-reply" class="btn btn-top q-reply" title="快速回复" style="display:none;">
            <img src="http://static.blog.csdn.net/images/blog-icon-reply.png" alt="快速回复">
        </a>    
    <a id="d-top-a" class="btn btn-top backtop" style="display: none;" title="返回顶部" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_huidaodingbu'])">         
         <img src="http://static.blog.csdn.net/images/top.png" alt="TOP">
    </a>
</div>
<script type="text/javascript">
    $(function ()
    {
        $("#ad_frm_0").height("90px");
        
        setTimeout(function(){
            $("#ad_frm_2").height("200px");
        },1000);    
    });
  
</script>
<style type="text/css">
    .tag_list
    {
        background: none repeat scroll 0 0 #FFFFFF;
        border: 1px solid #D7CBC1;
        color: #000000;
        font-size: 12px;
        line-height: 20px;
        list-style: none outside none;
        margin: 10px 2% 0 1%;
        padding: 1px;
    }
    .tag_list h5
    {
        background: none repeat scroll 0 0 #E0DBD3;
        color: #47381C;
        font-size: 12px;
        height: 24px;
        line-height: 24px;
        padding: 0 5px;
        margin: 0;
    }
    .tag_list h5 a
    {
        color: #47381C;
    }
    .classify
    {
        margin: 10px 0;
        padding: 4px 12px 8px;
    }
    .classify a
    {
        margin-right: 20px;
        white-space: nowrap;
    }
</style>




<div class="tag_list" style="">


    <h5>
        <a href="http://www.csdn.net/tag/" target="_blank">核心技术类目</a></h5>
    <div class="classify">
<a title="全部主题" href="http://www.csdn.net/tag" target="_blank" onclick="LogClickCount(this,336);">全部主题</a>
<a title="Hadoop" href="http://g.csdn.net/5272865" target="_blank" onclick="LogClickCount(this,336);">Hadoop</a>
<a title="AWS" href="http://g.csdn.net/5272866" target="_blank" onclick="LogClickCount(this,336);">AWS</a>
<a title="移动游戏" href="http://g.csdn.net/5272870" target="_blank" onclick="LogClickCount(this,336);">移动游戏</a>
<a title="Java" href="http://g.csdn.net/5272871" target="_blank" onclick="LogClickCount(this,336);">Java</a>
<a title="Android" href="http://g.csdn.net/5272872" target="_blank" onclick="LogClickCount(this,336);">Android</a>
<a title="iOS" href="http://g.csdn.net/5272873" target="_blank" onclick="LogClickCount(this,336);">iOS</a>
<a title="Swift" href="http://g.csdn.net/5272868" target="_blank" onclick="LogClickCount(this,336);">Swift</a>
<a title="智能硬件" href="http://g.csdn.net/5272869" target="_blank" onclick="LogClickCount(this,336);">智能硬件</a>
<a title="Docker" href="http://g.csdn.net/5272867" target="_blank" onclick="LogClickCount(this,336);">Docker</a>
<a title="OpenStack" href="http://g.csdn.net/5272925" target="_blank" onclick="LogClickCount(this,336);">OpenStack</a>
<a title="VPN" href="http://www.csdn.net/tag/vpn" target="_blank" onclick="LogClickCount(this,336);">VPN</a>
<a title="Spark" href="http://g.csdn.net/5272924" target="_blank" onclick="LogClickCount(this,336);">Spark</a>
<a title="ERP" href="http://www.csdn.net/tag/erp" target="_blank" onclick="LogClickCount(this,336);">ERP</a>
<a title="IE10" href="http://www.csdn.net/tag/ie10" target="_blank" onclick="LogClickCount(this,336);">IE10</a>
<a title="Eclipse" href="http://www.csdn.net/tag/eclipse" target="_blank" onclick="LogClickCount(this,336);">Eclipse</a>
<a title="CRM" href="http://www.csdn.net/tag/crm" target="_blank" onclick="LogClickCount(this,336);">CRM</a>
<a title="JavaScript" href="http://www.csdn.net/tag/javascript" target="_blank" onclick="LogClickCount(this,336);">JavaScript</a>
<a title="数据库" href="http://www.csdn.net/tag/数据库" target="_blank" onclick="LogClickCount(this,336);">数据库</a>
<a title="Ubuntu" href="http://www.csdn.net/tag/ubuntu" target="_blank" onclick="LogClickCount(this,336);">Ubuntu</a>
<a title="NFC" href="http://www.csdn.net/tag/nfc" target="_blank" onclick="LogClickCount(this,336);">NFC</a>
<a title="WAP" href="http://www.csdn.net/tag/wap" target="_blank" onclick="LogClickCount(this,336);">WAP</a>
<a title="jQuery" href="http://www.csdn.net/tag/jquery" target="_blank" onclick="LogClickCount(this,336);">jQuery</a>
<a title="BI" href="http://www.csdn.net/tag/bi" target="_blank" onclick="LogClickCount(this,336);">BI</a>
<a title="HTML5" href="http://www.csdn.net/tag/html5" target="_blank" onclick="LogClickCount(this,336);">HTML5</a>
<a title="Spring" href="http://www.csdn.net/tag/spring" target="_blank" onclick="LogClickCount(this,336);">Spring</a>
<a title="Apache" href="http://www.csdn.net/tag/apache" target="_blank" onclick="LogClickCount(this,336);">Apache</a>
<a title=".NET" href="http://www.csdn.net/tag/.net" target="_blank" onclick="LogClickCount(this,336);">.NET</a>
<a title="API" href="http://www.csdn.net/tag/api" target="_blank" onclick="LogClickCount(this,336);">API</a>
<a title="HTML" href="http://www.csdn.net/tag/html" target="_blank" onclick="LogClickCount(this,336);">HTML</a>
<a title="SDK" href="http://www.csdn.net/tag/sdk" target="_blank" onclick="LogClickCount(this,336);">SDK</a>
<a title="IIS" href="http://www.csdn.net/tag/iis" target="_blank" onclick="LogClickCount(this,336);">IIS</a>
<a title="Fedora" href="http://www.csdn.net/tag/fedora" target="_blank" onclick="LogClickCount(this,336);">Fedora</a>
<a title="XML" href="http://www.csdn.net/tag/xml" target="_blank" onclick="LogClickCount(this,336);">XML</a>
<a title="LBS" href="http://www.csdn.net/tag/lbs" target="_blank" onclick="LogClickCount(this,336);">LBS</a>
<a title="Unity" href="http://www.csdn.net/tag/unity" target="_blank" onclick="LogClickCount(this,336);">Unity</a>
<a title="Splashtop" href="http://www.csdn.net/tag/splashtop" target="_blank" onclick="LogClickCount(this,336);">Splashtop</a>
<a title="UML" href="http://www.csdn.net/tag/uml" target="_blank" onclick="LogClickCount(this,336);">UML</a>
<a title="components" href="http://www.csdn.net/tag/components" target="_blank" onclick="LogClickCount(this,336);">components</a>
<a title="Windows Mobile" href="http://www.csdn.net/tag/windowsmobile" target="_blank" onclick="LogClickCount(this,336);">Windows Mobile</a>
<a title="Rails" href="http://www.csdn.net/tag/rails" target="_blank" onclick="LogClickCount(this,336);">Rails</a>
<a title="QEMU" href="http://www.csdn.net/tag/qemu" target="_blank" onclick="LogClickCount(this,336);">QEMU</a>
<a title="KDE" href="http://www.csdn.net/tag/kde" target="_blank" onclick="LogClickCount(this,336);">KDE</a>
<a title="Cassandra" href="http://www.csdn.net/tag/cassandra" target="_blank" onclick="LogClickCount(this,336);">Cassandra</a>
<a title="CloudStack" href="http://www.csdn.net/tag/cloudstack" target="_blank" onclick="LogClickCount(this,336);">CloudStack</a>
<a title="FTC" href="http://www.csdn.net/tag/ftc" target="_blank" onclick="LogClickCount(this,336);">FTC</a>
<a title="coremail" href="http://www.csdn.net/tag/coremail" target="_blank" onclick="LogClickCount(this,336);">coremail</a>
<a title="OPhone " href="http://www.csdn.net/tag/ophone " target="_blank" onclick="LogClickCount(this,336);">OPhone </a>
<a title="CouchBase" href="http://www.csdn.net/tag/couchbase" target="_blank" onclick="LogClickCount(this,336);">CouchBase</a>
<a title="云计算" href="http://www.csdn.net/tag/云计算" target="_blank" onclick="LogClickCount(this,336);">云计算</a>
<a title="iOS6" href="http://www.csdn.net/tag/iOS6" target="_blank" onclick="LogClickCount(this,336);">iOS6</a>
<a title="Rackspace " href="http://www.csdn.net/tag/rackspace " target="_blank" onclick="LogClickCount(this,336);">Rackspace </a>
<a title="Web App" href="http://www.csdn.net/tag/webapp" target="_blank" onclick="LogClickCount(this,336);">Web App</a>
<a title="SpringSide" href="http://www.csdn.net/tag/springside" target="_blank" onclick="LogClickCount(this,336);">SpringSide</a>
<a title="Maemo" href="http://www.csdn.net/tag/maemo" target="_blank" onclick="LogClickCount(this,336);">Maemo</a>
<a title="Compuware" href="http://www.csdn.net/tag/compuware" target="_blank" onclick="LogClickCount(this,336);">Compuware</a>
<a title="大数据" href="http://www.csdn.net/tag/大数据" target="_blank" onclick="LogClickCount(this,336);">大数据</a>
<a title="aptech" href="http://www.csdn.net/tag/aptech" target="_blank" onclick="LogClickCount(this,336);">aptech</a>
<a title="Perl" href="http://www.csdn.net/tag/perl" target="_blank" onclick="LogClickCount(this,336);">Perl</a>
<a title="Tornado" href="http://www.csdn.net/tag/tornado" target="_blank" onclick="LogClickCount(this,336);">Tornado</a>
<a title="Ruby" href="http://www.csdn.net/tag/ruby" target="_blank" onclick="LogClickCount(this,336);">Ruby</a>
<a title="Hibernate" href="http://www.csdn.net/hibernate" target="_blank" onclick="LogClickCount(this,336);">Hibernate</a>
<a title="ThinkPHP" href="http://www.csdn.net/tag/thinkphp" target="_blank" onclick="LogClickCount(this,336);">ThinkPHP</a>
<a title="HBase" href="http://www.csdn.net/tag/hbase" target="_blank" onclick="LogClickCount(this,336);">HBase</a>
<a title="Pure" href="http://www.csdn.net/tag/pure" target="_blank" onclick="LogClickCount(this,336);">Pure</a>
<a title="Solr" href="http://www.csdn.net/tag/solr" target="_blank" onclick="LogClickCount(this,336);">Solr</a>
<a title="Angular" href="http://www.csdn.net/tag/angular" target="_blank" onclick="LogClickCount(this,336);">Angular</a>
<a title="Cloud Foundry" href="http://www.csdn.net/tag/cloudfoundry" target="_blank" onclick="LogClickCount(this,336);">Cloud Foundry</a>
<a title="Redis" href="http://www.csdn.net/tag/redis" target="_blank" onclick="LogClickCount(this,336);">Redis</a>
<a title="Scala" href="http://www.csdn.net/tag/scala" target="_blank" onclick="LogClickCount(this,336);">Scala</a>
<a title="Django" href="http://www.csdn.net/tag/django" target="_blank" onclick="LogClickCount(this,336);">Django</a>
<a title="Bootstrap" href="http://www.csdn.net/tag/bootstrap" target="_blank" onclick="LogClickCount(this,336);">Bootstrap</a>
    </div>


</div>
  <script language="javascript" type="text/javascript">     
      $(function(){
              setTimeout(function(){
                  $.get("/u013573133/svc/GetTagContent",function(data){
                      $(".tag_list").html(data).show();
                  });     
              });
          },500);                       
 </script> 




<div id="pop_win" style="display:none ;position: absolute; z-index: 10000; border: 1px solid rgb(220, 220, 220); top: 222.5px; left: 630px; opacity: 1; background: none 0px 0px repeat scroll rgb(255, 255, 255);">
    
</div>
<div id="popup_mask"></div>
<style>
    #popup_mask
    {
        position: absolute;
        width: 100%;
        height: 100%;
        background: #000;
        z-index: 9999;
        left: 0px;
        top: 0px;
        opacity: 0.3;
        filter: alpha(opacity=30);
        display: none;
    }


</style>








<script type="text/javascript">
    $(function(){
        setTimeout(function(){
            $(".comment_body:contains('回复')").each(function(index,item){
                var u=$(this).text().split(':')[0].toString().replace("回复","")
                var thisComment=$(this);
                if(u)
                {
                    $.getJSON("https://passport.csdn.net/get/nick?callback=?", {users: u}, function(a) {
                        if(a!=null&&a.data!=null&&a.data.length>0)
                        {
                            nick=a.data[0].n; 
                            if(u!=nick)
                            {
                                thisComment.text(thisComment.text().replace(u,nick));  
                            }
                        }       
                    });  
                }
            });         


        },200);  


        setTimeout(function(){
            $(".math").each(function(index,value){$(this).find("span").last().css("color","#fff"); })
        },5000);


        setTimeout(function(){
            $(".math").each(function(index,value){$(this).find("span").last().css("color","#fff"); })
        },10000);


        setTimeout(function(){
            $(".math").each(function(index,value){$(this).find("span").last().css("color","#fff"); })
        },15000);
        
        setTimeout(function(){
            $("a img[src='http://js.tongji.linezing.com/stats.gif']").parent().css({"position":"absolute","left":"50%"});
        },300);
    });


    function loginbox(){
        var $logpop=$("#pop_win");
        $logpop.html('<iframe src="https://passport.csdn.net/account/loginbox?service=http://static.blog.csdn.net/callback.htm" frameborder="0" height="600" width="400" scrolling="no"></iframe>');


        $('#popup_mask').css({
            opacity: 0.5,
            width: $( document ).width() + 'px',
            height:  $( document ).height() + 'px'
        });
        $('#popup_mask').css("display","block");
 
        $logpop.css( {
            top: ($( window ).height() - $logpop.height())/ 2  + $( window 
       ).scrollTop() + 'px',
            left:($( window ).width() - $logpop.width())/ 2
        } );
 
        setTimeout( function () {
            $logpop.show();
            $logpop.css( {
                opacity: 1
            } );
        }, 200 );
 
        $('#popup_mask').unbind("click");
        $('#popup_mask').bind("click", function(){
            $('#popup_mask').hide();
            var $clopop = $("#pop_win");
            $("#common_ask_div_sc").css("display","none");
            $clopop.css( {
                opacity: 0
            } );
            setTimeout( function () {
                $clopop.hide();
            }, 350 );
            return false;
        });
    }   


</script>
 <script language="javascript" type="text/javascript" src="http://ads.csdn.net/js/async_new.js"></script>      








                        <div class="clear">
                        </div>
                    </div>                   
                
            </div>
0 0