首页 文章 精选 留言 我的

精选列表

搜索[分区技术],共10000篇文章
优秀的个人博客,低调大师

Nacos 配置中心源码 | 京东物流技术团队

客户端 入口 在引入配置中心 maven 依赖的 jar 文件中找到 spring-cloud-starter-alibaba-nacos-config-2.2.5.RELEASE.jar!/META-INF/spring.factories,在该配置文件找到 NacosConfigBootstrapConfiguration 配置类,该类是 nacos 配置中心的入口类,类中注册了三个 bean。   NacosConfigProperties:属性配置类,对应配置文件中 spring.cloud.nacos.config 前缀的属性。 NacosConfigManager:管理 NacosConfigProperties 和 ConfigService。 NacosPropertySourceLocator:加载配置中心配置信息。 NacosConfigManager 在 NacosConfigManager 构造方法中,调用了 createConfigService 方法,该方法通过工厂类调用 ConfigService 实现类的构造方法创建 ConfigService 实例。   在 ConfigService 的实现类 NacosConfigService 的构造方法中会初始化 this.agent = new MetricsHttpAgent(new ServerHttpAgent(properties));,该 agent 是用来像服务端发送请求的代理。  ServerHttpAgent 类中 NacosRestTemplate 属性是发送远程调用的工具类,会调用 HttpMethod.GET 方法调用服务端 rest 请求。  在回到 NacosConfigService#NacosConfigService 的方法中 this.worker = new ClientWorker(this.agent, this.configFilterChainManager, properties); 该属性是客户端工作线程类,在类的内部有两个线程池: 1. 只有一个线程的线程池 this.executor = Executors.newScheduledThreadPool(1, new ThreadFactory() 用来执行定时任务,每隔 10ms 执行一次 checkConfigInfo(); 方法,按照每 3000 个配置项为一批次捞取待轮询的 cacheData 实例,将其包装成为一个 LongPollingTask 提交进入第二个线程池 executorService 处理。   2.线程数等于处理器个数的线程池,用来执行 ClientWorker.LongPollingRunnable#LongPollingRunnable#run,cacheMap 中缓存着需要刷新的配置,将 cacheMap 中数量以 3000 分一个组,分别创建一个 LongPollingRunnable 用来监听配置更新,在 LongPollingRunnable#run 方法中调用checkLocalConfig(cacheData); 检查本地的配置,容错的处理;调用 checkUpdateDataIds(cacheDatas, inInitializingCacheList); 方法是向 nacos 服务端 发送一个长连接超时事件30s,返回有更新的dataids;调用 getServerConfig(dataId, group, tenant, 3000L); 方法是根据返回有变化的dataids调用服务端配置中心接口获取配置属性,并更新本地快照;调用checkListenerMd5();方式,对有变化的配置添加监听处理;最后继续调用executorService.execute(this); 方法轮询处理。    CacheData#checkListenerMd5   在listener.receiveConfigInfo(contentTmp); 方法中会调用到 AbstractSharedListener#receiveConfigInfo 方法,会发布 RefreshEvent 事件。   对应的事件监听器为:RefreshEventListener, Spring Cloud 实现的,在该监听器里更新配置和刷新容器中标记了 @RefreshScope 的配置,在 onApplicationEvent 方法中监听2个事件,ApplicationReadyEvent(spring boot 事件,表示 application 应该初始化完成)、RefreshEvent。   RefreshEvent:this.handle((RefreshEvent)event);处理该事件,用来刷新容器中标记了 @RefreshScope注解的配置,org.springframework.cloud.context.refresh.ContextRefresher#refresh   refreshEnvironment();中 extract(this.context.getEnvironment().getPropertySources()) 抽取除系统变量外的其他变量;addConfigFilesToEnvironment();把原有的 environment里面的参数放到一个新建的 spring context 容器下重新加载,完事之后关闭新容器,这里就是获取参数的新值;   changes(before,extract(this.context.getEnvironment().getPropertySources())) 获取新的参数值,并和之前得进行比较找出改变得参数值。  this.context.publishEvent(new EnvironmentChangeEvent(this.context, keys)); 发布环境变更事件,并带上改变得参数值。 回到 ContextRefresher#refresh 方法,看下 this.scope.refreshAll(); 刷新标记@RefreshScope注解的 bean。   super.destroy(); 方法,清楚 scope 里面的缓存,下次就会重新从 BeanFactory 获取一个新的实例会使用新的配置。 this.context.publishEvent(new RefreshScopeRefreshedEvent()); 方法发布事件。 服务端 DumpService DumpService 类是一个抽象类负责从存储中查询配置保存到磁盘上,它有两个子类,EmbeddedDumpService嵌入式存储(DERBY)、ExternalDumpService扩展数存储。  ExternalDumpService 实现类的 init 方法上 @PostConstruct 注解,在 spring 构建 bean 的过程中会执行带有 @PostConstruct 的初始化方法。 调用到抽象父类 DumpService#dumpOperate 的方法,调用到 dumpConfigInfo 方法,dumpConfigInfo 方法会判断是全量更新,还是追加更新。  如果 isAllDump 为true 会走全量更新,会进行判断是否有快速更新配置、是否存在心跳检查文件、最后检查时间是否小于 6小时,上述判断都满足就不走全量更新,否则走全量更新。  dumpAllProcessor.process(new DumpAllTask());将数据库中的所有 configInfo 配置信息查询出来,写入服务器端磁盘缓存。  persistService.findConfigMaxId(); 查询数据库中最大的主键,用于分页处理。  persistService.findAllConfigInfoFragment(lastMaxId, PAGE_SIZE); 从数据库中分页查询数据,每次查询1000条。   ConfigCacheService.dump(cf.getDataId(), cf.getGroup(), cf.getTenant(), cf.getContent(), cf.getLastModified(),cf.getType()); 写入磁盘  保存到文件中  updateMd5(groupKey, md5, lastModifiedTs); 缓存配置信息的 MD5 到内存中,并发布 LocalDataChangeEvent 事件。  事件监听器会在 NotifyCenter.registerSubscriber 调用。  获取配置 HttpMethod.GET /nacos/v1/cs/configs 获取服务端配置接口,ConfigController#getConfig。  在getConfig 中调用了 inner.doGetConfig(request, response, dataId, group, tenant, tag, clientIp); 在 doGetConfig 方法中会调用 DiskUtil.targetBetaFile(dataId, group, tenant);方法,从本地磁盘上获取,不是从 mysql 中拉取,如果直接修改 mysql数据不会生效的,需要发布 ConfigDataChangeEvent 事件,触发更新。  监听配置 HttpMethod.POST 请求调用 /nacos/v1/cs/configs/listener 轮询接口调用长连接。  longPollingService.addLongPollingClient(request, response, clientMd5Map, probeRequestSize); 长连接轮询处理。  SwitchService.getSwitchInteger(SwitchService.FIXED_DELAY_TIME, 500); 最多处理29.5s 需要保留0.5s来响应客户端,避免超时。  MD5Util.compareMd5(req, rsp, clientMd5Map); 比较客户端的 md5 与当前服务端的是否一致,不一致返回到 changedGroups。  有不一致数据直接响应 generateResponse(req, rsp, changedGroups);  线程池执行长连接任务 ConfigExecutor.executeLongPolling。  LongPollingService.ClientLongPolling#run 长轮询。  ConfigExecutor.scheduleLongPolling 延迟 29.5s 执行  延迟执行先删除队列中自己的任务 allSubs.remove(ClientLongPolling.this);  allSubs.add(this); 添加到队列  inner.doPollingConfig(request, response, clientMd5Map, probeModify.length());  MD5Util.compareMd5(request, response, clientMd5Map); 和当前配置比较,返回有变更的配置 nacos 管理端变更配置 HttpMethod.POST /nacos/v1/cs/configs  persistService.insertOrUpdate(srcIp, srcUser, configInfo, time, configAdvanceInfo, true); 持节化信息到数据库。     回到 ConfigController#publishConfig 看下 ConfigChangePublisher.notifyConfigChange 方法,触发 ConfigDataChangeEvent 事件。   ConfigDataChangeEvent 事件监听。  ConfigExecutor.executeAsyncNotify(new AsyncTask(nacosAsyncRestTemplate, queue)); 同步其他节点。  还有 LongPollingService 初始化的时候订阅了 LocalDataChangeEvent 事件,也会监听到。  ConfigExecutor.executeLongPolling(new DataChangeTask(evt.groupKey, evt.isBeta, evt.betaIps)); 看下 LongPollingService.DataChangeTask#run,push 模式, 遍历 allSubs 把变化的 key 响应客户端。clientSub.sendResponse(Arrays.asList(groupKey)); 作者:京东物流 张士欣 来源:京东云开发者社区 自猿其说Tech 转载请注明来源

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

