一:介绍

1.说明

  Storm里面引入DRPC主要是利用storm的实时计算能力来并行化CPU intensive的计算。DRPC的storm topology以函数的参数流作为输入,而把这些函数调用的返回值作为topology的输出流。

2.工作机制

  Distributed RPC是由一个”DPRC Server”协调的(storm自带了一个实现)DRPC服务器协调

  1) 接收一个RPC请求。

  2) 发送请求到storm topology

  3) 从storm topology接收结果。

  4) 把结果发回给等待的客户端。从客户端的角度来看一个DRPC调用跟一个普通的RPC调用没有任何区别。

3.工作流程

  

  客户端给DRPC服务器发送要执行的方法的名字,以及这个方法的参数。

  实现了这个函数的topology使用 DRPCSpout 从DRPC服务器接收函数调用流。

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

二:本地DRPC

1.主驱动类

 package com.jun.tridentWithHbase;

 import backtype.storm.Config;
import backtype.storm.LocalCluster;
import backtype.storm.LocalDRPC;
import backtype.storm.StormSubmitter;
import backtype.storm.generated.AlreadyAliveException;
import backtype.storm.generated.InvalidTopologyException;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Values;
import org.apache.storm.hbase.trident.state.HBaseMapState;
import storm.trident.Stream;
import storm.trident.TridentState;
import storm.trident.TridentTopology;
import storm.trident.operation.builtin.Count;
import storm.trident.operation.builtin.MapGet;
import storm.trident.operation.builtin.Sum;
import storm.trident.state.OpaqueValue;
import storm.trident.state.StateFactory;
import storm.trident.testing.FixedBatchSpout;
import storm.trident.testing.MemoryMapState; public class TridentDemo {
public static void main(String[] args) throws AlreadyAliveException, InvalidTopologyException {
TridentTopology tridentTopology=new TridentTopology();
//模拟数据
Fields field=new Fields("log","flag");
FixedBatchSpout spout=new FixedBatchSpout(field,5,
new Values("168.214.187.214 - - [1481953616092] \"GET /view.php HTTP/1.1\" 200 0 \"http://cn.bing.com/search?q=spark mllib\" \"Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1\" \"-\"","A"),
new Values("168.187.202.202 - - [1481953537038] \"GET /IBEIfeng.gif?order_id=1063&orderTime=1481953537038&memberId=4000012340500607&productInfos=10005-2099.48-B-1|10004-1886.62-A-2|10001-961.99-A-1&orderAmt=6834.70 HTTP/1.1\" 200 0 \"-\" \"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2;Tident/6.0)\" \"-\"","A"),
new Values("61.30.167.187 - - [1481953539039] \"GET /IBEIfeng.gif?order_id=1064&orderTime=1481953539039&memberId=4000930409959999&productInfos=10007-3329.13-B-1|10009-2607.71-B-1|10002-390.62-A-1|10006-411.00-B-2&orderAmt=7149.46 HTTP/1.1\" 200 0 \"-\" \"Mozilla/5.0 (Linux; Android 4.2.1; Galaxy Nexus Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19\" \"-\"","A"),
new Values("30.29.132.190 - - [1481953544042] \"GET /IBEIfeng.gif?order_id=1065&orderTime=1481953544043&memberId=1234568970080798&productInfos=10005-2099.48-B-1|10001-3242.40-C-2|10006-411.00-B-1&orderAmt=8995.28 HTTP/1.1\" 200 0 \"-\" \"Mozilla/5.0 (iPhone; CPU iPhone OS 7_)_3 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B511 Safari/9537.53\" \"-\"","B"),
new Values("222.190.187.201 - - [1481953578068] \"GET /IBEIfeng.gif?order_id=1066&orderTime=1481953578068&memberId=3488586887970809&productInfos=10005-2099.48-B-1|10001-2774.16-C-2&orderAmt=7647.80 HTTP/1.1\" 200 0 \"-\" \"Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1\" \"-\"","B"),
new Values("72.202.43.53 - - [1481953579069] \"GET /IBEIfeng.gif?order_id=1067&orderTime=1481953579069&memberId=2084859896989877&productInfos=10007-3329.13-B-1|10001-961.99-A-2&orderAmt=5253.10 HTTP/1.1\" 200 0 \"-\" \"Mozilla/5.0 (Linux; Android 4.2.1; Galaxy Nexus Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19\" \"-\"","B")
);
//多次循环
spout.setCycle(true);
//流处理
Stream stream=tridentTopology.newStream("orderAnalyse",spout)
//过滤
.each(new Fields("log"),new ValidLogFilter())
//解析
.each(new Fields("log"), new LogParserFunction(),new Fields("orderId","orderTime","orderAmtStr","memberId"))
//投影
.project(new Fields("orderId","orderTime","orderAmtStr","memberId"))
//时间解析
.each(new Fields("orderTime"),new DateTransFormerFunction(),new Fields("day","hour","minter"))
;
//分流
//1.基于minter统计订单数量,分组统计
TridentState state=stream.groupBy(new Fields("minter"))
//全局聚合,使用内存存储状态信息
.persistentAggregate(new MemoryMapState.Factory(),new Count(),new Fields("orderNumByMinter"));
// state.newValuesStream().each(new Fields("minter","orderNumByMinter"),new PrintFilter()); //2.另一个流,基于分钟的订单金额,局部聚合
Stream partitionStream=stream.each(new Fields("orderAmtStr"),new TransforAmtToDoubleFunction(),new Fields("orderAmt"))
.groupBy(new Fields("minter"))
//局部聚合
.chainedAgg() //聚合链
.partitionAggregate(new Fields("orderAmt"),new LocalSum(),new Fields("orderAmtSumOfLocal"))
.chainEnd(); //聚合链 //做一次全局聚合
TridentState partitionState=partitionStream.groupBy(new Fields("minter"))
//全局聚合
.persistentAggregate(new MemoryMapState.Factory(),new Fields("orderAmtSumOfLocal"),new Sum(),new Fields("totalOrderAmt"));
partitionState.newValuesStream().each(new Fields("minter","totalOrderAmt"),new PrintFilter()); //提交
Config config=new Config();
if(args==null || args.length<=0){
//应该是构建一个DRPC的服务器
LocalDRPC localDRPC=new LocalDRPC();
tridentTopology.newDRPCStream("orderDataServer",localDRPC)
//参数处理
.each(new Fields("args"),new RequestParamsParserFunction(),new Fields("date"))
//查询,重要的参数是上面的partitionState
.stateQuery(partitionState,new Fields("date"),new MapGet(),new Fields("totalAmtByMinter"))
//投影
.project(new Fields("date","totalAmtByMinter"));
//提交任务
LocalCluster localCluster=new LocalCluster();
localCluster.submitTopology("tridentDemo",config,tridentTopology.build());
//获取值
String jsonResult=localDRPC.execute("orderDataServer","201612171345 201612171345");
System.out.println("***"+jsonResult+"***"); }else {
config.setNumWorkers(2);
StormSubmitter.submitTopology(args[0],config,tridentTopology.build());
}
}
}

