Twitter Storm - DRPC

简介:

DRPC ,Distributed Remote Procedure Call 
RPC本身是个成熟和古老的概念, Storm里面引入DRPC主要是利用storm的实时计算能力来并行化CPU intensive的计算

DRPC, 只是storm应用的一个场景, 并且storm提供相应的编程框架, 以方便程序员

提供DRPC server的实现, 并提供对DRPC场景经行封装的Topology  
对于storm, Topology内部其实是没有任何区别的, 主要就是实现和封装Topology和DRPC Server之间交互的spout和bolt  
具体交互过程如下图,

image

 

LinearDRPCTopologyBuilder

Storm封装了这样一个Topology实现LinearDRPCTopologyBuilder的topology builder

会使用DRPCSpout从DRPC服务器接收函数调用流, 每个函数调用被DRPC服务器标记了一个唯一的id. 
这个topology然后计算结果, 在topology的最后一个叫做ReturnResults的bolt会连接到DRPC服务器, 并且把这个调用的结果发送给DRPC服务器(通过那个唯一的id标识). 
DRPC服务器用那个唯一id来跟等待的客户端匹配上,唤醒这个客户端并且把结果发送给它.

public static class ExclaimBolt implements IBasicBolt {
    public void prepare(Map conf, TopologyContext context) {
    }
 
    public void execute(Tuple tuple, BasicOutputCollector collector) {
        String input = tuple.getString(1);
        collector.emit(new Values(tuple.getValue(0), input + "!"));
    }
 
    public void cleanup() {
    }
 
    public void declareOutputFields(OutputFieldsDeclarer declarer) {
        declarer.declare(new Fields("id", "result"));
    }
 
}
 
public static void main(String[] args) throws Exception {
    LinearDRPCTopologyBuilder builder
        = new LinearDRPCTopologyBuilder("exclamation");
    builder.addBolt(new ExclaimBolt(), 3);
    // ...
}

使用LinearDRPCTopologyBuilder

首先, 使用builder创建topology的时候, topology name要等于function name(PRC call) 
其次, 这里不需要指定spout, 因为已经做了封装, 会自动从DRPC server读取数据 
再者, 所有bolt的输出的第一个field必须是request-id, 最后一般bolt的输出一定是(request-id, result) 
最后, builder会自动将结果发给DRPC server

 

A more complex example, ReachTopology

前面的例子, 无法说明为什么要使用storm来实现RPC, 那个操作直接在RPC server上就可以完成 
当只有对并行计算和数据量有一定要求时, 才能体现出价值... 
ReachTopology, 每个人发送的URL都会被所有follower收到, 所以要计算某URL的reach, 只需要如下几步, 
找出所有发送该URL的tweeter, 取出他们的follower, 去重复, 计数

Let's look at a more complex example which really needs the parallelism a Storm cluster provides for computing the DRPC function. 
The example we'll look at is computing the reach of a URL on Twitter.

The reach of a URL is the number of unique people exposed to a URL on Twitter. To compute reach, you need to:

  1. Get all the people who tweeted the URL
  2. Get all the followers of all those people
  3. Unique the set of followers
  4. Count the unique set of followers
LinearDRPCTopologyBuilder builder = new LinearDRPCTopologyBuilder("reach");
builder.addBolt(new GetTweeters(), 3);
builder.addBolt(new GetFollowers(), 12)
        .shuffleGrouping();
builder.addBolt(new PartialUniquer(), 6)
        .fieldsGrouping(new Fields("id", "follower"));
builder.addBolt(new CountAggregator(), 2)
        .fieldsGrouping(new Fields("id"));

首先对于LinearDRPCTopologyBuilder中, 没有各个spout和bolt的id, 可能因为是线性的, 所以没有必要显式指明关系, 按加入顺序就可以 
GetTweeters(), 输入(rpc-id, url), 输出(rpc-id, tweeter) 
GetFollowers(), 输入(rpc-id, tweeter), 输出(rpc-id, follower)

对于PartialUniquer仔细分析一下, 
首先是基于id和follower的grouping, fieldsGrouping(new Fields("id", "follower")), 因为可能由多个RPC同时执行, 所以只需要保证同一个RPC的followers被发到同一个task即可. 
接着继承BaseBatchBolt, 可以在finishBatch中emit结果 
使用HashSet来存放follower, 保证不重复

    public static class PartialUniquer extends BaseBatchBolt {
        BatchOutputCollector _collector;
        Object _id;
        Set<String> _followers = new HashSet<String>();
        
        @Override
        public void prepare(Map conf, TopologyContext context, BatchOutputCollector collector, Object id) {
            _collector = collector;
            _id = id;
        }

        @Override
        public void execute(Tuple tuple) {
            _followers.add(tuple.getString(1));
        }
        
        @Override
        public void finishBatch() {
            _collector.emit(new Values(_id, _followers.size()));
        }

        @Override
        public void declareOutputFields(OutputFieldsDeclarer declarer) {
            declarer.declare(new Fields("id", "partial-count"));
        }
    }

 