为什么前端技术栈如此复杂?

前端生态系统的复杂性是出了名的。在每一层,似乎都存在着不兼容的,相互竞争的标准。 没有通用的导入系统。ES模块、CommonJS、异步模块定义(AMD)和通用模块定义(UMD)都是你可以导入或分享代码的不同方式。打包器试图通过支持多种方法来解决这个问题。但是代码经历了多层的压缩、混淆和转译。TypeScript被编译成JavaScript。网络上的代码会被压缩(以减少网络带宽)或混淆(以防止复制)。源映射可以解决其中一些问题,但这又是另一项需要配置的事情。获取正确的堆栈跟踪可能会很棘手。这需要语言、工具和运行时之间的协调。 极其不同的环境。一个特性和一个错误。前端代码预期在任何地方运行 - 不仅仅是浏览器。在不同环境中可用的上下文和API各不相同,很难知道你有哪些可用的上下文(更不用说知道你正在导入的库假设了什么)。这段代码能在服务器上运行吗?这段代码能在客户端上运行吗?这对开发者来说很困难(我可以使用什么代码)对于库维护者来说也很困难(我应该为哪些环境优化我的代码?)。 过度强调文件结构。太多的前端工具依赖于项目结构来进行行为设定。配置必须在项目的根目录中(导致了一长串的tailwind.config.js、postcss.config.js、eslint.config.js、next.config.js等)。文件结构对于导入代码是必要的恶,但在前端中,它却做了更多的事情。它可能是一个API,用于将特定文件路由为网页,或者作为API,或者作为静态网页,或者作为动态重新生成的网页。这些都很方便,但有时候很难调试,也很难发现代码库的部分内容。 配置地狱。开箱即用的工具有很多。长期以来,我们有create-react-app,这是一个被赞誉的工具包,它集成了许多这样的工具,从一开始就为开发者提供了一个可用的配置。但是,如果你偏离了这条黄金路径,你就会被20多个开发工具和复杂的交互所困扰。几乎每个工具都在与其他工具争斗。ESLint(代码检查工具)和Prettier(代码格式化工具)经常发生冲突。 开发失衡。在代码和部署之间有如此多的步骤,意味着热重载开发往往复杂。这导致了像webpack-dev-server这样的工具的出现,它为你处理了大部分问题。但是要警惕魔法。这些开发服务器中有太多的假设,它们可能会迅速偏离生产行为。 原文:https://matt-rickard.com/why-is-the-frontend-stack-so-complicated 作者:Matt Rickard

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

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部分的功能。

用户登录
用户注册