首页 文章 精选 留言 我的

精选列表

搜索[执行机制],共10017篇文章
优秀的个人博客,低调大师

RocketMQ底层通信机制

分布式系统各个角色间的通信效率很关键,通信效率的高低直接影响系统性能,基于Socket实现一个高效的Tcp通信协议是个很有挑战的事情,本节说明RocketMQ是如何解决这个问题的 1.1.1 Remoting模块RocketMQ的通信相关代码在Remoting模块里,先来看看主要类结构。 RemotingService为最上层接口,定义了三个方法:void start();void shutdown();void registerRPCHook(RPCHook rpcHook);RemotingClient,RemotingServer继承RemotingService接口, 并增加了自己特有的方法。代码清单1-1 RemotingClient主要函数定义void registerProcessor(final int requestCode, final NettyRequestProcessor processor,final ExecutorService executor);RemotingCommand invokeSync(final String addr, final RemotingCommand request, final long timeoutMillis);void invokeAsync(final String addr, final RemotingCommand request, final long timeoutMillis,final InvokeCallback invokeCallback);void invokeOneway(final String addr, final RemotingCommand request, final long timeoutMillis);void updateNameServerAddressList(final List addrs); 然后看看具体的实现类,NettyRemotingClient和NettyRemotingServer分别实现了RemotingClient和RemotingServer, 而且都继承了NettyRemotingAbstract类. 通过上面的封装,RocketMQ各个模块间的通信,可以通过发送统一格式的自定义消息(RemotingCommand)来完成的,各个模块间的通信实现简洁明了。比如NameServer模块中,NameServerController有个remotingServer变量,NameServer在启动时初始化好各个变量,然后启动remotingServer即可,剩下NameServer要做的是专心实现好处理RemotingCommand的逻辑。代码清单1-2 NameServer处理主流程代码@Overridepublic RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException { if (log.isDebugEnabled()) { log.debug("receive request, {} {} {}", request.getCode(), RemotingHelper.parseChannelRemoteAddr(ctx.channel()), request); } switch (request.getCode()) { case RequestCode.PUT_KV_CONFIG: return this.putKVConfig(ctx, request); case RequestCode.GET_KV_CONFIG: return this.getKVConfig(ctx, request); case RequestCode.DELETE_KV_CONFIG: return this.deleteKVConfig(ctx, request); case RequestCode.REGISTER_BROKER: Version brokerVersion = MQVersion.value2Version(request.getVersion()); if (brokerVersion.ordinal() >= MQVersion.Version.V3_0_11.ordinal()) { return this.registerBrokerWithFilterServer(ctx, request); } else { return this.registerBroker(ctx, request); } case RequestCode.GET_HAS_UNIT_SUB_UNUNIT_TOPIC_LIST: return this.getHasUnitSubUnUnitTopicList(ctx, request); case RequestCode.UPDATE_NAMESRV_CONFIG: return this.updateConfig(ctx, request); case RequestCode.GET_NAMESRV_CONFIG: return this.getConfig(ctx, request); default: break; } return null; }在Consumer的源码中,获取消息的底层的通信部分也是发送一个RemotingComand 请求,返回的response也是个RemotingCommand类型。代码清单1-3 Consumer请求消息底层实现代码private PullResult pullMessageSync(// final String addr, // 1 final RemotingCommand request, // 2 final long timeoutMillis// 3 ) throws RemotingException, InterruptedException, MQBrokerException { RemotingCommand response = this.remotingClient.invokeSync(addr, request, timeoutMillis); assert response != null; return this.processPullResponse(response); }从源码中可以看出,RocketMQ中复杂的通信过程,被RemotingCommand统一起来,大部分的逻辑都是通过发送Command,接受并处理Command完成。1.1.2 协议设计和编解码RocketMQ自己定义了一个通信协议,使得模块间传输的二进制消息和有意义的内容之间互相转换。协议格式如图4-2所示。 图1-2 RocketMQ的通信协议 (1)第一部分是大端4个字节整数,值等于第二,三,四部分长度总和 (2)第二部分是大端4个字节整数,值等于第三部分的长度 (3)第三部分是通过json 序列化的数据 (4)第四部分是通过应用自定义二进制序列化的数据 消息的解码过程在RomotingCommand的decode函数里。 代码清单1-4 消息解码函数 public static RemotingCommand decode(final ByteBuffer byteBuffer) { int length = byteBuffer.limit(); int oriHeaderLen = byteBuffer.getInt(); int headerLength = getHeaderLength(oriHeaderLen); byte[] headerData = new byte[headerLength]; byteBuffer.get(headerData); RemotingCommand cmd = headerDecode(headerData, getProtocolType(oriHeaderLen)); int bodyLength = length - 4 - headerLength; byte[] bodyData = null; if (bodyLength > 0) { bodyData = new byte[bodyLength]; byteBuffer.get(bodyData); } cmd.body = bodyData; return cmd; }对应的消息编码过程在RemotingCommand的encode函数中。代码清单1-5 消息编码函数public ByteBuffer encode() { // 1> header length size int length = 4; // 2> header data length byte[] headerData = this.headerEncode(); length += headerData.length; // 3> body data length if (this.body != null) { length += body.length; } ByteBuffer result = ByteBuffer.allocate(4 + length); // length result.putInt(length); // header length result.put(markProtocolType(headerData.length, serializeTypeCurrentRPC)); // header data result.put(headerData); // body data; if (this.body != null) { result.put(this.body); } result.flip(); return result; } 1.1.3 Netty库RocketMQ是基于Netty库来完成RemotingServer和RemotingClient具体的通信实现的,Netty是个事件驱动的网络编程框架,它屏蔽了Java Socket,Nio等复杂细节,用户只需用好Netty,就可以实现一个网络编程专家+并发编程专家水平的Server、Client网络程序。应用Netty有一定的门槛,需要了解它的EventLoopGroup,Channel,Handler模型以及各种具体的配置。RocketMQ利用Netty实现的通信类是NettyRemotingServer和NettyRemotingClient,用户也可以参考这两个类的实现来学习使用Netty。 推荐阅读: 云栖社区官方出品 RocketMQ实战与原理解析作者:杨开元定价:59.00元•RocketMQ由阿里开源,Apache开源项目,经受多年流量峰值考验,在多个性能指标上远超同类产品•作者是阿里资深数据专家,有多年RocketMQ使用经验,深入研究RocketMQ源代码,写作前与RocketMQ官方团队有深入沟通•云栖社区官方出品,得到RocketMQ官方研发团队以及业界的多位专家的肯定和推荐 阅读原文:http://product.dangdang.com/25290633.html

优秀的个人博客,低调大师

ElasticSearch的工作机制

ElasticSearch,和Solr一样,是底层基于Apache Lucene,且具备高可靠性的企业级搜索引擎。 ElasticSearch中的一些概念其实和关系型数据库都有对应关系,比如数据库在ES中被称为索引,表在ES中被称作Type。 具体对应关系见下表。 ElasticSearch中的Replica是副本的意思,创建副本的好处有两个,1,可以分流部分查询请求,2,如果集群中的某个分片丢失了,就可以使用这个副本将数据全部找回来,因为这个原因,副本分片和源分片不会放在同一节点上。 ES中每一个索引都可以被分成多个分片,但不一定每个分片都有副本,但是一旦创建了副本,就会有主分片的说法(作为复制源的分片),分片和副本的数量可以在索引创建的时候指定。下图是副本和分片的示意图,分片和它的副本不会在同一个节点上。 在索引创建之后,你可以在任何时候动态地改变副本的数量,但是你事后不能改变分片的数量。 默认情况下,Elasticsearch中的每个索引被分片5个主分片和1套副本,这意味着,如果你的集群中至少有两个节点,你的索引将会有5个主分片和另外5个副本,这样的话每个索引总共就有10个分片。 当ES的一个节点启动后,它会通过广播方式找到集群中的其他节点,并且建立连接。 在集群中,其中的某个节点会被选取作为主节点,这个主节点负责管理集群状态。这个主节点对于用户来说是透明的,用户不需要知道哪个节点是主节点。任何操作都可以发送到任何节点。必要的时候,任何节点可以并行的发送子查询到其他节点,并且将得到的响应合并后发送给用户,这些操作都不需要访问主节点。 主节点读取集群信息,在读取过程中,它会检测分片的情况,哪些分片是主分片,并且是可用的,在这一步之后,所有的分片已经准备好了,而副本还没有。下一步的操作就是找到那些已经被复制过的分片,将他们作为副本。如果一切顺利,那么ES启动成功了,所有的分片和副本都已经准备好了。 在ES工作的时候,主节点会监控所有的节点是否正常,默认配置为:节点每隔1s主节点会发送1次心跳,超时时间为30s,测试次数为3次,超过3次,则认为该节点同主节点已经脱离了。如果某一个节点出现问题,ES认为这个节点损坏,该节点会从集群中删除,并且ES会重新平衡整个集群。 ES通过Query DSL (基于json的查询语言)来查询数据,在ES内部,每次查询分成2个步骤,分散和聚合,分散是指查询所有相关的分片,聚合是指把所有分片上的查询结果合并,排序,处理然后在返回给客户端。 ElasticSearch 有4中方式来构建数据库,最简单的方法是使用index API,将一个Document发送到特定的index,一般通过curl tools实现。第二第三种方法是通过bulk API和UDP bulk API。两者的区别仅在于连接方式。第四种方式是通过一个插件-river。river运行在ElasticSearch上,并且可以从外部数据库导入数据到ES中。需要注意的是,数据构建仅在分片上进行,而不能在副本上进行。 本文转自cnn23711151CTO博客,原文链接:http://blog.51cto.com/cnn237111/1582354,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册