Non-linear DRPC topologies

当前LinearDRPCTopologyBuilder只能handle线性的bolt workflow 

LinearDRPCTopologyBuilder only handles "linear" DRPC topologies, where the computation is expressed as a sequence of steps (like reach). It's not hard to imagine functions that would require a more complicated topology with branching and merging of the bolts. For now, to do this you'll need to drop down into using CoordinatedBolt directly. Be sure to talk about your use case for non-linear DRPC topologies on the mailing list to inform the construction of more general abstractions for DRPC topologies.


本文章摘自博客园,原文发布日期:2013-05-08

目录
相关文章
|
JSON 小程序 前端开发
微信小程序的目录结构及页面结构的说明
本文详细介绍了微信小程序的目录结构、页面组成部分以及项目的全局配置文件,阐述了小程序的宿主环境和运行机制,包括小程序启动和页面渲染的过程。
微信小程序的目录结构及页面结构的说明
|
数据采集 JavaScript 前端开发
如何判断一个网站是否采取了反爬虫措施
通过观察请求响应、分析请求频率限制和检测JavaScript动态加载来初步判断网站是否使用反爬虫措施。使用Python `requests` 发送请求并检查响应头和内容,寻找验证码、限制信息。尝试短时间内多次请求,看是否被限制。使用Selenium模拟浏览器行为,获取动态加载内容。注意,这些方法仅为初步判断,实际可能需更深入分析,并确保爬取行为合法合规。
|
缓存 运维 监控
|
NoSQL Java Redis
Spring Boot集成Redis全攻略:高效数据存取,打造性能飞跃的Java微服务应用!
【8月更文挑战第3天】Spring Boot是备受欢迎的微服务框架,以其快速开发与轻量特性著称。结合高性能键值数据库Redis,可显著增强应用性能。集成步骤包括:添加`spring-boot-starter-data-redis`依赖,配置Redis服务器参数,注入`RedisTemplate`或`StringRedisTemplate`进行数据操作。这种集成方案适用于缓存、高并发等场景,有效提升数据处理效率。
1433 2
|
Web App开发 存储 JavaScript
前端如何学习Node.js及Node.js的主要用途
【7月更文挑战第16天】 学习Node.js对前端开发者至关重要,涉及理解其基于V8的运行时环境、JavaScript基础、安装与验证、核心模块(如fs、http、path)及npm管理。实践项目,如用Express建服务器,参与开源,深入学习异步编程和事件循环。Node.js用于服务器开发、构建工具、本地开发服务器和实时应用,提升全栈能力。借助官方文档和各种资源加速学习。
748 4
|
Ubuntu 文件存储 Docker
使用nas唤醒其他PC主机
使用nas唤醒其他PC主机
|
机器学习/深度学习 算法 Python
【Python 机器学习专栏】随机森林算法的性能与调优
【4月更文挑战第30天】随机森林是一种集成学习方法,通过构建多棵决策树并投票或平均预测结果,具有高准确性、抗过拟合、处理高维数据的能力。关键性能因素包括树的数量、深度、特征选择和样本大小。调优方法包括调整树的数量、深度,选择关键特征和参数优化。Python 示例展示了使用 GridSearchCV 进行调优。随机森林广泛应用于分类、回归和特征选择问题,是机器学习中的重要工具。
1357 1
|
SQL NoSQL 关系型数据库
13 秒插入 30 万条数据,这才是批量插入正确的姿势!
【8月更文挑战第9天】在数据处理和数据库管理中,高效批量插入数据是一项至关重要的技能。无论是大数据分析、日志处理还是业务数据快速导入,高效的批量插入能力都能显著提升系统性能和用户体验。今天,我们就来深入探讨如何在极短时间内(如13秒内)向数据库批量插入30万条数据,分享那些被验证过的高效技术和最佳实践。
1806 0
|
Windows
Windows Kill 被占用的端口
Windows Kill 被占用的端口
518 0
Windows Kill 被占用的端口
|
分布式计算 大数据 Hadoop
Python大数据之PySpark(二)PySpark安装
Python大数据之PySpark(二)PySpark安装
1430 0

热门文章

最新文章