首页
关于作者
阅读记录
友链
Search
1
微内核插件架构风格在skywalking agent 上的实践
363 阅读
2
debian 11 安装nginx 并配置端口映射
341 阅读
3
和chatgpt聊设计
307 阅读
4
开始看《金阁寺》
246 阅读
5
github上star的工程分类记录
202 阅读
不知所云
杂记
书籍摘抄
有点技术
Redis
运维
架构
nginx
byzer
尚未分类
程序人生
与AI聊天
登录
/
注册
Search
标签搜索
nginx
redis
byzer
github
运维
mybatis-plus
王猪
累计撰写
25
篇文章
累计收到
3
条评论
首页
栏目
不知所云
杂记
书籍摘抄
有点技术
Redis
运维
架构
nginx
byzer
尚未分类
程序人生
与AI聊天
页面
关于作者
阅读记录
友链
搜索到
16
篇与
的结果
2024-04-16
架构的起始——黄金链路
架构的起始——黄金链路2023年底,公司有一个部门的对客系统出现了十分严重的故障,损失严重。当日一系列只听过名字,没见过真人的大佬都出现在机房跟进问题排查的进度。事后,具体的原因仍未完全定位。也因这场故障,开始公司级别的重视架构的重要性。2024年,架构提升就摆到了第一位。“黄金链路”应运而生,其指的是一系列涉及客户的重要交易链路的梳理。对于一个几百套系统在生产运行多年的公司来说,想要端到端的完成梳理,是一份巨大的工程。有幸参与到这份工作内容中,也是艰辛伴随着一些成就感。在正式将组织架构调整到架构运维组后,第一份差事就是负责梳理一个未接触过的系统的黄金链路,编写汇报材料。用时1个多月,120多页的PPT,才算完成一份较为完善的材料进行汇报。在此记录一下这份材料编写过程的一些收获。第一是如何进行工作的安排,由中心架构师牵头组织会议,架构运维组全体参加,由系统原负责人进行黄金链路的描述。描述的顺序是业务进行的顺序,讲述使用到的微服务、中间件、外部系统,系统的风险点、监控点,会议中形成泳道图。并在泳道图的每个节点中注释其涉及的数据库表、redis使用的key、es的索引、外部调用的接口等等。第二是汇报的视角,主要分为系统视角与用户视角。系统视角针对泳道图中每一个节点、远程调用进行分析其可能的故障点、应急方案、可优化的方案。从用户的视角,又从对用户的影响分为3种类型,分别是系统报错、内容差错、体验差。并站在用户视角的反馈,梳理第一时间的应急预案是什么,主打三板斧,第一时间停止继续损失,再考虑精确排查问题的节点可能性。第三是汇报的思路,这是一块软技能,对于一张涉及16个微服务,70+节点,30+系统间调用的泳道图,如何向上汇报,让领导能够清晰了解该链路的重要性、当前业务主要的经过、存在的风险点、后续优化的方案、系统应急的方案完善性。首先对该黄金链路的主要业务进行介绍,通过哪些系统对哪些客户进行了服务,服务的量有多大,体现出该黄金链路的价值。其次展示该链路涉及的0层图、1层图(不严格),以及生产部署的物理视图。接着从概要进入详细的泳道图全览,并介绍泳道图中节点的编码方式。然后按照节点重要性进行分类排序、索引,之后再一个个节点进行详细分析,描述其功能,系统视角分类、用户视角分类,故障场景以及对应的应急方案、是否可添加监控、优化方案等等。接着切换为用户视角再总结不同的用户反馈的处理应急预案。最后再附上链路中涉及的表、接口、关键代码的附件。写这样的材料对我来说,真的挺折磨,因为这是公司第一次做这样的事情,汇报材料的模板,格式,都是做了不知道多少次的反复修改,领导每天都能给出一些指导,好在的确是收获不少。之后,我也直接参与了该系统几次生产问题的排查,例如CPU使用率高等问题。发现经过黄金链路的“折磨”后,对链路上的业务已经大致了解了,在排查过程中,真的可以指着泳道图,问对应的同事,这里的表现好像不大对,是不是出现了什么对应的问题。接下来有时间的话,我还想总结一下最近在做的应急演练。思考一下应急演练在测试环境的模拟,系统间问题的编排。不过也不是什么高大上的东西,可能连灰度都不涉及。后一阶段还要在生产上演练~
2024年04月16日
106 阅读
0 评论
0 点赞
2023-08-03
新建复杂工程时引入mybatis-plus注意点
新建复杂工程时引入mybatis-plus注意点有如下的工程结构:/root 根目录 /root/module1 模块1 /root/module2 模块2 /root/module_starter 启动模块(依赖模块1、模块2)记得引入starter我们在module1、module2中会定义mapper、dao等类,所以是需要依赖mybatis-plus相关的注解、类的,例如@TableId等。然后在module_starter中存在启动类,就需要注意:这个模块就需要依赖于mybatis-plus-boot-starter, 不然启动后所有@Mapper均不会生效。记得规范@MapperScan包名范围在项目中,mapper可能存在多个包中,需要注意的是,使用@MapperScan 时,包名不可过于宽泛,例如com.company,过于宽泛的包名会导致Service接口被作为Mapper扫描,最终出现重复Bean导致项目启动失败。@MapperScan 中可以配置多个包名,所以建议可配置的精细一些,以mapper为结尾。
2023年08月03日
107 阅读
0 评论
0 点赞
2023-07-25
class path resource 'xxx.yaml' cannot be opened
class path resource 'xxx.yaml' cannot be openedclass path resource [ xxx.yaml]cannot be opened because it dose not exist。类路径下无法打开一个文件,因为它不存在。这是一个存在/src/main/resources/ 目录下的文件,理论上,在maven 打包后能够读到的。但是反复报错。通过运行时debug, 执行System.getProperty("java.class.path")打印类路径,能够明确的看到C:\Users\xxx\xxx\target\classes; C:\xxx\xxx\xxx\xxx\xxx.jar; ...点开到classes 目录下,能够看到application.yml 等都存在,但是自定义的 xxx.yaml 的确不存在。蓦然想起因为流水线要求打包的jar包要在最外层的target下,内部module 的pom.xml是有一定设置的。而哪些文件被打包进来是有限制的:<resources> <resource> <directory>src/main/resources</directory> <inculude>**/*.yml</inculude> <inculude>**/*.xml</inculude> <inculude>**/*.properties</inculude> </resource> </resources>唯独少了yaml,所以相应的补充一个*/.yaml 即可。总结一下就是,遇到问题还是看看具体报错信息,逐步定位,其实不难。
2023年07月25日
159 阅读
0 评论
0 点赞
2023-07-14
深入理解spring batch
深入理解spring batch一个轻量级、全面的批处理框架,旨在开发对企业系统日常运营至关重要的强大批处理应用程序。概念JobLauncherjob启动器,用于启动jobJobjob接口,默认仅一个实现SimpleJobStepstep接口,一个job中可以有多个Step。其实现较多,也是spring batch中主要扩展、定制的接口。其实现的子类主要主:FlowStep 将一组Step委托给Flow 进行执行。TaskletStep 最简单的Step实现JobStep 将Job包装成一个Step,用Job将不同的Step进行隔离,用于管理Job之间的依赖关系。PartitionStep 使用PartitionHandler对执行进行分区和扩展负载。...JobRepository默认实现为SimpleJobRepository,其包含四个dao操作,其都是以接口的形式暴露出来:JobInstanceDao jobInstanceDao; 任务执行实例资源操作JobExecutionDao jobExecutionDao; 任务执行资源操作StepExecutionDao stepExecutionDao; 步骤执行资源操作ExecutionContextDao ecDao; 执行上下文资源操作Spring Batch 通过JobRepository将JobExecution、StepExecution等运行时上下文、状态进行持久化。JobExecution任务执行,与一个任务实例绑定,当任务的步骤执行时,会动态将一个个StepExecution添加到其中。所以每一个StepExecution都可以通过绑定的JobExecution去获取到所有的StepExecution。StepExecution步骤执行,与每个步骤绑定,同时与JobExecution建立多对一的关系。执行逻辑JobLauncher#run 启动JobjobRepository#getLastJobExecution 获取JobExecution、StepExecution进行校验job.getJobParametersValidator.validate 校验入参jobRepository.createJobExecution 创建JobExecutionjob.execute 进入任务执行BatchMetrics.createObservation 开始任务执行的指标监测listener.beforeJob(execution) 具体任务执行前监听器处理doExecute(execution) 具体任务执行(由子类实现)循环handleStep SimpleJob中循环调用保护方法(由SimpleStepHandler实现)调用step的execute()方法listener.afterJob(execution) 具体任务执行后监听器处理这是一个比较粗略的执行逻辑,从中可以看到有以下扩展点:JobParametersValidator 对任务入参可进行校验JobExecutionListener 可对job的执行前后进行监听处理StepExecutionListener 可对step执行的前后进行监听处理表结构JobInstanceDao -> JOB_INSTANCE表JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSIONJobExecutionDao -> JOB_EXECUTION表JOB_EXECUTION_ID, JOB_INSTANCE_ID, START_TIME, END_TIME, STATUS, EXIT_CODE, EXIT_MESSAGE, VERSION, CREATE_TIME, LAST_UPDATEDStepExecutionDao -> STEP_EXECUTIONSTEP_EXECUTION_ID, VERSION, STEP_NAME, JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, COMMIT_COUNT, READ_COUNT, FILTER_COUNT, WRITE_COUNT, EXIT_CODE, EXIT_MESSAGE, READ_SKIP_COUNT, WRITE_SKIP_COUNT, PROCESS_SKIP_COUNT, ROLLBACK_COUNT, LAST_UPDATED, CREATE_TIMEExecutionContextDao -> JOB_EXECUTION_CONTEXT、STEP_EXECUTION_CONTEXTJOB_EXECUTION_CONTEXT:SHORT_CONTEXT, SERIALIZED_CONTEXT, JOB_EXECUTION_IDSTEP_EXECUTION_CONTEXT:SHORT_CONTEXT, SERIALIZED_CONTEXT, STEP_EXECUTION_ID
2023年07月14日
102 阅读
0 评论
0 点赞
2023-07-10
线上JVM问题排查常用方法
线上JVM问题排查常用方法jpsjps -l 打印java进程的进程号、对应的jar包或命令jps -v 打印java进程的进程号、启动的详细命令、参数jstatjstat -options 查看可选参数-class -compiler -gc -gccapacity -gccause -gcmetacapacity -gcnew -gcnewcapacity -gcold -gcoldcapacity -gcutil -printcompilationclass 打印类加载信息C:\Users\18919>jstat -class 61160 100 5 Loaded Bytes Unloaded Bytes Time 87286 177563.7 3141 4347.7 53.62 87286 177563.7 3141 4347.7 53.62 87286 177563.7 3141 4347.7 53.62 87286 177563.7 3141 4347.7 53.62 87286 177563.7 3141 4347.7 53.62gc 打印gc信息,主要查看FGC相关属性是否正常C:\Users\18919>jstat -gc 61160 100 5 S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT CGC CGCT GCT 0.0 2048.0 0.0 1230.4 634880.0 45056.0 544768.0 403678.5 524864.0 519870.3 68352.0 66078.1 183 1.970 0 0.000 106 2.050 4.020 0.0 2048.0 0.0 1230.4 634880.0 45056.0 544768.0 403678.5 524864.0 519870.3 68352.0 66078.1 183 1.970 0 0.000 106 2.050 4.020 0.0 2048.0 0.0 1230.4 634880.0 45056.0 544768.0 403678.5 524864.0 519870.3 68352.0 66078.1 183 1.970 0 0.000 106 2.050 4.020 0.0 2048.0 0.0 1230.4 634880.0 45056.0 544768.0 403678.5 524864.0 519870.3 68352.0 66078.1 183 1.970 0 0.000 106 2.050 4.020 0.0 2048.0 0.0 1230.4 634880.0 45056.0 544768.0 403678.5 524864.0 519870.3 68352.0 66078.1 183 1.970 0 0.000 106 2.050 4.020jstackjstackC:\Users\18919>jstack 61160 2023-07-10 14:03:11 Full thread dump OpenJDK 64-Bit Server VM (17.0.7+10-b829.16 mixed mode): Threads class SMR info: _java_thread_list=0x00000291ac179d80, length=73, elements={ 0x00000290c39b4fb0, 0x00000290ef87e850, 0x00000290ef8a7cb0, 0x00000290ef8df530, 0x00000291c1427c70, 0x00000291b3e53e00, 0x00000291a311a6a0, 0x00000291cd92f250, 0x00000291a3119830 } "main" #1 prio=5 os_prio=0 cpu=1625.00ms elapsed=91669.62s tid=0x00000290c39b4fb0 nid=0xee14 waiting on condition [0x000000da51d6e000] java.lang.Thread.State: TIMED_WAITING (parking) at jdk.internal.misc.Unsafe.park(java.base@17.0.7/Native Method) - parking to wait for <0x0000000081c81338> (a kotlinx.coroutines.BlockingCoroutine) at java.util.concurrent.locks.LockSupport.parkNanos(java.base@17.0.7/LockSupport.java:252) at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:88) at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59) at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source) at com.intellij.idea.Main.main(Main.kt:40) "Signal Dispatcher" #4 daemon prio=9 os_prio=2 cpu=0.00ms elapsed=91669.59s tid=0x00000290ef8df530 nid=0xea78 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE ... "Attach Listener" #5 daemon prio=5 os_prio=2 cpu=0.00ms elapsed=91669.59s tid=0x00000290ef8dfff0 nid=0xf2ac waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLEjstack pid | grep deadlock 主要用来排查是否存在死锁toptop -H -p [pid] 查看进程中具体是那一条线程的CPU利用率高printf '%x\n' [tid] 将10进制转成16进制jstack pid | grep tid(16进制) 搜索出该线程。vi打开搜索看的更全。jmapjmap -dump:live,format=b,file=heap.hprof pid 生成heap.hprof堆快照文件,可下载用mat打开jmap -histo:live pid | head -20 打印线程存活对象信息。(非基础类的数量多可能就会是存在问题的类)jhatjhat <heap.hprof文件路径> 解析堆快照,会启动一个web应用,在浏览器可分析(简陋)以包为分类,展示每个类ip:port/showInstanceCounts 从大到小按类实例的数量进行展示ip:port/histo 从大到小按占用字节数进行展示ip:port/oql 执行oql表达式的界面SELECT obj FROM java.lang.Object obj WHERE obj.name = 'example'SELECT obj FROM java.lang.Object obj ORDER BY obj.timestamp DESCSELECT COUNT(obj) FROM java.lang.Object objjinfojinfo pid 打印java系统参数、vm标记、vm参数arthasarthas 是阿里开源的在线问题排查工具。较多功能基于Java agent、java ti agent。以下部分命令能加快排查问题进度。dashboard展示线程、内存、gc等信息heapdumpheapdump --live arthas-output/dump.hprof生成文件在arthas-output目录,可以通过浏览器下载: http://localhost:8563/arthas-output/jvm打印jvm信息:DEADLOCK-COUNT: JVM 当前死锁的线程数MAX-FILE-DESCRIPTOR-COUNT:JVM 进程最大可以打开的文件描述符数threadthread -b, 找出当前阻塞其他线程的线程thread -n 3 展示当前最忙的前 N 个线程并打印堆栈jadjad java.lang.String 反编译java.lang.Stringjad demo.MathGame main --lineNumber false --lineNumber 参数默认值为 true,显示指定为 false 则不打印行号。sc查看 JVM 已加载的类信息sc demo.* 模糊搜索sc com.*sc -d demo.MathGame 打印类的详细信息排查常规操作下载应用Jar包,用于反编译看代码,使用Jd-gui或者idea打开。jdk提供的命令或arthas针对问题进行排查jdk命令排查jstack pid |grep deadlock 找死锁jmap -dump:live,format=b,file=heap.hprof pid 生成heap.hprof堆快照文件下载快照文件用Mat打开堆快照文件,内存泄露分析报告生成(慢)jhat <heap.hprof文件路径> 用于简单看直方图等(快)arthas排查上传arthas包,启动并attach到应用进程。jvm 看死锁线程数thread -n 3 展示当前最忙的前 N 个线程并打印堆栈sc com.* 搜索内部编写的类jad java.lang.String 反编译看代码
2023年07月10日
110 阅读
0 评论
0 点赞
1
2
...
4
浙公网安备 33020502001051号
浙ICP备2023015387号-1