1.asyncsocket Դ??
2.Alluxio 客户端源码分析
3.c++网络编程:Boost.asio源码剖析
asyncsocket Դ??
OkHttp是一个广泛应用于Android开发中的网络请求库,其支持HTTP1、HTTP2等多种协议,为日常开发提供强大支持。本文基于OkHttp4.9.0版本代码,从其创建开始,文档在线浏览源码深入探究OkHttp如何发起网络请求。
使用OkHttp的第一步是创建OkHttpClient实例,这实质上是一个配置类,用于管理请求时的各种参数设置,通过Builder模式实现灵活的配置。
Request类作为基础请求构造类,用于描述请求参数,包括域名、请求方式、请求头、请求体等信息。Builder方法提供链式调用,优雅地配置请求细节。
Call类作为请求的入口,通过OkHttpClient的实例方法发起请求。Call是一个接口,内部实现了OkHttpClient配置的Dispatcher来处理请求。
enqueue方法处理异步请求,创建AsyncCall实例,卖炒股源码并调用Dispatcher进行请求处理。execute方法用于同步请求,加入请求队列,创建响应责任链发起请求。
getResponseWithInterceptorChain方法是OkHttp发起请求的核心,构建拦截器列表并按顺序调用,处理请求并返回。
cancel方法用于请求取消,停止后续IO操作和连接断开,进行事件通知。
RealInterceptorChain类追踪请求流程,最终调用proceed方法处理请求。Dispatcher类管理异步请求执行逻辑,控制并发请求数量。
RetryAndFollowUpInterceptor拦截器负责错误重试和重定向,ExchangeFinder类在连接池中寻找可用连接,ConnectInterceptor类负责连接服务器。
CallServerInterceptor类执行IO操作与服务器交互,BridgeInterceptor类处理请求和响应数据,CacheInterceptor类进行缓存管理。
RealConnection类实现实际网络连接,底层使用Socket连接服务器。
CallServerInterceptor类处理请求和响应数据,实现网络IO操作。源码金铲
BridgeInterceptor类作为应用与网络交互的桥梁,处理请求头和Cookie信息。
Response对象最终提供用户访问请求信息和响应结果。
总结,OkHttp的请求流程从创建OkHttpClient开始,通过Request描述请求信息,Call发起请求,由Dispatcher管理异步请求执行逻辑,实现代理和重试等功能。底层使用Socket进行网络连接,OkIO进行IO操作,通过责任链模式有序处理请求。阅读OkHttp源码可以深入了解设计模式、功能抽象等知识,提高编程能力。
Alluxio 客户端源码分析
Alluxio是一个用于云分析和人工智能的开源数据编排技术,作为分布式文件系统,采用与HDFS相似的主从架构。系统中包含一个或多个Master节点存储集群元数据信息,以及Worker节点管理缓存的数据块。本文将深入分析Alluxio客户端的实现。
创建客户端逻辑在类alluxio.client.file.FileSystem中,简单示例代码如下。
客户端初始化包括调用FileSystem.Context.create创建客户端对象的doris源码视频上下文,在此过程中需要初始化客户端以创建与Master和Worker连接的连接池。若启用了配置alluxio.user.metrics.collection.enabled,将启动后台守护线程定时与Master节点进行心跳传输监控指标信息。同时,客户端初始化时还会创建负责重新初始化的后台线程,定期从Master拉取配置文件的哈希值,若Master节点配置发生变化,则重新初始化客户端,期间阻塞所有请求直到重新初始化完成。
创建具有缓存功能的客户端在客户端初始化后,调用FileSystem.Factory.create进行客户端创建。客户端实现分为BaseFileSystem、MetadataCachingBaseFileSystem和LocalCacheFileSystem三种,其中MetadataCachingBaseFileSystem和LocalCacheFileSystem对BaseFileSystem进行封装,提供元数据和数据缓存功能。BaseFileSystem的调用主要分为三大类:纯元数据操作、读取文件操作和写入文件操作。针对元数据操作,直接调用对应GRPC接口(例如listStatus)。接下来,将介绍客户端如何与Master节点进行通信以及读取和写入的流程。
客户端需要先通过MasterInquireClient接口获取主节点地址,当前有三种实现:PollingMasterInquireClient、SingleMasterInquireClient和ZkMasterInquireClient。httpwebrequest 获取源码其中,PollingMasterInquireClient是针对嵌入式日志模式下选择主节点的实现类,SingleMasterInquireClient用于选择单节点Master节点,ZkMasterInquireClient用于Zookeeper模式下的主节点选择。因为Alluxio中只有主节点启动GRPC服务,其他节点连接客户端会断开,PollingMasterInquireClient会依次轮询所有主节点,直到找到可以连接的节点。之后,客户端记录该主节点,如果无法连接主节点,则重新调用PollingMasterInquireClient过程以连接新的主节点。
数据读取流程始于BaseFileSystem.openFile函数,首先通过getStatus向Master节点获取文件元数据,然后检查文件是否为目录或未写入完成等条件,若出现异常则抛出异常。寻找合适的Worker节点根据getStatus获取的文件信息中包含所有块的信息,通过偏移量计算当前所需读取的块编号,并寻找最接近客户端并持有该块的Worker节点,从该节点读取数据。判断最接近客户端的Worker逻辑位于BlockLocationUtils.nearest,考虑使用domain socket进行短路读取时的Worker节点地址一致性。根据配置项alluxio.worker.data.server.domain.socket.address,判断每个Worker使用的domain socket路径是否一致。如果没有使用域名socket信息寻找到最近的Worker节点,则根据配置项alluxio.user.ufs.block.read.location.policy选择一个Worker节点进行读取。若客户端和数据块在同一节点上,则通过短路读取直接从本地文件系统读取数据,否则通过与Worker节点建立GRPC通信读取文件。
如果无法通过短路读取数据,客户端会回退到使用GRPC连接与选中的Worker节点通信。首先判断是否可以通过domain socket连接Worker节点,优先选择使用domain socket方式。创建基于GRPC的块输入流代码位于BlockInStream.createGrpcBlockInStream。通过GRPC进行连接时,每次读取一个chunk大小并缓存chunk,减少RPC调用次数提高性能,chunk大小由配置alluxio.user.network.reader.chunk.size.bytes决定。
读取数据块完成后或出现异常终止,Worker节点会自动释放针对该块的写入锁。读取异常处理策略是记录失败的Worker节点,尝试从其他Worker节点读取,直到达到重试次数上限或没有可用的Worker节点。
若无法通过本地Worker节点读取数据,则客户端尝试发起异步缓存请求。若启用了配置alluxio.user.file.passive.cache.enabled且存在本地Worker节点,则向本地Worker节点发起异步缓存请求,否则向负责读取该块数据的Worker节点发起请求。
数据写入流程首先向Master节点发送CreateFile请求,Master验证请求合法性并返回新文件的基本信息。根据不同的写入类型,进行不同操作。如果是THROUGH或CACHE_THROUGH等需要直接写入底层文件系统的写入类型,则选择一个Worker节点处理写入到UFS的数据。对于MUST_CACHE、CACHE_THROUGH、ASYNC_THROUGH等需要缓存数据到Worker节点上的写入类型,则打开另一个流负责将每个写入的块缓存到不同的Worker上。写入worker缓存块流程类似于读取流程,若写入的Worker与客户端在同一个主机上,则使用短路写直接将块数据写入Worker本地,无需通过网络发送到Worker上。数据完成写入后,客户端向Master节点发送completeFile请求,表示文件已写入完成。
写入失败时,取消当前流以及所有使用过的输出流,删除所有缓存的块和底层存储中的数据,与读取流程不同,写入失败后不进行重试。
零拷贝实现用于优化写入和读取流程中WriteRequest和ReadResponse消息体积大的问题,通过配置alluxio.user.streaming.zerocopy.enabled开启零拷贝特性。Alluxio通过实现了GRPC的MethodDescriptor.Marshaller和Drainable接口来实现GRPC零拷贝特性。MethodDescriptor.Marshaller负责对消息序列化和反序列化的抽象,用于自定义消息序列化和反序列化行为。Drainable扩展java.io.InputStream,提供将所有内容转移到OutputStream的方法,避免数据拷贝,优化内容直接写入OutputStream的过程。
总结,阅读客户端代码有助于了解Alluxio体系结构,明白读取和写入数据时的数据流向。深入理解Alluxio客户端实现对于后续阅读其他Alluxio代码非常有帮助。
c++网络编程:Boost.asio源码剖析
Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一。Boost库由C++标准委员会库工作组成员发起,其中有些内容有望成为下一代C++标准库内容。在C++社区中影响甚大,是不折不扣的“准”标准库。
boost.asio是Boost库中非常著名的I/O组件,是用于网络和低层IO编程的跨平台C++库,为开发者提供了C++环境下稳定的异步模型。其在性能、移植性、扩展性等方面均为人称道,甚至被很多业内人士称为“网络神器”。asio是目前唯一有希望进入C++标准库以弥补标准库在网络方面的缺失的C++网络库,因此对asio的学习在某种意义上可以说是学习C++网络编程的必修课。
本文从源码角度出发,深入浅出地剖析asio的架构和设计理念,将asio的一切秘密呈现在读者眼前。适合已有较完善的C++基础知识、具备一定程度的泛型技术和面向对象技术、并对boost.asio有一定的了解的读者。
asio的核心架构由三大组件构成:io_object、services服务和"Asio核心组件",其中io_object是I/O对象的集合,包含socket、deadline_timer等对象;services服务是逻辑功能的实现者,包含deadline_timer_service、win_iocp_socket_service等服务;"Asio核心组件"即io_service,通过关联类service_registry管理服务,由io_object提供接口。
io_service的真正逻辑实现封装在内部桥接的类io_service_impl中,io_service_impl继承于service_base,在io_service初始化时被创建并由io_service持有其引用。asio中包含多个服务,如strand_service、deadline_timer_service、stream_socket_service等,以及对应的I/O对象如io_service::strand、basic_deadline_timer等。
asio中还包含Protocol和InternetProtocol概念,用于定义通信协议和网络通信协议。此外,还引入了泛型概念如ConstBuffer、ConstBufferSequence、MutableBuffer、MutableBufferSequence、Stream、AsyncReadStream、AsyncWriteStream、SyncReadStream和SyncWriteStream等,使得asio在设计上更加灵活和高效。
泛型与面向对象的完美结合使得asio在设计上既具有面向对象的封装性和可扩展性,又具备泛型编程的灵活性和高效性。通过Service Concept和CSU(Core-Service-User)架构,asio实现了用户友好的接口设计,使得开发者能够以简单而统一的方式使用asio提供的功能,无需自行处理复杂的泛型组件组装工作。
2024-11-19 16:36
2024-11-19 16:33
2024-11-19 16:23
2024-11-19 16:09
2024-11-19 15:20
2024-11-19 14:51
2024-11-19 14:31
2024-11-19 13:57