spark源码阅读之network(2)
在上节的解读中发现spark的源码中大量使用netty的buffer部分的api,该节将看到netty核心的一些api,比如channel:
privatestaticclassClientPool{
TransportClient[] clients;
Object[] locks;
publicClientPool(int size){
clients =newTransportClient[size];
locks =newObject[size];
for(int i =0; i < size; i++){
locks[i]=newObject();
}
}
publicTransportClient createClient(String remoteHost,int remotePort)throwsIOException{
// Get connection from the connection pool first.
// If it is not found or not active, create a new one.
finalInetSocketAddress address =newInetSocketAddress(remoteHost, remotePort);
// Create the ClientPool if we don't have it yet.
ClientPool clientPool = connectionPool.get(address);
if(clientPool ==null){
connectionPool.putIfAbsent(address,newClientPool(numConnectionsPerPeer));
clientPool = connectionPool.get(address);
}
int clientIndex = rand.nextInt(numConnectionsPerPeer);
TransportClient cachedClient = clientPool.clients[clientIndex];
if(cachedClient !=null&& cachedClient.isActive()){
logger.trace("Returning cached connection to {}: {}", address, cachedClient);
return cachedClient;
}
// If we reach here, we don't have an existing connection open. Let's create a new one.
// Multiple threads might race here to create new connections. Keep only one of them active.
synchronized(clientPool.locks[clientIndex]){
cachedClient = clientPool.clients[clientIndex];
if(cachedClient !=null){
if(cachedClient.isActive()){
logger.trace("Returning cached connection to {}: {}", address, cachedClient);
return cachedClient;
}else{
logger.info("Found inactive connection to {}, creating a new one.", address);
}
}
clientPool.clients[clientIndex]= createClient(address);
return clientPool.clients[clientIndex];
}
}
*/
publicTransportClient createUnmanagedClient(String remoteHost,int remotePort)
throwsIOException{
finalInetSocketAddress address =newInetSocketAddress(remoteHost, remotePort);
return createClient(address);
}
/** Create a completely new {@link TransportClient} to the remote address. */
privateTransportClient createClient(InetSocketAddress address)throwsIOException{
logger.debug("Creating new connection to "+ address);
Bootstrap bootstrap =newBootstrap();
bootstrap.group(workerGroup)
.channel(socketChannelClass)
// Disable Nagle's Algorithm since we don't want packets to wait
.option(ChannelOption.TCP_NODELAY,true)
.option(ChannelOption.SO_KEEPALIVE,true)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, conf.connectionTimeoutMs())
.option(ChannelOption.ALLOCATOR, pooledAllocator);
finalAtomicReference<TransportClient> clientRef =newAtomicReference<TransportClient>();
finalAtomicReference<Channel> channelRef =newAtomicReference<Channel>();
bootstrap.handler(newChannelInitializer<SocketChannel>(){
@Override
publicvoid initChannel(SocketChannel ch){
TransportChannelHandler clientHandler = context.initializePipeline(ch);
clientRef.set(clientHandler.getClient());
channelRef.set(ch);
}
});
// Connect to the remote server
long preConnect =System.nanoTime();
ChannelFuture cf = bootstrap.connect(address);
if(!cf.awaitUninterruptibly(conf.connectionTimeoutMs())){
thrownewIOException(
String.format("Connecting to %s timed out (%s ms)", address, conf.connectionTimeoutMs()));
}elseif(cf.cause()!=null){
thrownewIOException(String.format("Failed to connect to %s", address), cf.cause());
}
TransportClient client = clientRef.get();
Channel channel = channelRef.get();
assert client !=null:"Channel future completed successfully with null client";
// Execute any client bootstraps synchronously before marking the Client as successful.
long preBootstrap =System.nanoTime();
logger.debug("Connection to {} successful, running bootstraps...", address);
try{
for(TransportClientBootstrap clientBootstrap : clientBootstraps){
clientBootstrap.doBootstrap(client, channel);
}
}catch(Exception e){// catch non-RuntimeExceptions too as bootstrap may be written in Scala
long bootstrapTimeMs =(System.nanoTime()- preBootstrap)/1000000;
logger.error("Exception while bootstrapping client after "+ bootstrapTimeMs +" ms", e);
client.close();
throwThrowables.propagate(e);
}
long postBootstrap =System.nanoTime();
logger.debug("Successfully created connection to {} after {} ms ({} ms spent in bootstraps)",
address,(postBootstrap - preConnect)/1000000,(postBootstrap - preBootstrap)/1000000);
return client;
}
privatefinalChannel channel;
privatefinalTransportResponseHandler handler;
@NullableprivateString clientId;
publicvoid fetchChunk(
long streamId,
finalint chunkIndex,
finalChunkReceivedCallback callback){
finalString serverAddr =NettyUtils.getRemoteAddress(channel);
finallong startTime =System.currentTimeMillis();
logger.debug("Sending fetch chunk request {} to {}", chunkIndex, serverAddr);
finalStreamChunkId streamChunkId =newStreamChunkId(streamId, chunkIndex);
handler.addFetchRequest(streamChunkId, callback);
channel.writeAndFlush(newChunkFetchRequest(streamChunkId)).addListener(
newChannelFutureListener(){
@Override
publicvoid operationComplete(ChannelFuture future)throwsException{
if(future.isSuccess()){
long timeTaken =System.currentTimeMillis()- startTime;
logger.trace("Sending request {} to {} took {} ms", streamChunkId, serverAddr,
timeTaken);
}else{
String errorMsg =String.format("Failed to send request %s to %s: %s", streamChunkId,
serverAddr, future.cause());
logger.error(errorMsg, future.cause());
handler.removeFetchRequest(streamChunkId);
channel.close();
try{
callback.onFailure(chunkIndex,newIOException(errorMsg, future.cause()));
}catch(Exception e){
logger.error("Uncaught exception in RPC response callback handler!", e);
}
}
}
});
}
publicvoid stream(finalString streamId,finalStreamCallback callback){
finalString serverAddr =NettyUtils.getRemoteAddress(channel);
finallong startTime =System.currentTimeMillis();
logger.debug("Sending stream request for {} to {}", streamId, serverAddr);
// Need to synchronize here so that the callback is added to the queue and the RPC is
// written to the socket atomically, so that callbacks are called in the right order
// when responses arrive.
synchronized(this){
handler.addStreamCallback(callback);
channel.writeAndFlush(newStreamRequest(streamId)).addListener(
newChannelFutureListener(){
@Override
publicvoid operationComplete(ChannelFuture future)throwsException{
if(future.isSuccess()){
long timeTaken =System.currentTimeMillis()- startTime;
logger.trace("Sending request for {} to {} took {} ms", streamId, serverAddr,
timeTaken);
}else{
String errorMsg =String.format("Failed to send request for %s to %s: %s", streamId,
serverAddr, future.cause());
logger.error(errorMsg, future.cause());
channel.close();
try{
callback.onFailure(streamId,newIOException(errorMsg, future.cause()));
}catch(Exception e){
logger.error("Uncaught exception in RPC response callback handler!", e);
}
}
}
});
}
}
publicbyte[] sendRpcSync(byte[] message,long timeoutMs){
finalSettableFuture<byte[]> result =SettableFuture.create();
sendRpc(message,newRpcResponseCallback(){
@Override
publicvoid onSuccess(byte[] response){
result.set(response);
}
@Override
publicvoid onFailure(Throwable e){
result.setException(e);
}
});
try{
return result.get(timeoutMs,TimeUnit.MILLISECONDS);
}catch(ExecutionException e){
throwThrowables.propagate(e.getCause());
}catch(Exception e){
throwThrowables.propagate(e);
}
}
spark源码阅读之network(2)的更多相关文章
- spark源码阅读之network(1)
spark将在1.6中替换掉akka,而采用netty实现整个集群的rpc的框架,netty的内存管理和NIO支持将有效的提高spark集群的网络传输能力,为了看懂这块代码,在网上找了两本书看< ...
- spark源码阅读之network(3)
TransportContext用来创建TransportServer和TransportclientFactory,同时使用TransportChannelHandler用来配置channel的pi ...
- Spark源码阅读之存储体系--存储体系概述与shuffle服务
一.概述 根据<深入理解Spark:核心思想与源码分析>一书,结合最新的spark源代码master分支进行源码阅读,对新版本的代码加上自己的一些理解,如有错误,希望指出. 1.块管理器B ...
- win7+idea+maven搭建spark源码阅读环境
1.参考. 利用IDEA工具编译Spark源码(1.60~2.20) https://blog.csdn.net/He11o_Liu/article/details/78739699 Maven编译打 ...
- spark源码阅读
根据spark2.2的编译顺序来确定源码阅读顺序,只阅读核心的基本部分. 1.common目录 ①Tags②Sketch③Networking④Shuffle Streaming Service⑤Un ...
- emacs+ensime+sbt打造spark源码阅读环境
欢迎转载,转载请注明出处,徽沪一郎. 概述 Scala越来越流行, Spark也愈来愈红火, 对spark的代码进行走读也成了一个很普遍的行为.不巧的是,当前java社区中很流行的ide如eclips ...
- spark源码阅读---Utils.getCallSite
1 作用 当该方法在spark内部代码中调用时,会返回当前调用spark代码的用户类的名称,以及其所调用的spark方法.所谓用户类,就是我们这些用户使用spark api的类. 2 内部实现 2.1 ...
- spark源码阅读--SparkContext启动过程
##SparkContext启动过程 基于spark 2.1.0 scala 2.11.8 spark源码的体系结构实在是很庞大,从使用spark-submit脚本提交任务,到向yarn申请容器,启 ...
- Spark源码阅读(1): Stage划分
Spark中job由action动作生成,那么stage是如何划分的呢?一般的解答是根据宽窄依赖划分.那么我们深入源码看看吧 一个action 例如count,会在多次runJob中传递,最终会到一个 ...
随机推荐
- call、apply、bind用法区别
call call() 方法调用一个函数, 其具有一个指定的 this 值和分别地提供的参数(参数的列表). <p class="danger"> 注意:该方法的作用和 ...
- TortoiseGit不同分支合并代码
现在有主分支master和分支day2.现在要把day2上的变更合并到主分支master上! 1.首先切换到目标分支master上. 说明当前分支是master分支. 2.在master分支上查看提交 ...
- vue router 传参 获取不到query,params
千万要注意,获取query/params 是this.$route.query 不是this.$router.query!!!
- vuecli3修改项目启动端口
工作中可能存在启动多个项目的时候,默认端口号会被占,导致启动错误,这种情况下只要把要启动的项目的端口号换掉启动未用的端口就可以了,具体实现如下: vuecli3中的端口文件存放目录为:node_mod ...
- 第17篇 shell编程基础(2)
shell study 1.Exit StatusIf the command executed successfully (or true), the value of $? is zero. If ...
- TCP报文送达确认ACK
TCP数据包中的序列号(Sequence Number)不是以报文段来进行编号的,而是将连接生存周期内传输的所有数据当作一个字节流,序列号就是整个字节流中每个字节的编号.一个TCP数据包中包含多个字节 ...
- 南阳OJ 61 传纸条(一)
传纸条(一) 时间限制:2000 ms | 内存限制:65535 KB 难度:5 描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行 ...
- linux 下SPI通信注意事项(待续)
一.2台Linux设备之间使用SPI通信 1.标准Linux只支持Master 模式.但是可以在驱动中修改为Slave模式: 2.硬件SPI可能支持Slave模式,也可能不支持.这个要提前确认好: 3 ...
- mysql索引之六:mysql高效索引之覆盖索引
概念 如果索引包含所有满足查询需要的数据的索引成为覆盖索引(Covering Index),也就是平时所说的不需要回表操作 判断标准 使用explain,可以通过输出的extra列来判断,对于一个索引 ...
- 权益保护-知识产权:知识产权(IP)百科
ylbtech-权益保护-知识产权:知识产权(IP)百科 知识产权,也称其为“知识所属权”,指“权利人对其智力劳动所创作的成果和经营活动中的标记.信誉所依法享有的专有权利”,一般只在有限时间内有效.各 ...