2.请求参数处理类

 package com.jun.tridentWithHbase;

 import backtype.storm.tuple.Values;
import storm.trident.operation.Function;
import storm.trident.operation.TridentCollector;
import storm.trident.operation.TridentOperationContext;
import storm.trident.tuple.TridentTuple; import java.util.Map; public class RequestParamsParserFunction implements Function {
@Override
public void execute(TridentTuple tridentTuple, TridentCollector tridentCollector) {
String parameters=tridentTuple.getStringByField("args");
String[] params=parameters.split(" ");
for (String param:params){
tridentCollector.emit(new Values(param));
}
} @Override
public void prepare(Map map, TridentOperationContext tridentOperationContext) { } @Override
public void cleanup() { }
}

3.效果

  

三:集群模式的DRPC 

1.主驱动类

  config.setNumWorkers(2);
//集群上构建DRPC服务器
tridentTopology.newDRPCStream("orderDataServer")
//参数处理
.each(new Fields("args"),new RequestParamsParserFunction(),new Fields("date"))
//查询,重要的参数是上面的partitionState
.stateQuery(partitionState,new Fields("date"),new MapGet(),new Fields("totalAmtByMinter"))
//投影
.project(new Fields("date","totalAmtByMinter"));
StormSubmitter.submitTopology(args[0],config,tridentTopology.build());

2.配置DRPC服务和端口

  

3.启动storm

4.启动Drpc进程

  在drpc.servers参数所指定的服务器上。

  命令:nohup bin/storm drpc >>/dev/null 2>&1 &

  查看端口是否正常打开:netstat -tlnup | grep 3772

5.将jar包提交到集群上

6.编写客户端

 package com.jun.tridentWithKafka;

 import backtype.storm.generated.DRPCExecutionException;
import backtype.storm.utils.DRPCClient;
import org.apache.thrift7.TException; public class DrpcClientDemo {
public static void main(String[] args) {
DRPCClient drpcClient=new DRPCClient("linux-hadoop01.ibeifeng.com",3772);
try {
String jsonResult=drpcClient.execute("orderDataServer","201612171345 201612171345");
System.out.println("==="+jsonResult+"===");
} catch (TException e) {
e.printStackTrace();
} catch (DRPCExecutionException e) {
e.printStackTrace();
}
}
}

  

