从启动脚本入手,看源码:
由上面一步走到这儿
正好有一个这样的jar包
在这个jar包里就可以看到基本的启动入口类了
去源码里面找,毫无疑问找对了
启动nacos加上这个参数 单机启动
启动完成后,可以直接访问localhost:8848/nacos 的界面,并且可以启动一个服务注册上去,如下图:
进入源码正题:
点进去看,其实就是拿instace里面的信息,传到下面这个repApi里去了,看到这儿其实不用往下看了,一个http的post请求么
这里跟上图一样,这里特别记一下这个路径
补充一下,为什么我们上面的源码入口直接就 找到了nacosnamingService类里(肯定是springboot的自动装配的原因嘛,依赖了nacos-discover包,就从这个包入手,毫无疑问,是右边第二行代码嘛):
点进去,看这个类
找到这个类的这个方法
再点进去他的这个方法,顺便看下他的调用关系
看到他的类关系里实现了一个ApplicationListener接口,这个得去他的父类里去看
去到父类里主要看这个方法
具体的bind方法
start方法点进去后,看这个注册的方法:
点这个注册的方法,当然是选这个类了,我们入口看的auto就是这个nacosauto
再点,到父类的注册方法
再点:
连着将这个方法点击两下,就到了我们本篇博客最开始的入口方法了:
很重要的经验:这里就是这个方法的先后调用顺序,越往上是最新的调用,下面是最初的调用
猜源码的方式,注册instance的类
找到注册的方法
将request转化为实例后,点击注册实例的方法
下面是对上面这张图的补充
点进去,这里标注的默认传的true,其实就是平时显示的那个临时实例(是否为临时实例,默认是true),简单标注图A
点进去这个方法
对上图做出补充,应该是一个是服务上线,一个是服务下线
点进去,就是添加实例的方法
回到图A 的put方法里点进去(这里有多个类实现,凭经验猜)
在点进去put方法
点击onPut方法进去看
点进去这里的addTask方法看看看
f
对上图的补充,就是将参数封装后,丢到一个内存队列里面去。至此,注册逻辑已经结束了
但是不是说把注册信息放入了某个双层map吗,怎么没有啊,就这么结束了?明天看吧
接着看:上面是放,下面就是拿了
handle方法点进去后,这里肯定就是上面的注册进去后,这里就是拿出来然后去注册
onchange方法点进去后,就是这样的。这里就是将实例拿出来后写到双层map里面去
点击上面的updateIps方法
上面这个方法到最后会把注册表放进这个set里。这个set是双层map的一个内部结构
这是个无限循环的提交方法,目的就是发消息到队列后可以随时拿出来
注册逻辑总结:naocs客户端发起注册时先将实例发送到队列中,然后一个线程拿到这个实例后去进行异步注册。
注册比eureka牛鼻的地方:准实时。一般1s之内就能感知到
nacos的注册表结构是一个双层map,为什么要设计成双层map呢?
这就是一套nacos可以注册多个环境的原因
交易服务组(多个微服务属于一个组别,可以写成一个trad)
当nacos注册时用了一个注册表的副本,全部写完后才会替换现有的注册表。避免写时读,因为写的时候有好几步呢。这样可以保证读写互步影响且能支持高并发。但是副本替换原注册表时,对于消费者来说感知的实时性是有一定延迟的,不过没有关系。
操作完成后,直接替换。这就是操作副本的体现之处。这个在updateIps方法里。上面有提到.
这就是copyonwrite。实现很简单,只要弄个副本替换原来的就行。但是思想需要明白。
提一个问题,如果副本特别大,复制时不时很浪费内存和时间吗?其实不会的。控制注册表写时的粒度就行。比如南京机房的实例和上海机房的实例可以分开来操作。