nacos笔记

nacos:

    startup.sh -m standalone  单独启动

客户端注册服务

    nacos 集成了 dubbo的话会在 DubboServiceRegistrationNonWebApplicationAutoConfiguration 做服务注册
            
    否则在 NacosServiceRegistryAutoConfiguration -> NacosAutoServiceRegistration -> AbstractAutoServiceRegistration 的 onApplicationEvent 的 bind() -> start() -> register()
    
    进入到 NacosServiceRegistry 的 register 方法
    
    
    NacosServiceRegistry


Nacos服务端的处理 

    服务端提供了一个InstanceController类,在这个类中提供了服务注册相关的API,而服务端发起初测时,调用的接口是:[post]: /nacos/v1/ns/instance
    
    serviceName: 代表客户端的项目名称
    namespace: nacos 的namespace
    
    InstanceController -> register() -> InstanceOperatorServiceImpl
    
    最后进入 ServiceManager 的 registerInstance 方法
        
         //创建一个空服务,在Nacos控制台服务列表展示的服务信息,实际上是初始化一个serviceMap,它是一个ConcurrentHashMap集合    
        createEmptyService(namespaceId, serviceName, instance.isEphemeral()); 
        
        //从serviceMap中,根据namespaceId和serviceName得到一个服务对象    
        Service service = getService(namespaceId, serviceName);        
        
           //调用addInstance创建一个服务实例    
        addInstance(namespaceId, serviceName, instance.isEphemeral(), instance);

            把服务实例添加到集合中,然后基于一致性协议进行数据的同步。


消费者的服务查询 
    服务注册成功之后,消费者就可以从nacos server中获取到服务提供者的地址,然后进行服务的调用。
    
    在服务消费中,有一个核心的类 NacosDiscoveryClient 负责和nacos交互,去获得服务提供者的地址信息。
    
    NacosDiscoveryAutoConfiguration -> NacosDiscoveryClientConfiguration ->  NacosDiscoveryClient
    
    NacosDiscoveryClient 中提供了一个 getInstances 方法用来根据服务提供者名称获取服务提供者的url地址的方法.客户端启动获取服务列表 

    HostReactor.getServiceInfo
        updateServiceNow, 立马从Nacos server中去加载服务地址信息
        
        scheduleUpdateIfAbsent 开启定时调度,每10s去查询一次服务地址
            
            HostReactor.scheduleUpdateIfAbsent 在查询服务调用 getServiceInfo 方法的代码中,会开启一个定时任务,这个任务会在默认在1s之后开始执行。而任务的具体实现是一个UpdateTask。
            
        HostReactor.UpdateTask run 方法 执行定时查询服务列表的任务

Raft 选举
    
    RaftCore 里面的 init 方法 
    
    
    //开启定时任务,每500ms执行一次,用来判断是否需要发起leader选举,每500ms发起一次心跳
    masterTask = GlobalExecutor.registerMasterElection(new MasterElection());
    //开启心跳机制
    heartbeatTask = GlobalExecutor.registerHeartbeat(new HeartBeat());

nacos-配置中心

    在spring boot项目启动时,有一个prepareContext的方法,它会回调所有实现了ApplicationContextInitializer的实例,来做一些初始化工作。

    
    NacosPropertySourceLocator
    
        //加载共享配置    loadSharedConfiguration(composite);    
        
        //加载扩展配置    loadExtConfiguration(composite);   
        
        //加载自身配置    loadApplicationConfiguration(composite, dataIdPrefix, nacosConfigProperties, env);

        
        loadNacosDataIfPresent 调用 loadNacosPropertySource 加载存在的配置信息。
            
        
        loadNacosPropertySource -> loadNacosData ->  configService.getConfig  -> NacosConfigService.getConfigInner


        
        NacosConfigService.getConfigInner
            先从本地磁盘中加载配置,因为应用在启动时,会加载远程配置缓存到本地,如果本地文件的内容不为空,直接返回。(在应用启动时ClientWorker会维护两个线程池用来获取配置信息)
            
            如果本地文件的内容为空,则调用worker.getServerConfig加载远程配置
            
            如果出现异常,则调用本地快照文件加载配置


        ClientWorker.getServerConfig
            
            通过agent.httpGet发起http请求,获取远程服务的配置。

        
        ClientWorker 可以看到 ClientWorker 除了将 HttpAgent 维持在自己内部,还创建了两个线程池:
            
            第一个线程池是只拥有一个线程用来执行定时任务的 executor,executor 每隔 10ms 就会执行一次 checkConfigInfo() 方法,从方法名上可以知道是每 10 ms 检查一次配置信息。
                
                最终执行 LongPollingRunnable.run 
                
            第二个线程池是一个普通的线程池,从 ThreadFactory 的名称可以看到这个线程池是做长轮询的。

        
        ClientWorker.LongPollingRunnable    每个长轮训 LongPullingRunnable 任务默认处理3000个监听配置集。如果超过3000, 则需要启动多个 LongPollingRunnable 去执行。
        
            checkUpdateDataIds     通过长轮训的方式,从远程服务器获得变化的数据进行返回
            
                首先从cacheDatas集合中找到isUseLocalConfigInfo为false的缓存
                
                调用 checkUpdateConfigStr -> agent.httpPost 长轮询

            getServerConfig
            
                根据dataId、group、tenant等信息,使用http请求从远程服务器上获得配置信息,读取到数据之后缓存到本地文件中

                
    服务端处理长轮询请求
        
        ConfigController.getListeners 这是客户端的长轮询请求
        
        clientLongPolling 到底做了什么操作。
            
            allSubs.add(this); allSubs是一个队列,队列里面放了 ClientLongPolling 这个对象
        
            这个任务要阻塞29.5s才能执行,因为立马执行没有任何意义,毕竟前面已经执行过一次了如果在29.5s+之内,数据发生变化,需要提前通知。需要有一种监控机制
        

        DataChangeTask.run    
        
            也就是服务端数据发生变更的时间,就会执行一个 DataChangeTask 的线程
            
            它里面有一个循环迭代器,从allSubs里面获得 ClientLongPolling 最后通过 clientSub.sendResponse 把数据返回到客户端。所以,这也就能够理解为何数据变化能够实时触发更新了。
        
        


AsyncContext介绍
    Servlet 3.0的异步处理支持特性,使Servlet 线程不再需要一直阻塞,直到业务处理完毕才能再输出响应,最后才结束该 Servlet 线程。
    
    在接收到请求之后,Servlet 线程可以将耗时的操作委派给另一个线~程来完成,自己在不生成响应的情况下返回至容器。针对业务处理较耗时的情况,这将大大减少服务器资源的占用,并且提高并发处理速度
    
    Servlet 3.0新增了异步处理,可以先释放容器分配给请求的线程与相关资源,减轻系统负担,原先释放了容器所分配线程的请求,其响应将被延后,可以在处理完成(例如长时间运算完成、所需资源已获得)时再对客户端进行响应。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值