Trident中的DRPC实现的更多相关文章

  1. Trident中使用HBase进行状态管理

    1.使用的类 2.使用HBaseMapState 3.使用状态管理 使用的状态管理还要看Spout StateFactory factory1 = HBaseMapState.opaque(opts1 ...

  2. Trident中的过滤与函数的区别

    1.共同点 都需要实现storm.trident.operation.Function接口 2.不同点 其中函数有发射这个步骤. .each(new Fields("orderTime&qu ...

  3. Trident中的解析包含的函数操作与投影操作

    一:函数操作 1.介绍 Tuple本身是不可变的 Function只是在原有的基础上追加新的tuple 2.说明 如果原来的字段是log,flag 新增之后的tuple可以访问这些字段,log,fla ...

  4. Trident中 FixedBatchSpout分析

    FixedBatchSpout 继承自 IBatchSpout IBatchSpout 方法 public interface IBatchSpout extends Serializable { v ...

  5. storm trident 示例

    Storm Trident的核心数据模型是一批一批被处理的“流”,“流”在集群的分区在集群的节点上,对“流”的操作也是并行的在每个分区上进行. Trident有五种对“流”的操作: 1.      不 ...

  6. [翻译][Trident] Trident state原理

    原文地址:https://github.com/nathanmarz/storm/wiki/Trident-state ----------------------------- Trident在读写 ...

  7. storm的trident编程模型

    storm的基本概念别人总结的, https://blog.csdn.net/pickinfo/article/details/50488226 编程模型最关键最难就是实现局部聚合的业务逻辑聚合类实现 ...

  8. 访问WEB-INF目录中的JSP文件

    方法1:本来WEB-INF中的jsp就是无法通过地址栏访问的.所以安全.如果说你要访问这个文件夹中的jsp文件需要在项目的web.xml文件中去配置servlet格式差不多的配置就ok了.如下: 访问 ...

  9. Storm系列(十七)DRPC介绍

    Storm版本0.9.5 在storm中DRPC服务应用于远程分布式计算,根据客户端提交的请求参数,而返回Storm计算的结果. DRPC服务启动流程(远程模式) 启动DRPC服务,启动命令:stor ...

随机推荐

  1. Truffle框架环境搭建

    注意:本教程需要Truffle4.0或者是更高的版本 以太坊的智能合约只是代码,和我们的纸质代码不同,此合同需要非常精确的方式理解 如果合同编码不正确,我们的交易可能会失败,会导致gas的损失,更不用 ...

  2. Idea-Java接入银联支付的Demo

    注:本文来源于:< Idea-Java接入银联支付的Demo > 接入银联支付的Demo,希望能给大家节约一点时间 https://github.com/wangfei0904306/un ...

  3. Confluence 6 安装 Oracle

    如果你还没有在安装可以连接的 Oracle 数据库,请先下载后进行安装.请参考 Oracle 文档 来获取有关安装的指南. 当你设置你的 Oracle 服务器的时候: 字符集 必须使用 AL32UTF ...

  4. Confluence 6 用自带的用户管理

    在一些特定的情况下,你可能希望禁用 Confluence 自带的用户管理或完全使用外部的用户目录进行用户管理.例如 Jira 软件或者 Jira Service Desk.你可以在 Confluenc ...

  5. 巧用&&和|| 让逻辑代码更简洁,逼格看起来更高一点(玩笑脸)

    通常当我们有一个需求 需要用到很多if else 进行条件筛选,例如: let level = 0; if(score > 12){ level = 4; } else if(score > ...

  6. python魔法函数之__getattr__与__getattribute__

    getattr 在访问对象的属性不存在时,调用__getattr__,如果没有定义该魔法函数会报错 class Test: def __init__(self, name, age): self.na ...

  7. js获取到的页面中的checkbox选中的项

    需求描述:列表第一列是checkbox name和value都是id 想通过复选框的勾选状态来获取id,在js中获取 js代码: var checkId=$("input[name='che ...

  8. java----static关键字(包括final)

    static修饰字段: 使用static关键字修饰一个字段:声明的static变量实际上就是一个全局变量 使用static关键字修饰一个方法:可以直接使用类调用方法,和对象没有关系了 使用static ...

  9. cf1108E2 线段树类似扫描线

    /* 有点像扫描线 思路:从左到右枚举每个点,枚举到点i时,把所有以i为起点的区间的影响删去 再加上以i-1为结尾的区间的影响 */ #include<bits/stdc++.h> usi ...

  10. bzoj 3566

    非常好也是比较难的题 首先,不难看出这是一道树形的概率dp 那么我们就要考虑转移 我们发现,一个点能充上电的概率是这个点本身通电的概率+这个点的子节点给他传过来电的概率+这个点的父节点给他传过来电的概 ...