alluxio源码解析-netty部分(2)
netty简介
netty作为alluxio中重要的通讯组件
在常见的客户端上传,下载中,都会有netty的参与

关于这个图,可以看上篇文章的介绍:
https://www.cnblogs.com/victor2302/p/10490253.html
- 解耦ufs和worker缓存的功能
- 解耦 BlockHandler和 ShortCircuitBlockHandler
- 解耦异步上传,同步上传
- 高性能传输
netty客户端部分:
1.固定的处理器:alluxio.network.netty.NettyClient
final Bootstrap boot = new Bootstrap(); boot.group(WORKER_GROUP)
.channel(NettyUtils.getClientChannelClass(!(address instanceof InetSocketAddress)));
boot.option(ChannelOption.SO_KEEPALIVE, true);
boot.option(ChannelOption.TCP_NODELAY, true);
boot.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
if (NettyUtils.USER_CHANNEL_TYPE == ChannelType.EPOLL) {
boot.option(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);
} // After 10 missed heartbeat attempts and no write activity, the server will close the channel.
final long timeoutMs = Configuration.getMs(PropertyKey.NETWORK_NETTY_HEARTBEAT_TIMEOUT_MS);
final long heartbeatPeriodMs = Math.max(timeoutMs / 10, 1);
boot.handler(new ChannelInitializer<Channel>() {
@Override
public void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(RPCMessage.createFrameDecoder());
pipeline.addLast(ENCODER);
pipeline.addLast(DECODER);
pipeline.addLast(new IdleStateHandler(0, heartbeatPeriodMs, 0, TimeUnit.MILLISECONDS));
pipeline.addLast(new IdleWriteHandler());
}
});
2.临时的处理器:针对通用response注册回调(ShortCircuitBlockHandler 调用)
public static ProtoMessage call(final NettyRPCContext context, ProtoMessage request)
throws IOException {
Channel channel = Preconditions.checkNotNull(context.getChannel());
final Promise<ProtoMessage> promise = channel.eventLoop().newPromise();
channel.pipeline().addLast(new RPCHandler(promise));
channel.writeAndFlush(new RPCProtoMessage(request)).addListener((ChannelFuture future) -> {
if (future.cause() != null) {
future.channel().close();
promise.tryFailure(future.cause());
}
});
ProtoMessage message;
try {
message = promise.get(context.getTimeoutMs(), TimeUnit.MILLISECONDS);
} catch (ExecutionException | TimeoutException e) {
CommonUtils.closeChannel(channel);
throw new IOException(e);
} catch (InterruptedException e) {
CommonUtils.closeChannel(channel);
throw new RuntimeException(e);
} finally {
if (channel.isOpen()) {
channel.pipeline().removeLast();
}
}
if (message.isResponse()) {
CommonUtils.unwrapResponseFrom(message.asResponse(), context.getChannel());
}
return message;
}
3.临时的处理器:针对读写操作注册回调(BlockHandler)
private NettyPacketReader(FileSystemContext context, WorkerNetAddress address,
Protocol.ReadRequest readRequest) throws IOException {
mContext = context;
mAddress = address;
mPosToRead = readRequest.getOffset();
mReadRequest = readRequest; mChannel = mContext.acquireNettyChannel(address);
mChannel.pipeline().addLast(new PacketReadHandler());
mChannel.writeAndFlush(new RPCProtoMessage(new ProtoMessage(mReadRequest)))
.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
} private NettyPacketWriter(FileSystemContext context, final WorkerNetAddress address, long id,
long length, long packetSize, Protocol.RequestType type, OutStreamOptions options,
Channel channel) {
mContext = context;
mAddress = address;
mLength = length;
Protocol.WriteRequest.Builder builder =
Protocol.WriteRequest.newBuilder().setId(id).setTier(options.getWriteTier()).setType(type);
if (type == Protocol.RequestType.UFS_FILE) {
Protocol.CreateUfsFileOptions ufsFileOptions =
Protocol.CreateUfsFileOptions.newBuilder().setUfsPath(options.getUfsPath())
.setOwner(options.getOwner()).setGroup(options.getGroup())
.setMode(options.getMode().toShort()).setMountId(options.getMountId()).build();
builder.setCreateUfsFileOptions(ufsFileOptions);
}
mPartialRequest = builder.buildPartial();
mPacketSize = packetSize;
mChannel = channel;
mChannel.pipeline().addLast(new PacketWriteResponseHandler());
}
netty服务端:
注册处理器列表:
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline(); final long timeoutMs = Configuration.getMs(PropertyKey.NETWORK_NETTY_HEARTBEAT_TIMEOUT_MS); // Decoders & Encoders
pipeline.addLast("frameDecoder", RPCMessage.createFrameDecoder());
pipeline.addLast("RPCMessageDecoder", new RPCMessageDecoder());
pipeline.addLast("RPCMessageEncoder", new RPCMessageEncoder()); // Idle Event Handlers
pipeline.addLast("idleEventHandler", new IdleStateHandler(timeoutMs, 0, 0,
TimeUnit.MILLISECONDS));
pipeline.addLast("idleReadHandler", new IdleReadHandler());
pipeline.addLast("heartbeatHandler", new HeartbeatHandler()); // Block Handlers
pipeline.addLast("blockReadHandler",
new BlockReadHandler(NettyExecutors.BLOCK_READER_EXECUTOR,
mWorkerProcess.getWorker(BlockWorker.class), mFileTransferType));
pipeline.addLast("blockWriteHandler", new BlockWriteHandler(
NettyExecutors.BLOCK_WRITER_EXECUTOR, mWorkerProcess.getWorker(BlockWorker.class),
mWorkerProcess.getUfsManager()));
pipeline.addLast("shortCircuitBlockReadHandler",
new ShortCircuitBlockReadHandler(NettyExecutors.RPC_EXECUTOR,
mWorkerProcess.getWorker(BlockWorker.class)));
pipeline.addLast("shortCircuitBlockWriteHandler",
new ShortCircuitBlockWriteHandler(NettyExecutors.RPC_EXECUTOR,
mWorkerProcess.getWorker(BlockWorker.class)));
pipeline.addLast("asyncCacheHandler", new AsyncCacheHandler(mRequestManager)); // UFS Handlers
pipeline.addLast("ufsFileWriteHandler", new UfsFileWriteHandler(
NettyExecutors.FILE_WRITER_EXECUTOR, mWorkerProcess.getUfsManager())); // Unsupported Message Handler
pipeline.addLast("unsupportedMessageHandler", new UnsupportedMessageHandler());
}
写入或者读取配置
alluxio.client.file.options.CreateFileOptions是FileSystem类createFile的第二个参数,可以选定不同的写入策略
例如:
- MUST_CACHE(只写入Alluxio,必须存储在Alluxio中)
- CACHE_THROUGH(尝试缓存,同步写入到UnderFS)
- THROUGH(无缓存,同步写入到UnderFS)
- ASYNC_THROUGH(异步写入到UnderFS,实现特性)
FileOutStream createFile(AlluxioURI path, CreateFileOptions options)
throws FileAlreadyExistsException, InvalidPathException, IOException, AlluxioException;
而这种写入选项,就是通过在传递netty message时,设置不同的标识,然后在netty中分派到不同的pipeline节点,处理各自的特性的
代码实例:
是否需要写入到ufs,则在UfsFileWriteHandler的acceptMessage方法中进行判断的
alluxio.worker.netty.UfsFileWriteHandler#acceptMessage
protected boolean acceptMessage(Object object) {
if (!super.acceptMessage(object)) {
return false;
}
Protocol.WriteRequest request = ((RPCProtoMessage) object).getMessage().asWriteRequest();
return request.getType() == Protocol.RequestType.UFS_FILE;
}
alluxio源码解析-netty部分(2)的更多相关文章
- Netty 源码解析: Netty 的 ChannelPipeline
ChannelPipeline和Inbound.Outbound 我想很多读者应该或多或少都有 Netty 中 pipeline 的概念.前面我们说了,使用 Netty 的时候,我们通 ...
- alluxio源码解析-rpc调用概述-client和worker之间的block模块的通讯架构(netty版本)(3)
(1.8版本)client和worker之间的block模块的通讯架构 block作为alluxio文件读取或者存储的最小基本单位,都是通过BlockOutStream和BlockInputtream ...
- alluxio源码解析-层次化存储(4)
层次化存储-特性介绍: https://www.alluxio.org/docs/1.6/cn/Tiered-Storage-on-Alluxio.html 引入分层存储后,Alluxio管理的数据块 ...
- alluxio源码解析-rpc调用概述(1)
alluxio中几种角色以及角色之间的rpc调用: 作为分布式架构的文件缓存系统,rpc调用必不可少 client作为客户端 master提供thrift rpc的服务,管理以下信息: block信息 ...
- Netty 4源码解析:请求处理
Netty 4源码解析:请求处理 通过之前<Netty 4源码解析:服务端启动>的分析,我们知道在最前端"扛压力"的是NioEventLoop.run()方法.我们指定 ...
- Netty 4源码解析:服务端启动
Netty 4源码解析:服务端启动 1.基础知识 1.1 Netty 4示例 因为Netty 5还处于测试版,所以选择了目前比较稳定的Netty 4作为学习对象.而且5.0的变化也不像4.0这么大,好 ...
- netty服务端启动--ServerBootstrap源码解析
netty服务端启动--ServerBootstrap源码解析 前面的第一篇文章中,我以spark中的netty客户端的创建为切入点,分析了netty的客户端引导类Bootstrap的参数设置以及启动 ...
- Netty源码解析—客户端启动
Netty源码解析-客户端启动 Bootstrap示例 public final class EchoClient { static final boolean SSL = System.getPro ...
- Netty源码解析---服务端启动
Netty源码解析---服务端启动 一个简单的服务端代码: public class SimpleServer { public static void main(String[] args) { N ...
随机推荐
- Linux权限_用户_和用户组
Linux中用户UID就判断操作系统中用户的身份. Centos7.x: 0:超级管理员 1-999:系统用户(包含Linux中自带服务) 1000以上 普通用户 Centos6.x : Root ...
- django基础知识之模板继承:
模板继承 模板继承可以减少页面内容的重复定义,实现页面内容的重用 典型应用:网站的头部.尾部是一样的,这些内容可以定义在父模板中,子模板不需要重复定义 block标签:在父模板中预留区域,在子模板中填 ...
- Win10自动更新关闭方法
一.为什么很多人会选择禁用Win10自动更新? 1.win10自动更新定义: Win 10的自动更新功能,即 Windows Update.这项功能本意是为一些软件.漏洞等提供更新服务.一般来说,只要 ...
- 2018年东北地区赛S - Problem I. Spell Boost HDU - 6508
题目地址:https://vjudge.net/problem/HDU-6508 思路:给一些卡,分为四种卡.1.白卡(没效果)2.魔法,作用卡(会对作用卡的费用减少,也会被魔法卡作用)3.作用卡(会 ...
- 设计模式:代理模式是什么,Spring AOP还和它有关系?
接着学习设计模式系列,今天讲解的是代理模式. 定义 什么是代理模式? 代理模式,也叫委托模式,其定义是给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用.它包含了三个角色: Subject: ...
- 探究Hybrid-APP技术原理
探究Hybrid-APP技术原理 author: @TiffanysBear 背景 随着Web技术的发展和移动互联网的发展,Hybrid技术已经成为一种前端开发的主流技术方案.那什么是Hybrid A ...
- AWS S3 上传文件
一.获取签名的URL 通过后端给的接口拿到已经签名好的文件上传的URL地址 二.读取文件(注:AWS 接受的二进制,不能使用form-data) // 获取文件二进制 getFileMd5 = (ke ...
- Java 读取PDF中的文本和图片
本文将介绍通过Java程序来读取PDF文档中的文本和图片的方法.分别调用方法extractText()和extractImages()来读取. 使用工具:Free Spire.PDF for Ja ...
- STM32F072从零配置工程-串口USART配置
也是使用HAL库进行配置,通过STMCube生成代码,可以通过这个简单的配置过程看到STMCube生成代码的一种规范: 从main函数入手观察其外设配置结构: 首先是HAL_Init()进行所有外设的 ...
- JS高级程序设计第4章--精简版
前言:纯手打!!!按照自己思路重写!!!这次是二刷了,想暑假做一次完整的笔记,但用本子来写笔记的话太贵了,可能哪天还丢了..所以还是博客好== 第四章:变量.作用域和内存问题 4.1 基本类型和引用类 ...