netty简介

Netty是 一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。
 

netty作为alluxio中重要的通讯组件

在常见的客户端上传,下载中,都会有netty的参与

关于这个图,可以看上篇文章的介绍:

https://www.cnblogs.com/victor2302/p/10490253.html

 
 
netty作为alluxio交互重要的组件,扮演者重要的角色:
  • 解耦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服务端:

注册处理器列表:

alluxio.worker.netty.PipelineHandler
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)的更多相关文章

  1. Netty 源码解析: Netty 的 ChannelPipeline

    ChannelPipeline和Inbound.Outbound         我想很多读者应该或多或少都有 Netty 中 pipeline 的概念.前面我们说了,使用 Netty 的时候,我们通 ...

  2. alluxio源码解析-rpc调用概述-client和worker之间的block模块的通讯架构(netty版本)(3)

    (1.8版本)client和worker之间的block模块的通讯架构 block作为alluxio文件读取或者存储的最小基本单位,都是通过BlockOutStream和BlockInputtream ...

  3. alluxio源码解析-层次化存储(4)

    层次化存储-特性介绍: https://www.alluxio.org/docs/1.6/cn/Tiered-Storage-on-Alluxio.html 引入分层存储后,Alluxio管理的数据块 ...

  4. alluxio源码解析-rpc调用概述(1)

    alluxio中几种角色以及角色之间的rpc调用: 作为分布式架构的文件缓存系统,rpc调用必不可少 client作为客户端 master提供thrift rpc的服务,管理以下信息: block信息 ...

  5. Netty 4源码解析:请求处理

    Netty 4源码解析:请求处理 通过之前<Netty 4源码解析:服务端启动>的分析,我们知道在最前端"扛压力"的是NioEventLoop.run()方法.我们指定 ...

  6. Netty 4源码解析:服务端启动

    Netty 4源码解析:服务端启动 1.基础知识 1.1 Netty 4示例 因为Netty 5还处于测试版,所以选择了目前比较稳定的Netty 4作为学习对象.而且5.0的变化也不像4.0这么大,好 ...

  7. netty服务端启动--ServerBootstrap源码解析

    netty服务端启动--ServerBootstrap源码解析 前面的第一篇文章中,我以spark中的netty客户端的创建为切入点,分析了netty的客户端引导类Bootstrap的参数设置以及启动 ...

  8. Netty源码解析—客户端启动

    Netty源码解析-客户端启动 Bootstrap示例 public final class EchoClient { static final boolean SSL = System.getPro ...

  9. Netty源码解析---服务端启动

    Netty源码解析---服务端启动 一个简单的服务端代码: public class SimpleServer { public static void main(String[] args) { N ...

随机推荐

  1. c++ 队列的基本应用

    c++ 队列的基本应用 题目描述 现在去营业厅办理业务,都要先取号,再等待叫号.叫号系统有两种模式: 1.取号,取号时要输入自己的11位电话号码,号码按取号的顺序存在系统中: 2.叫号,叫号时会显示当 ...

  2. 使用@Transactional注意的问题

    @Transactional 基本原理概述 在应用系统调用声明@Transactional 的目标方法时,Spring Framework 默认使用 AOP 代理,在代码运行时生成一个代理对象,根据@ ...

  3. js random获取随机数,获取任意范围内随机整数

     壹 ❀ 引 想着好久没做笔试题了,去GitHub找了面试相关的项目,结果被第一道题难住了.....说难其实也不难,而是我忘记了取范围随机整数怎么写了,不可否认如果当时是我在笔试,肯定也凉了,那么就由 ...

  4. NioEventLoopGroup初始化

    本文是我对Netty的NioEventLoopGroup及NioEventLoop初始化工作的源码阅读笔记, 如下图,是Netty的Reactor线程模型图,本文描述NioEventLoopGroup ...

  5. 小心使用strcpy函数时越界

    strcpy()函数应该是我们用的比较常用的一个函数,基本功能是将一个字符串拷贝到我指定的内存空间.但是要复制的字符串长度超过这段内存空间的话,结果可能是未知的. 比如以下的程序: #include ...

  6. 小程序实现图片上传,预览以及图片base64位处理

    最近一段时间在做小程序项目,第一期功也完工了.需要好好总结一下经验,把项目中遇到的问题好好总结一下,遇到的问题,踩过的坑.今天写一个小程序实现图片上传,预览,以及删除,图片base64位处理.下面就是 ...

  7. React的Context的使用方法简介

    context 定义: Context提供了一种方式,能够让数据在组件树中传递,而不必一级一级手动传递. API : createContext(defaultValue?). 使用方法: 首先要引入 ...

  8. 个人永久性免费-Excel催化剂功能第39波-DotNet版的正则处理函数

    在很久之前已经开发过的一些自定义函数,未能有详细的讲解,接下来几波中着重对之前开发过的自定义函数进行详细讲解及示例说明,希望能够帮助到普通用户们能顺利使用,此篇介绍为正则表达式函数. 文章出处说明 原 ...

  9. 题解 P3811 【【模板】乘法逆元】

    P3811 [模板]乘法逆元 一个刚学数论的萌新,总结了一下这题的大部分做法 //一.费马小定理+快速幂 O(nlogn) 64分 #include<cstdio> using names ...

  10. C#各版本新增加功能

    本系列文章主要整理并介绍 C# 各版本的新增功能. C# 8.0 C#8.0 于 2019年4月 随 .NET Framework 4.8 与 Visual Studio 2019 一同发布,但是当前 ...