RocketMq源码学习(一) nameService
public class NamesrvStartup { public static Properties properties = null; public static CommandLine commandLine = null; public static void main(String[] args) { main0(args); } public static NamesrvController main0(String[] args) { System.setProperty(RemotingCommand.REMOTING_VERSION_KEY, Integer.toString(MQVersion.CURRENT_VERSION)); try { //PackageConflictDetect.detectFastjson(); Options options = ServerUtil.buildCommandlineOptions(new Options());------------args是用java -jar 后面输入的字符串,按照键值对输入的,这一步是解析命令行的参数,c是指定config的配置文件,p看样子是退出? commandLine = ServerUtil.parseCmdLine("mqnamesrv", args, buildCommandlineOptions(options), new PosixParser()); if (null == commandLine) { System.exit(-1); return null; } final NamesrvConfig namesrvConfig = new NamesrvConfig(); final NettyServerConfig nettyServerConfig = new NettyServerConfig(); nettyServerConfig.setListenPort(9876); if (commandLine.hasOption('c')) { String file = commandLine.getOptionValue('c'); if (file != null) { InputStream in = new BufferedInputStream(new FileInputStream(file)); properties = new Properties(); properties.load(in); MixAll.properties2Object(properties, namesrvConfig); MixAll.properties2Object(properties, nettyServerConfig); namesrvConfig.setConfigStorePath(file); System.out.printf("load config properties file OK, " + file + "%n"); in.close(); } } if (commandLine.hasOption('p')) { MixAll.printObjectProperties(null, namesrvConfig); MixAll.printObjectProperties(null, nettyServerConfig); System.exit(0); } MixAll.properties2Object(ServerUtil.commandLine2Properties(commandLine), namesrvConfig); if (null == namesrvConfig.getRocketmqHome()) { System.out.printf("Please set the %s variable in your environment to match the location of the RocketMQ installation%n", MixAll.ROCKETMQ_HOME_ENV); System.exit(-2); } LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); JoranConfigurator configurator = new JoranConfigurator(); configurator.setContext(lc); lc.reset(); configurator.doConfigure(namesrvConfig.getRocketmqHome() + "/conf/logback_namesrv.xml"); final Logger log = LoggerFactory.getLogger(LoggerName.NAMESRV_LOGGER_NAME); MixAll.printObjectProperties(log, namesrvConfig); MixAll.printObjectProperties(log, nettyServerConfig); ----------------这个controller是关键类,传入两个配置文件进去 final NamesrvController controller = new NamesrvController(namesrvConfig, nettyServerConfig); // remember all configs to prevent discard controller.getConfiguration().registerConfig(properties); --------------看下面的start方法,实际是调用controller中的一个叫remotingServer的参数的start方法,而remotingServer的赋值就是在这个initialize方法中,new一个NettyRemotingServer出来,是调用netty的入口(见下文) boolean initResult = controller.initialize(); if (!initResult) { controller.shutdown(); System.exit(-3); } Runtime.getRuntime().addShutdownHook(new ShutdownHookThread(log, new Callable<Void>() { @Override public Void call() throws Exception { controller.shutdown(); return null; } })); controller.start(); String tip = "The Name Server boot success. serializeType=" + RemotingCommand.getSerializeTypeConfigInThisServer(); log.info(tip); System.out.printf(tip + "%n"); return controller; } catch (Throwable e) { e.printStackTrace(); System.exit(-1); } return null; } public static Options buildCommandlineOptions(final Options options) { Option opt = new Option("c", "configFile", true, "Name server config properties file"); opt.setRequired(false); options.addOption(opt); opt = new Option("p", "printConfigItem", false, "Print all config item"); opt.setRequired(false); options.addOption(opt); return options; } }
sh ${ROCKETMQ_HOME}/bin/runserver.sh com.alibaba.rocketmq.namesrv.NamesrvStartup $@--------上面这行代码是bin目录下的mqnamesrv文件中的命令,执行NamesrvStartup 的Main方法,启动nameServer,既然是用netty作为io框架来做服务端,必然有netty两个线程池的eventloop
@Override------------NettyRemotingServer的start方法,eventLoopGroupBoss是父线程池,管理端口监控连接的,eventLoopGroupSelector 是子线程池,select channel的读写,处理业务逻辑的 public void start() { this.defaultEventExecutorGroup = new DefaultEventExecutorGroup( nettyServerConfig.getServerWorkerThreads(), new ThreadFactory() { private AtomicInteger threadIndex = new AtomicInteger(0); @Override public Thread newThread(Runnable r) { return new Thread(r, "NettyServerCodecThread_" + this.threadIndex.incrementAndGet()); } }); ServerBootstrap childHandler = this.serverBootstrap.group(this.eventLoopGroupBoss, this.eventLoopGroupSelector) .channel(useEpoll() ? EpollServerSocketChannel.class : NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 1024) .option(ChannelOption.SO_REUSEADDR, true) .option(ChannelOption.SO_KEEPALIVE, false) .childOption(ChannelOption.TCP_NODELAY, true) .childOption(ChannelOption.SO_SNDBUF, nettyServerConfig.getServerSocketSndBufSize()) .childOption(ChannelOption.SO_RCVBUF, nettyServerConfig.getServerSocketRcvBufSize()) .localAddress(new InetSocketAddress(this.nettyServerConfig.getListenPort()))-----------根据之前分析netty可以知道,initchannel方法中添加的handler,每一个channel在accept生成的时候,都会把childHandler给添加到自己的pipeline当中去,当然initChannel方法中的handler也会添加进去,这几个handler一定有处理服务注册和服务发现相关逻辑的。 .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline() .addLast(defaultEventExecutorGroup, HANDSHAKE_HANDLER_NAME, new HandshakeHandler(TlsSystemConfig.tlsMode)) .addLast(defaultEventExecutorGroup,//这里用的netty的第三个线程池,把channel的读写和在pipeline中的数据处理分开-----------------Encoder和Decoder的encode/decode方法之所以能使用,是被继承的适配器中的channelread/write调用了 new NettyEncoder(), new NettyDecoder(),-----------------------检测心跳,长时间没有数据的连接关闭掉 new IdleStateHandler(0, 0, nettyServerConfig.getServerChannelMaxIdleTimeSeconds()),-----------------------------重写了register,active等方法 new NettyConnectManageHandler(),-----------------------------核心的数据处理类,明天再看 new NettyServerHandler() ); } }); if (nettyServerConfig.isServerPooledByteBufAllocatorEnable()) { childHandler.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT); } try { ChannelFuture sync = this.serverBootstrap.bind().sync(); InetSocketAddress addr = (InetSocketAddress) sync.channel().localAddress(); this.port = addr.getPort(); } catch (InterruptedException e1) { throw new RuntimeException("this.serverBootstrap.bind().sync() InterruptedException", e1); } if (this.channelEventListener != null) { this.nettyEventExecutor.start(); } this.timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { try { NettyRemotingServer.this.scanResponseTable(); } catch (Throwable e) { log.error("scanResponseTable exception", e); } } }, 1000 * 3, 1000); }
RocketMq源码学习(一) nameService的更多相关文章
- RocketMQ 源码学习笔记————Producer 是怎么将消息发送至 Broker 的?
目录 RocketMQ 源码学习笔记----Producer 是怎么将消息发送至 Broker 的? 前言 项目结构 rocketmq-client 模块 DefaultMQProducerTest ...
- RocketMQ 源码学习笔记 Producer 是怎么将消息发送至 Broker 的?
目录 RocketMQ 源码学习笔记 Producer 是怎么将消息发送至 Broker 的? 前言 项目结构 rocketmq-client 模块 DefaultMQProducerTest Roc ...
- (转)RocketMQ源码学习--消息存储篇
http://www.tuicool.com/articles/umQfMzA 1.序言 今天来和大家探讨一下RocketMQ在消息存储方面所作出的努力,在介绍RocketMQ的存储模型之前,可以先探 ...
- 【RocketMQ源码学习】- 1. 入门
为什么读RocketMQ 消息队列在互联网应用中使用较为广泛,学习她可以让我门更加了解使用技术的工作原理 透过学习她的源码,拓宽认知 RocketMQ经历了阿里双十一 有哪些名词 Producer 消 ...
- RocketMQ源码学习--消息存储篇
转载. https://blog.csdn.net/mr253727942/article/details/55805876 1.序言 今天来和大家探讨一下RocketMQ在消息存储方面所作出的努力, ...
- 【RocketMQ源码学习】- 4. Client 事务消息源码解析
介绍 > 基于4.5.2版本的源码 1. RocketMQ是从4.3.0版本开始支持事务消息的. 2. RocketMQ的消息队列能够保证生产端,执行数据和发送MQ消息事务一致性,而消费端的事务 ...
- 【RocketMQ源码学习】- 3. Client 发送同步消息
本文较长,代码后面给了方法简图,希望给你帮助 发送的方式 同步发送 异步发送 消息的类型 普通消息 顺序消息 事务消息 发送同步消息的时序图 为了防止读者朋友嫌烦,可以看下时序图,后面我也会给出方法的 ...
- 【RocketMQ源码学习】- 5. 消息存储机制
前言 面试官:你了解RocketMQ是如何存储消息的吗?我:额,,,你等下,我看下这篇文字, (逃 由于这部分内容优点多,所以请哥哥姐姐们自备茶水,欢迎留言! RocketMQ存储设计是高可用和高性能 ...
- RocketMQ 源码分析 —— Message 发送与接收
1.概述 Producer 发送消息.主要是同步发送消息源码,涉及到 异步/Oneway发送消息,事务消息会跳过. Broker 接收消息.(存储消息在<RocketMQ 源码分析 —— Mes ...
随机推荐
- android -------- 颜色的半透明效果配置
最近有朋友问我 Android 背景颜色的半透明效果配置,我网上看资料,总结了一下, 开发中也是常常遇到的,所以来写篇博客 常用的颜色值格式有: RGB ARGB RRGGBB AA ...
- [Fiddler] ReadResponse() failed: The server did not return a complete response for this request. Server returned 0 bytes.
待解决 [Fiddler] ReadResponse() failed: The server did not return a complete response for this request. ...
- React文档(二)Hello World
开始学习React最简单的实践就是去试一试CodePen上面的Hello World程序.你不需要安装任何东西,只要新开一个标签页打开例子依照原例操作即可.如果你更喜欢在本地开发,那么来看看安装的介绍 ...
- ie8不支持currentTarget的解决办法
一般绑定事件时,我们都会在事件回调方法里用event.currentTarget获取当前对象,但到ie8里就获取不到了. 解决方法如下: var eve = event || window.event ...
- hadoop中发送文件的脚本
多台主机执行相同的命令 [xcall] [/usr/local/bin] sudo nano xcall ----------------------------------------------- ...
- Wannafly挑战赛27-A/B
链接:https://www.nowcoder.com/acm/contest/215/A来源:牛客网 题目描述 “White shores, and beyond. A far green coun ...
- oracle数据库静态监听配置示例
[oracle@Oracle11g admin]$ cat listener.ora SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (GLOB ...
- springmvc访问项目默认先访问后台再返回首页
1.spring过滤的url-pattern设置成了/,所以这里随便给个新的后缀 <welcome-file-list> <welcome-file>index.zl</ ...
- 【Linux】bash shell学习
Bash Shell Linux系统的合法shell都写入/etc/shells这个文件,默认使用的shell版本称为“Bourne Again Shell(简称bash)” 用户登录时系统会分配一个 ...
- ubuntu下唤醒或休眠远程计算机
ubuntu让我明白,没有什么完美的东西,要想完美必须付出代价.要么花时间折腾,要么花时间赚钱买系统. 人生也是一样,所以不要期待什么完美.哪有那么好的人,在合适的时间合适的地点让你遇见,还对你有感觉 ...