使用Copyonwrite改造本地缓存
背景
周四下午正在吃的码分下午茶,偷闲刷了一会手机(光明正大的),突然就有客服中心的**姐找上门来说xxx操作又出现失败了,但是多点几次又没问题了(之前也出现过,可是代码中没有任何异常处理和日志的输出很难排查,没办法老代码,前任写的我也没办法,只能加上等复现的时候再看看),看着**姐焦急的表情,下午茶瞬间就不香了,找bug去!
产生原因定位在rancher上输入账号找到对应的服务,根据关键字找到相关日志映入眼帘的是java.lang.NullPointException跟随报错的行数找到了相关代码块:
if(StringUtils.isNotEmpty(feeSetting.getFileId())){ returnschoolService.deal(sysConfigService.getString("url"));}其中报错的是
schoolService.deal(sysConfigService.getString("url"));定位问题,应该是调用StringgetString(Stringkey);空指针导致的.
分析相关代码:
publicStringgetString(Stringkey){ if(configs==null){ initConfig();}returnconfigs.get(key);}其中initConfig()的实现:
privatevoidinitConfig(){ synchronized(lock){ if((configs==null)||configs.isEmpty()){ configs=newHashMap<String,String>();//从db中加载到configsloadSysConfig();}}}其中configs是个成员变量
privatestaticMap<String,String>configs=null;复制代码查了一下数据库,有对应的数据存在,不是数据的问题
getString(Stringkey)接口内部没报错,说明这个程序没报错
抓了抓头(有点意思),只有Map中没有相应的数据才有可能报空指针,查找了相关方法,找到了如下代码:
publicvoidreload(){ if((configs!=null)&&!configs.isEmpty()){ configs.clear();this.initConfig();}}只有一处调用该方法
@ComponentpublicclassSysConfgMQListenerimplementsMessageListenerConcurrently{ protectedfinalLoggerlog=LoggerFactory.getLogger(SysConfgMQListener.class);@AutowiredprivateISysConfigServicesysConfigService;@OverridepublicConsumeConcurrentlyStatusconsumeMessage(List<MessageExt>msgs,ConsumeConcurrentlyContextcontext){ log.info("SysConfgMQListenerretrieving...");for(MessageExtmsg:msgs){ log.info("messageExt,body:{ }",newString(msg.getBody()));this.sysConfigService.reload();}returnConsumeConcurrentlyStatus.CONSUME_SUCCESS;}}这是RocketMq的消费者这里调用了,而且还是广播模式,所有节点都能消费,这个Mq的生产者是在后台触发刷新时候产生的.
真相只有一个首先触发Mq的消费,导致Map刷新,重新加载调用reload()
当执行configs.clear();之后Map就是一个空对象,没有任何数据
如果这个时候是有多个线程访问getString(Stringkey)获取到的值就是null
改造第一个想到的是用Redis来替换,但是很快就自我否定了,这个接口在没有触发刷新机制的前提下运行了几年是好好的,而且基础配置放Redis的话过期时间的设置不好判断,并且还要多个IO的传递,性能没有本地的Map好.
第二个想到的方案就是在getString(Stringkey)方法中加锁,这只能当做下下策
正在一筹莫展的时候,突然灵光一闪,这不是跟注册中心很像吗?各个客户端去拉取数据,而nacos为了高性能就是用了Copyonwrite的思想来实现的,越想越行,干!
代码改造如下:
publicvoidreload(){ if((configs!=null)&&!configs.isEmpty()){ //先清除再加载会出现,在两个操作之间请求的接口获取都为空//configs.clear();//this.initConfig();this.reloadForConfigs();}}其中this.reloadForConfigs();
privatevoidreloadForConfigs(){ Map<String,String>newConfigs=newHashMap<>();try{ List<Config>datas=configDao.listConfigs();if(datas!=null){ for(Configcf:datas){ newConfigs.put(cf.getKey(),cf.getValue());}}}catch(Exceptione){ LogUtil.exception(log,e);}if(CollectionUtil.isNotEmpty(newConfigs)){ //替换旧的this.configs=newConfigs;}}这改造完上线之后,跟踪了一段时间日志中也没发现空指针(**姐也不来找我了-_-,不开森),有那么一点点的成就感.
总结开发的时候要考虑多线程和并发场景
遇到问题别慌,认真分析
好的方案不是一蹴而就的
多读好的代码如框架源码,不断的积累,现在用不上,某一时刻就用上了
作者:董懂套实战教程KubernetesK8s CKA认证实战(完整版)BAT大厂基于K8s构建企业容器云平台
套实战教程KubernetesK8s CKA认证实战(完整版)BAT大厂基于K8s构建企业容器云平台
内容包括:K8s+Docker+DevOps+Jenkins+CICD+Git+Istio+Service Mesh云原生实战,云计算,码分微服务,码分容器架构师,码分全栈架构师,码分来图定制源码集群实战,码分部署落地,码分服务治理,码分服务网格,码分原理剖析,码分实战应用,码分云原生架构,码分CKA认证实战班,码分平台设计与开发教程。码分
网盘下载: soft.com/javajg/.html
总目录:涵盖套云原生实战训练营K8s,挑战年薪万K8s+Docker+DevOps+Jenkins+CICD+Git+Istio+Service Mesh云计算,微服务,容器架构师,全栈架构师,集群实战,部署落地,服务治理,线程池源码图服务网格,原理剖析,实战应用,云原生架构,CKA认证实战班,平台设计与开发视频教程。
第套:云原生高薪课,从零到一构建开源的企业级PaaS平台视频教程
第套:搭建企业私有云平台,实现云上亿级流Kubernetes+DevOps+Jenkins+Istio实战课程
第套:云原生实战Docker+K8s+Kubeshere+DevOps架构师必修课程
第套:云原生微服务架构实战精讲,微服务架构迁移和落地视频教程
第套:云原生微信小程序开发实战,云开发成为标配
第套:云原生+边缘计算项目实战,KubeEdge打造边缘管理平台,云边端一体化设计
第套:真正的云原生架构与云IDC实操业务,腾讯架构师工程师TCP认证课程,含DevOps
第套:世界强Kubernetes实战课程,全栈架构师基于K8s的实战教学
第套:K8S微服务与容器云架构师课程,Linux云计算微服务架构师讲解实际生产内容
第套:BAT大厂基于K8s构建企业容器云平台,CKA认证实战班
第套:Kubernetes原理剖析与实战应用,进阶高级架构师必须选项
第套:K8S集群实战,组件部署和使用,持久化存储与代码自动发布教程
第套:Docker与Kubernetes最佳实践,架构师必备技能
第套:全面Docker系统性入门,大牛有形指标源码从基础到高阶实战视频教程
第套:DevOps平台设计和开发视频教程
第套:大厂进阶篇Docker与微服务实战,技术点全面覆盖
第套:DevOps落地笔记,优化研发流程,提高效率和质量
第套:Service Mesh实战,微服务架构实践和落地
第套:Service Mesh服务实战课程,微服务架构全方位解读
第套:Istio服务网格服务治理,微服务架构与设计全面解析
第套:大厂Istio基础与实践,一线实战分享视频教程
第套:KubernetesCKS认证实战班,架构+网络+存储+安全+监控+日志
第套:Kubernetes网络训练营,运维和开发进阶体系课
第套:Kubernetes实战与源码剖析,自动化运维管理集群
第套:阿里云平台构建云原生应用架构,全流程开发
第套:云原生架构师课程,顶级架构设计思维模型,架构设计哲学
第套:Jenkins工程实践,DevOps交付流水线落地
第套:Jenkins企业级持续集成持续部署,DI视频教程
第套:一站式搞定企业级云原生,专业技能+核心原理+方案设计+系统分析
第套:个人博客开发,全栈+实战,HOOKS+Redux+Webpack+Immer
第套:Serverless架构课程,概念篇+开发篇+进阶篇+场景案例
第套:Serverless进阶实战,成为专业工程师,云原生技术红利
第套:Kubernetes高可用集群安装,网站刷流量源码日常运维视频教程
第套:Kubernetes最佳实践课程,基于世界强的高薪实战
第套:Golang企业级运维,DevOps运维开发实战
第套:新版容器编排最佳实践,Kubernetes-Rancher2.x视频教程
第套:电商项目K8S部署与性能优化,基于K8S集群电商微服务项目
第套:Docker入门到进阶,全面掌握从基础到高级
第套:Golang企业级运维,高级运维必修课程
javaå¹è®è¦å¦ä¹ åªäºå 容ï¼
ç®åJavaå¹è®å 容å æ¬ï¼1ãHTML+CSS3+æ°æ®åº
2ãJava SEï¼Javaé¢å对象ææ³ï¼è®¾è®¡æ¨¡å¼ãé¢å对象ååãJavaé«é¶APIã线ç¨ãç½ç»ç¼ç¨ãåå°ãNIOï¼
3ãJava webï¼Java webåºç¡ãJSãDOMæä½ãJSP/Servletã第ä¸æ¹å·¥å ·å ãTomcat...ï¼
4ãæ¡æ¶ï¼ç½ç»åçãHTTPåè®®ãLinuxæä½ç³»ç»ãäºæå¡æ建ãSSMæ¡æ¶åºç¨ãOracleåºç¨ãSpring JPAãHibernate...ï¼
5ãé«å¯ç¨ãé«å¹¶åãé«æ©å±ï¼SpringBootãç¼åãåå¸å¼ãæ件ãå ¨æç´¢å¼ãæå¡ä¸é´ä»¶ãæ¶æ¯ä¸é´ä»¶ãäºæå¡å¨ãäºåå¨ãäºæ°æ®åºãååæå¡...ï¼
6ãå¾®æå¡ã大æ°æ®
以ä¸æ¯æ们年æ´æ°ç课ç¨ï¼æ¨å¯ä»¥äºè§£ä¸ä¸ï¼
å¦æ³å¦ä¹ ï¼å¯ä»¥å¨æ们线ä¸å¦ä¹ å¹³å°ï¼ç¾æç¨åºåè¿è¡äºè§£ï¼
Rancher产品说明和Demo
Rancher是一个为使用容器的公司打造的容器管理平台,它简化了使用Kubernetes的流程,使开发者能够“Run Kubernetes Everywhere”,满足IT需求规范,并赋能DevOps团队。随着Kubernetes在市场上的兴起,Rancher 2.x已经完全转向了Kubernetes。Rancher支持创建托管服务提供商的集群、自动创建节点并安装Kubernetes集群,或者导入已存在的Kubernetes集群。通过支持集群的身份验证和基于角色的访问控制(RBAC),Rancher使系统管理员能够从一个位置控制全部集群的访问。Rancher可以对集群及其资源进行详细的监控和在需要时发送告警,将容器日志发送给外部日志系统,并通过应用商店与Helm集成。如果您的精准主图源码外部CI/CD流水线系统已经存在,可以将其与Rancher对接,若没有,Rancher也提供了简单易用的流水线来帮助您自动部署和升级工作负载。Rancher还提供了多集群应用、全局DNS、服务网格、安全扫描、集群模板和基于OPA的策略管理等功能,使其成为一个全栈式的Kubernetes容器管理平台。
Rancher的安装过程可参考文档“Rancher环境搭建.md”。在实际应用中,Rancher在IT管理团队和DevOps开发团队之间起到了关键作用。DevOps团队可以将他们的应用部署在他们选择的云上,无论是公有云还是私有云,而IT管理团队则负责管理用户、集群、多云之间的权限。
Rancher API Server作为Rancher的核心组件,基于嵌入式Kubernetes API Server和ETCD数据库构建,提供了一系列关键功能,包括授权和角色权限控制、使用Kubernetes的功能、配置云端基础信息、查看集群信息、编辑下游集群等。
在产品架构方面,Rancher Server由认证代理、Rancher API Server、集群控制器、etcd节点和集群Agent组成。除了集群Agent,其他组件都部署在Rancher Server中。Rancher通过认证代理管理Kubernetes集群,支持在单个节点或高可用的Kubernetes集群上安装Rancher。为确保性能和安全性,建议在高可用的Kubernetes集群中部署Rancher Server,并将Rancher Server集群与运行业务的下游集群分开部署。
与下游集群交互的流程包括:认证代理、集群控制器、集群Agent、节点Agent以及授权集群端点等组件的角色与功能。认证代理集成多种认证方式,如本地认证、活动目录认证和GitHub认证等,确保了请求的安全性。集群控制器和集群Agent负责信息的畅通,节点Agent则在集群Agent不可用时,通过创建通信管道实现与集群控制器的连接,完成与下游集群的通信。同时,Rancher提供了授权集群端点功能,以降低网络延迟,便于用户直接连接到集群。
在运维场景中,了解相关重要文件如kubeconfig等对于问题排查和集群升级至关重要。在实际部署和使用Rancher时,根据下游集群的类型(如通过云供应商自动创建节点、通过自定义主机部署、托管的Kubernetes集群或导入的Kubernetes集群)选择合适的启动工具。
Rancher Server的组件和源代码详细信息可参考其官方文档或GitHub源代码仓库。在进行Rancher安装和配置时,可以遵循官方文档进行操作,以确保系统的稳定运行和高效管理。
SUSE加入欧拉(openEuler)开源社区,打造本地化操作系统基石
SUSE加入欧拉(openEuler)开源社区,共同发布数硕Linux,引发国内关注。
数硕Linux的诞生,旨在解决Linux源代码库和补丁包位置对安全可控性的影响问题。该操作系统是SUSE的中文翻译,通过与openEuler社区合作,强化了其企业级Linux开发经验,如性能优化、版本构建等功能,为openEuler社区带来了巨大提升。
云计算技术进入新阶段,开源协同开发模式成为主流。国电南瑞采用结合openEuler技术的麒麟信安操作系统,成功打造智能电网调度控制系统,部署在多个站点,为电力系统提供稳定运行保障。
容器技术和微服务架构成为企业低成本开发、灵活适配和管理调度编排的需求新选择。SUSE通过收购Rancher,成为企业级Linux、容器、Kubernetes、边缘计算领域的首选开源公司,创新虚拟化和云原生之间的统一管理、调度和编排技术。
openEuler作为开放社区,欢迎SUSE加入,通过与SUSE合作,openEuler工程能力得到巨大提升,同时国内社区也从SUSE立足中国的发展中获益。openEuler当前版本覆盖多种指令集,支持多样化算力和边缘计算、嵌入式电子设备等新场景,加速研究成果转化,让其在企业中真正可用。
SUSE在工程方面积累了丰富的经验,加入欧拉开源社区,使欧拉开源操作系统对高性能介质的支持上了一个新台阶。SUSE与openEuler合作,通过贡献经验与技术,推动欧拉开源操作系统的发展。
Linux操作系统自年发布以来,成为学术交流和技术创新的重要平台。在企业上云趋势下,选择开放、兼容、自由的解决方案成为关键,云计算技术进入全新阶段。数硕Linux的出现,标志着SUSE与openEuler社区的合作,为欧拉开源社区和行业客户带来了重大利好。
数硕Linux通过整合SUSE的工程经验和Rancher相关云原生产品技术,推动欧拉开源操作系统在服务器、云、边缘计算和容器各方向的持续创新。SUSE不仅参与国产Linux操作系统国内大循环,还推动国内国际双循环,携手中国开源走向世界。
2024-11-30 10:25
2024-11-30 09:56
2024-11-30 09:16
2024-11-30 09:13
2024-11-30 09:09