禅与计算机 禅与计算机
首页
  • Java基础

    • 聊一聊java一些核心知识点
    • 聊聊java面向对象核心知识点
    • 聊聊Java中的异常
    • 聊聊Java中的常用类String
    • 万字长文带你细聊Java注解本质
    • 来聊聊Java的反射机制
    • 深入解析Java泛型的魅力与机制
    • Java集合框架深度解析与面试指南
    • Java常用集合类HashMap深度解析
    • LinkedHashMap源码到面试题的全解析
    • 深入解析CopyOnWriteArrayList的工作机制
    • Java基础IO总结
    • Java三大IO模型小结
    • Java BIO NIO AIO详解
    • Java进阶NIO之IO多路复用详解
    • Java8流式编程入门
    • 一文速通lambda与函数式编程
    • Java8函数式方法引用最佳实践
  • Java并发编程

    • Java并发编程基础小结
    • 深入理解Java中的final关键字
    • 浅谈Java并发安全发布技术
    • 浅谈Java并发编程中断的哲学
    • Java线程池知识点小结
    • 浅谈Java线程池中拒绝策略与流控的艺术
    • synchronized关键字使用指南
    • 深入源码解析synchronized关键字
    • 详解JUC包下的锁
    • 详解并发编程中的CAS原子类
    • LongAdder源码分析
    • AQS源码解析
    • 深入剖析Java并发编程中的死锁问题
    • Java并发容器总结
    • 详解Java并发编程volatile关键字
    • 并发编程ThreadLocal必知必会
    • CompletableFuture基础实践小结
    • CompletableFuture异步多任务最佳实践
    • 硬核详解FutureTask设计与实现
    • 线程池大小设置的底层逻辑与场景化方案
    • 来聊一个有趣的限流器RateLimiter
  • JVM相关

    • 从零开始掌握 JVM
    • JVM核心知识点小结
    • JVM指令集概览:基础与应用
    • JVM类加载器深度解析
    • JVM方法区深度解析
    • Java内存模型JMM详解
    • Java对象大小的精确计算方法
    • 逃逸分析在Java中的应用与优化
    • 从零开始理解JVM的JIT编译机制
    • G1垃圾回收器:原理详解与调优指南
    • JVM故障排查实战指南
    • JVM内存问题排错最佳实践
    • JVM内存溢出排查指南
    • 简明的Arthas使用教程
    • 简明的Arthas配置及基础运维教程
    • 基于Arthas Idea的JVM故障排查与指令生成
    • 基于arthas量化监控诊断java应用方法论与实践
    • 深入剖析arthas技术原理
  • 深入理解Spring框架

    • Spring 核心知识点全面解析
    • Spring核心功能IOC详解
    • Spring AOP 深度剖析与实践
    • Spring 三级缓存机制深度解析
    • 深入 Spring 源码,剖析设计模式的落地实践
    • 探索 Spring 事务的奥秘
    • 深入解析Spring Bean的生命周期管理
    • 解读 Spring Boot 核心知识点
    • Spring Boot 启动优化实战:1分钟到13秒的排查与优化之路
    • Spring Boot自动装配原理及实践
    • 一文快速上手Sharding-JDBC
    • sharding-jdbc如何实现分页查询
    • 基于DynamicDataSource整合分库分表框架Shardingsphere
  • 计算机组成原理

    • 计算机硬件知识小结
    • CPU核心知识点小结
    • 浅谈CPU流水线的艺术
    • 从Java程序员视角聊聊CPU缓存
    • CPU任务调度和伪共享问题小结
    • CPU MESI缓存一致性协议
    • CPU内存管理机制
    • 内存深度解析
    • 磁盘存储原理
    • 详解计算机启动步骤
    • CPU南北桥架构与发展史
    • CPU中断机制与硬件交互详解
  • 操作系统

    • 如何实现一个高性能服务器
    • Linux文件结构与文件权限
    • Linux常见压缩指令小结
    • Linux核心系统调用详解
    • Linux进程管理
    • Linux线程管理
    • 进程与线程深度解析
    • Linux进程间通信机制
    • 零拷贝技术原理与实践
    • CPU缓存一致性问题深度解析
    • IO任务与CPU调度艺术
  • 计算机网络

    • 网卡通信原理详解
    • 网卡数据包处理指南
    • 基于抓包详解TCP协议
  • 编码最佳实践

    • 浅谈现代软件工程TDD最佳实践
    • 浅谈TDD模式下并发程序设计与实现
    • 面向AI编程新范式Trae后端开发环境搭建与实践
    • 基于提示词工程的Redis签到功能开发实践
    • 基于Vibe Coding的Redis分页查询实现
    • 告别AI无效对话:资深工程师的提示词设计最佳实践
  • 实用技巧与配置

    • Mac常用快捷键与效率插件指南
    • Keynote技术科普短视频制作全攻略
  • 写作

    • 写好技术博客的5大核心原则:从认知科学到AI工具的全流程指南
  • 开发工具

    • IDEA配置详解与高效使用指南
  • Nodejs
  • 博客搭建
  • Redis

    • Redis核心知识小结
    • 解锁Redis发布订阅模式
    • 掌握Redis事务
    • Redis主从复制技术
    • Redis的哨兵模式详解
    • 深度剖析Redisson分布式锁
    • 详解redis单线程设计思路
    • 来聊聊Redis所实现的Reactor模型
    • Redis RDB持久化源码深度解析
    • 来聊聊redis的AOF写入
    • 来聊聊Redis持久化AOF管道通信的设计
    • 来聊聊redis集群数据迁移
    • Redis SDS动态字符串深度解析
    • 高效索引的秘密:redis跳表设计与实现
    • 聊聊redis中的字典设计与实现
  • MySQL

    • MySQL基础知识点小结
    • 解读MySQL 索引基础
    • MySQL 索引进阶指南
    • 解读MySQL Explain关键字
    • 探秘 MySQL 锁:原理与实践
    • 详解MySQL重做日志redolog
    • 详解undoLog在MySQL MVCC中的运用
    • MySQL二进制日志binlog核心知识点
    • MySQL高效插入数据的最佳实践
    • MySQL分页查询优化指南
    • MySQL流式查询的奥秘与应用解析
    • 来聊聊分库分表
    • 来聊聊大厂常用的分布式ID生成方案
  • ElasticSearch

    • 从Lucene到Elasticsearch:进化之路
    • ES 基础使用指南
    • ElasticSearch如何写入一篇文档
    • 深入剖析Elasticsearch文档读取原理
    • 聊聊ElasticSearch性能调优
    • Spring借助Easy-Es操作ES
  • Netty

    • 一文快速了解高性能网络通信框架Netty
    • Netty网络传输简记
    • 来聊聊Netty的ByteBuf
    • 来聊聊Netty消息发送的那些事
    • 解密Netty高性能之谜:NioEventLoop线程池阻塞分析
    • 详解Netty中的责任链Pipeline如何管理ChannelHandler
    • Netty Reactor模型常见知识点小结
    • Netty如何驾驭TCP流式传输?粘包拆包问题全解
    • Netty解码器源码解析
  • 消息队列

    • 一文快速入门消息队列
    • 消息队列RocketMQ入门指南
    • 基于RocketMQ实现分布式事务
    • RocketMQ容器化最佳实践
    • RocketMQ常见问题与深度解析
    • Kafka快速安装与使用指南
  • Nginx

    • Linux下的nginx安装
    • Nginx基础入门总结
    • Nginx核心指令小结
    • Nginx进程结构与核心模块初探
    • Nginx应用进阶HTTP核心模块配置
    • Nginx缓存及HTTPS配置小记
    • nginx高可用实践简记
    • Nginx性能优化
  • 微服务基础

    • 微服务基础知识小结
    • 分布式事务核心概念小结
    • OpenFeign核心知识小结
    • 微服务组件Gateway核心使用小结
    • 分布式事务Seata实践
    • 用 Docker Compose 完成 Seata 的整合部署
  • Nacos

    • Nacos服务注册原理全解析
    • Nacos服务订阅流程全解析
    • Nacos服务变更推送流程全解析
    • 深入解析SpringCloud负载均衡器Loadbalancer
    • Nacos源码环境搭建与调试指南
  • Seata

    • 深度剖析Seata源码
  • Docker部署

    • 一文快速掌握docker的理念和基本使用
    • 使用docker编排容器
    • 基于docker-compose部署微服务基本环境
    • 基于docker容器化部署微服务
    • Gateway全局异常处理及请求响应监控
    • Docker图形化界面工具Portainer最佳实践
  • Go基础

    • 一文带你速通Go语言基础语法
    • 一文快速掌握Go语言切片
    • 来聊聊go语言的hashMap
    • 一文速通go语言类型系统
    • 浅谈Go语言中的面向对象
    • go语言是如何实现协程的
    • 聊聊go语言中的GMP模型
    • 极简的go语言channel入门
    • 聊聊go语言基于epoll的网络并发实现
    • 写给Java开发的Go语言协程实践
  • mini-redis实战

    • 来聊聊我用go手写redis这件事
    • mini-redis如何解析处理客户端请求
    • 实现mini-redis字符串操作
    • 硬核复刻redis底层双向链表核心实现
    • 动手复刻redis之go语言下的字典的设计与落地
    • Go 语言下的 Redis 跳表设计与实现
    • Go 语言版 Redis 有序集合指令复刻探索
  • 项目编排

    • Spring脚手架创建简记
    • Spring脚手架集成分页插件
    • Spring脚手架集成校验框架
    • maven父子模块两种搭建方式简记
    • SpringBoot+Vue3前后端快速整合入门
    • 来聊聊Java项目分层规范
  • 场景设计

    • Java实现文件分片上传
    • 基于时间缓存优化浏览器轮询阻塞问题
    • 基于EasyExcel实现高效导出
    • 10亿数据高效插入MySQL最佳方案
    • 从开源框架中学习那些实用的位运算技巧
  • CI/CD

    • 基于NETAPP实现内网穿透
    • 基于Gitee实现Jenkins自动化部署SpringBoot项目
    • Jenkins离线安装部署教程简记
    • 基于Nexus搭建Maven私服基础入门
    • 基于内网的Jenkins整合gitlab综合方案简记
  • 监控方法论

    • SpringBoot集成Prometheus与Grafana监控
    • Java监控度量Micrometer全解析
    • 从 micrometer计量器角度快速上手promQL
    • 硬核安利一个监控告警开源项目Nightingale
  • Spring AI

    • Spring AI Alibaba深度实战:一文掌握智能体开发全流程
    • Spring AI Alibaba实战:JVM监控诊断Arthas Agent的工程化构建与最佳实践
  • 大模型评测

    • M2.7 真能打!我用两个真实场景测了测,结果有点意外
    • Qoder JetBrains插件评测:祖传代码重构与接口优化实战
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

sharkchili

计算机禅修者
首页
  • Java基础

    • 聊一聊java一些核心知识点
    • 聊聊java面向对象核心知识点
    • 聊聊Java中的异常
    • 聊聊Java中的常用类String
    • 万字长文带你细聊Java注解本质
    • 来聊聊Java的反射机制
    • 深入解析Java泛型的魅力与机制
    • Java集合框架深度解析与面试指南
    • Java常用集合类HashMap深度解析
    • LinkedHashMap源码到面试题的全解析
    • 深入解析CopyOnWriteArrayList的工作机制
    • Java基础IO总结
    • Java三大IO模型小结
    • Java BIO NIO AIO详解
    • Java进阶NIO之IO多路复用详解
    • Java8流式编程入门
    • 一文速通lambda与函数式编程
    • Java8函数式方法引用最佳实践
  • Java并发编程

    • Java并发编程基础小结
    • 深入理解Java中的final关键字
    • 浅谈Java并发安全发布技术
    • 浅谈Java并发编程中断的哲学
    • Java线程池知识点小结
    • 浅谈Java线程池中拒绝策略与流控的艺术
    • synchronized关键字使用指南
    • 深入源码解析synchronized关键字
    • 详解JUC包下的锁
    • 详解并发编程中的CAS原子类
    • LongAdder源码分析
    • AQS源码解析
    • 深入剖析Java并发编程中的死锁问题
    • Java并发容器总结
    • 详解Java并发编程volatile关键字
    • 并发编程ThreadLocal必知必会
    • CompletableFuture基础实践小结
    • CompletableFuture异步多任务最佳实践
    • 硬核详解FutureTask设计与实现
    • 线程池大小设置的底层逻辑与场景化方案
    • 来聊一个有趣的限流器RateLimiter
  • JVM相关

    • 从零开始掌握 JVM
    • JVM核心知识点小结
    • JVM指令集概览:基础与应用
    • JVM类加载器深度解析
    • JVM方法区深度解析
    • Java内存模型JMM详解
    • Java对象大小的精确计算方法
    • 逃逸分析在Java中的应用与优化
    • 从零开始理解JVM的JIT编译机制
    • G1垃圾回收器:原理详解与调优指南
    • JVM故障排查实战指南
    • JVM内存问题排错最佳实践
    • JVM内存溢出排查指南
    • 简明的Arthas使用教程
    • 简明的Arthas配置及基础运维教程
    • 基于Arthas Idea的JVM故障排查与指令生成
    • 基于arthas量化监控诊断java应用方法论与实践
    • 深入剖析arthas技术原理
  • 深入理解Spring框架

    • Spring 核心知识点全面解析
    • Spring核心功能IOC详解
    • Spring AOP 深度剖析与实践
    • Spring 三级缓存机制深度解析
    • 深入 Spring 源码,剖析设计模式的落地实践
    • 探索 Spring 事务的奥秘
    • 深入解析Spring Bean的生命周期管理
    • 解读 Spring Boot 核心知识点
    • Spring Boot 启动优化实战:1分钟到13秒的排查与优化之路
    • Spring Boot自动装配原理及实践
    • 一文快速上手Sharding-JDBC
    • sharding-jdbc如何实现分页查询
    • 基于DynamicDataSource整合分库分表框架Shardingsphere
  • 计算机组成原理

    • 计算机硬件知识小结
    • CPU核心知识点小结
    • 浅谈CPU流水线的艺术
    • 从Java程序员视角聊聊CPU缓存
    • CPU任务调度和伪共享问题小结
    • CPU MESI缓存一致性协议
    • CPU内存管理机制
    • 内存深度解析
    • 磁盘存储原理
    • 详解计算机启动步骤
    • CPU南北桥架构与发展史
    • CPU中断机制与硬件交互详解
  • 操作系统

    • 如何实现一个高性能服务器
    • Linux文件结构与文件权限
    • Linux常见压缩指令小结
    • Linux核心系统调用详解
    • Linux进程管理
    • Linux线程管理
    • 进程与线程深度解析
    • Linux进程间通信机制
    • 零拷贝技术原理与实践
    • CPU缓存一致性问题深度解析
    • IO任务与CPU调度艺术
  • 计算机网络

    • 网卡通信原理详解
    • 网卡数据包处理指南
    • 基于抓包详解TCP协议
  • 编码最佳实践

    • 浅谈现代软件工程TDD最佳实践
    • 浅谈TDD模式下并发程序设计与实现
    • 面向AI编程新范式Trae后端开发环境搭建与实践
    • 基于提示词工程的Redis签到功能开发实践
    • 基于Vibe Coding的Redis分页查询实现
    • 告别AI无效对话:资深工程师的提示词设计最佳实践
  • 实用技巧与配置

    • Mac常用快捷键与效率插件指南
    • Keynote技术科普短视频制作全攻略
  • 写作

    • 写好技术博客的5大核心原则:从认知科学到AI工具的全流程指南
  • 开发工具

    • IDEA配置详解与高效使用指南
  • Nodejs
  • 博客搭建
  • Redis

    • Redis核心知识小结
    • 解锁Redis发布订阅模式
    • 掌握Redis事务
    • Redis主从复制技术
    • Redis的哨兵模式详解
    • 深度剖析Redisson分布式锁
    • 详解redis单线程设计思路
    • 来聊聊Redis所实现的Reactor模型
    • Redis RDB持久化源码深度解析
    • 来聊聊redis的AOF写入
    • 来聊聊Redis持久化AOF管道通信的设计
    • 来聊聊redis集群数据迁移
    • Redis SDS动态字符串深度解析
    • 高效索引的秘密:redis跳表设计与实现
    • 聊聊redis中的字典设计与实现
  • MySQL

    • MySQL基础知识点小结
    • 解读MySQL 索引基础
    • MySQL 索引进阶指南
    • 解读MySQL Explain关键字
    • 探秘 MySQL 锁:原理与实践
    • 详解MySQL重做日志redolog
    • 详解undoLog在MySQL MVCC中的运用
    • MySQL二进制日志binlog核心知识点
    • MySQL高效插入数据的最佳实践
    • MySQL分页查询优化指南
    • MySQL流式查询的奥秘与应用解析
    • 来聊聊分库分表
    • 来聊聊大厂常用的分布式ID生成方案
  • ElasticSearch

    • 从Lucene到Elasticsearch:进化之路
    • ES 基础使用指南
    • ElasticSearch如何写入一篇文档
    • 深入剖析Elasticsearch文档读取原理
    • 聊聊ElasticSearch性能调优
    • Spring借助Easy-Es操作ES
  • Netty

    • 一文快速了解高性能网络通信框架Netty
    • Netty网络传输简记
    • 来聊聊Netty的ByteBuf
    • 来聊聊Netty消息发送的那些事
    • 解密Netty高性能之谜:NioEventLoop线程池阻塞分析
    • 详解Netty中的责任链Pipeline如何管理ChannelHandler
    • Netty Reactor模型常见知识点小结
    • Netty如何驾驭TCP流式传输?粘包拆包问题全解
    • Netty解码器源码解析
  • 消息队列

    • 一文快速入门消息队列
    • 消息队列RocketMQ入门指南
    • 基于RocketMQ实现分布式事务
    • RocketMQ容器化最佳实践
    • RocketMQ常见问题与深度解析
    • Kafka快速安装与使用指南
  • Nginx

    • Linux下的nginx安装
    • Nginx基础入门总结
    • Nginx核心指令小结
    • Nginx进程结构与核心模块初探
    • Nginx应用进阶HTTP核心模块配置
    • Nginx缓存及HTTPS配置小记
    • nginx高可用实践简记
    • Nginx性能优化
  • 微服务基础

    • 微服务基础知识小结
    • 分布式事务核心概念小结
    • OpenFeign核心知识小结
    • 微服务组件Gateway核心使用小结
    • 分布式事务Seata实践
    • 用 Docker Compose 完成 Seata 的整合部署
  • Nacos

    • Nacos服务注册原理全解析
    • Nacos服务订阅流程全解析
    • Nacos服务变更推送流程全解析
    • 深入解析SpringCloud负载均衡器Loadbalancer
    • Nacos源码环境搭建与调试指南
  • Seata

    • 深度剖析Seata源码
  • Docker部署

    • 一文快速掌握docker的理念和基本使用
    • 使用docker编排容器
    • 基于docker-compose部署微服务基本环境
    • 基于docker容器化部署微服务
    • Gateway全局异常处理及请求响应监控
    • Docker图形化界面工具Portainer最佳实践
  • Go基础

    • 一文带你速通Go语言基础语法
    • 一文快速掌握Go语言切片
    • 来聊聊go语言的hashMap
    • 一文速通go语言类型系统
    • 浅谈Go语言中的面向对象
    • go语言是如何实现协程的
    • 聊聊go语言中的GMP模型
    • 极简的go语言channel入门
    • 聊聊go语言基于epoll的网络并发实现
    • 写给Java开发的Go语言协程实践
  • mini-redis实战

    • 来聊聊我用go手写redis这件事
    • mini-redis如何解析处理客户端请求
    • 实现mini-redis字符串操作
    • 硬核复刻redis底层双向链表核心实现
    • 动手复刻redis之go语言下的字典的设计与落地
    • Go 语言下的 Redis 跳表设计与实现
    • Go 语言版 Redis 有序集合指令复刻探索
  • 项目编排

    • Spring脚手架创建简记
    • Spring脚手架集成分页插件
    • Spring脚手架集成校验框架
    • maven父子模块两种搭建方式简记
    • SpringBoot+Vue3前后端快速整合入门
    • 来聊聊Java项目分层规范
  • 场景设计

    • Java实现文件分片上传
    • 基于时间缓存优化浏览器轮询阻塞问题
    • 基于EasyExcel实现高效导出
    • 10亿数据高效插入MySQL最佳方案
    • 从开源框架中学习那些实用的位运算技巧
  • CI/CD

    • 基于NETAPP实现内网穿透
    • 基于Gitee实现Jenkins自动化部署SpringBoot项目
    • Jenkins离线安装部署教程简记
    • 基于Nexus搭建Maven私服基础入门
    • 基于内网的Jenkins整合gitlab综合方案简记
  • 监控方法论

    • SpringBoot集成Prometheus与Grafana监控
    • Java监控度量Micrometer全解析
    • 从 micrometer计量器角度快速上手promQL
    • 硬核安利一个监控告警开源项目Nightingale
  • Spring AI

    • Spring AI Alibaba深度实战:一文掌握智能体开发全流程
    • Spring AI Alibaba实战:JVM监控诊断Arthas Agent的工程化构建与最佳实践
  • 大模型评测

    • M2.7 真能打!我用两个真实场景测了测,结果有点意外
    • Qoder JetBrains插件评测:祖传代码重构与接口优化实战
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 项目编排

  • 场景设计

  • CI-CD

  • 架构设计

    • 浅谈分布式架构设计思想和常见优化手段
      • 写在文章开头
      • 详解高并发系统的关键指标
      • 数据一体化模式
        • 详解数据一体化模式
        • 监控时如何判定当前服务器是否正常
      • 应用与数据分离模式
        • 应用与数据分离架构简介
        • 关于单体应用启动前系统指标飙升问题
      • 缓存与性能的提升
      • 分布式负载均衡
        • 分布式负载均衡架构模式
        • 系统的QPS与服务器数量评估
        • 服务器选型
        • 分布式架构一定比单体架构要好
      • 读写分离
      • 引入CDN缓存
      • 分库分表
        • 详解分库分表理论思路
        • 如果单表数据量大,只能考虑分库分表吗
      • 分布式架构
        • 详解分布式结构模式
        • 分布式业务架构流量突增问题
        • 削峰填谷的流量控制策略
        • 关于服务限流的探讨
      • 分布式微服务
        • 详解分布式微服务架构特点
        • 服务拆分后的接口机器预估
        • 微服务界面长耗时问题
      • 小结
      • 参考
  • 监控方法论

  • 软件工程实践
  • 架构设计
sharkchili
2026-03-25
目录

浅谈分布式架构设计思想和常见优化手段

@[toc]

# 写在文章开头

之前的文章更多是从微观的视角去某些分布式架构下的计数架构落地细节,而本系列的文章笔者将从宏观架构的视角来软件架构设计的那些事,希望对你有帮助。

我是 SharkChili ,Java 开发者,Java Guide 开源项目维护者。欢迎关注我的公众号:写代码的SharkChili,也欢迎您了解我的开源项目 mini-redis:https://github.com/shark-ctrl/mini-redis (opens new window)。

为方便与读者交流,现已创建读者群。关注上方公众号获取我的联系方式,添加时备注加群即可加入。

# 详解高并发系统的关键指标

在设计一个软件系统的时候,我们需要对系统性能进行整体的评估,下面就是需要我们在日常进行系统评估和调优分析的关键指标:

  1. RT(response time):响应时间,它代表发送请求到响应数据所花费的时间,也可以为理解我们web开发领域所谓的接口响应耗时,它反映了系统响应的快慢。
  2. throughput:也就是我们常说的吞吐量,它在不同的领域都有着不同的含义:
业务角度:吞吐量可以代表请求数/秒、人/天或者 处理的业务数/小时
网络角度:从网络角度来看,可直接用字节数/秒
1
2

针对广义上互联网领域,该指标更多反应的是系统的负载能力,在没有性能瓶颈时,服务器吞吐量计算公式为:

F= VU(虚拟用户数) * R(虚拟用户发出请求数) /T (测试时花费的时间)
1
  1. QPS(每秒请求数):指服务器一秒内处理了多少个请求,主要用于表示读请求。

  2. TPS(每秒事务数): 以高并发系统中TPS中所指的事务数包括3个过程:客户端请求服务端、服务端内部执行业务逻辑、服务端响应结果给客户端。

这里很多读者可能对于TPS和QPS的概念有写混淆,实际上TPS相较于QPS来说更能反应服务单位时间内的一个完整的原子的事务的处理能力。 例如我们现在有个web页面,当用户打开到完全加载查看到页面内容时,这就可以理解为1个TPS,而这个页面中所有请求的接口就应该计入QPS中。

  1. PV(访问量): 也就是page view,页面浏览量的意思,用户每对网站中一个完整的网页进行一次浏览就可以视为PV+1。
  2. UV(独立访客):unique visitor指代某个网站或者或者链接中出现的不同的IP的数量,我们可以把ip地址视为这个访客的身份证,这意味着某个ip某天无论访问网站多少次均视为一次,这也意味着UV代表着网站某天有多少独立访客进行访问。

# 数据一体化模式

# 详解数据一体化模式

软件发展初期,大部分软件应用都以门户、OA等系统为主,这些系统无论在访问人数还是系统数据量都是有限的。所以单体服务器就可以轻松解决这些问题。所以此时的软件架构着重追求的简单和快速迭代、成本低,所以所有程序和数据库等部署在一台服务器上,因为这种架构是将应用和数据库都存放在一台服务器上,所以我们一般称这种部署模式为数据一体化模式:

# 监控时如何判定当前服务器是否正常

针对业务初期的数据一体化模式,性能瓶颈大概率要依赖与系统服务器指标监测,这里我们针对一个8C16G服务器并独立部署和一个单体应用和数据库的场景,给出一个比较合理的指标参考:

  1. CPU利用率:一般建议高负载情况下不要超70%。
  2. 负载:单核负载超过0.7就说明有问题,所以负载一般要求卡在5.6(8核*0.7)以内算正常。
  3. 磁盘利用率:一般来说超过70%时就需要考虑清理一些过期的无用的垃圾数据了。
  4. 堆内存占用:一般建议堆内存不要分配超过机器的一半,可以适当多一些。
  5. 内存使用率:结合上述堆内存的配置,一般来说内存使用率不要超过70%超过则说明可能有内存泄漏或者程序吞吐量下降的风险。
  6. GC次数和时长:这个更多是经验之谈,理论来说full gc不要在也为高峰期出现就行了,而每次垃圾回收时常stw一般不要超过200ms,这样对用户来说是无感知的,而minor gc最坏的场景一般要求每分钟不能超过1次,每次50ms以内比较合理。

关于系统负载情况的评估可以参考这篇文章:Understanding Linux CPU Load - when should you be worried?:https://scoutapm.com/blog/understanding-load-averages (opens new window)

# 应用与数据分离模式

# 应用与数据分离架构简介

基于这个架构我们的业务体量有所增加,此时无论是活跃用户数量还是数据量都有所上升,这时候我们一般都会考虑增加资源,于是我们将应用和数据库分离。

这样做的好处是让软件和数据库可以专注于各自维度的优化,即应用是对外提供服务的,更着重追求CPU和内存。而数据库因为需要堆数据进行存储和索引等IO操作,更着重的是IO性能以及磁盘转速,当然对于内存要求也是有的,所以将数据库从应用服务器中分离将其部署在一台磁盘空间更大、IO性能更好的服务器上,由此提升应用整体吞吐量:

# 关于单体应用启动前系统指标飙升问题

通过数据与应用分离,我们得到了一个更加存粹的应用系统服务器,此时调优工作会更着重于应用,假如应用启动后前几分钟,Load、RT、CPU等飙高,如何定位,可能的原因是什么?

注意问题所强调的启动后的几分钟,说明这些问题大部分是发生在启动前,一般来说服务启动可能存在如下问题:

  1. 灰度发布
  2. 资源初始化预热

针对问题1,这是分布式场景的问题,我们简单说明一下,假如我们日常100台服务器刚好承载业务流量,灰度发布是批次升级,这期间就可能存在不到100台服务承载100台服务器的流量,在灰度升级期间就可能存在上述指标飙高的情况。

这对问题2,就是我们的单体架构的场景了,我们的服务启动前都需要连接池、线程池、缓存预热的预热等工作,针对这种情况我们可以用例如arthas等工具进行定位排查,确保这些工作完成后再将服务暴露出去。

除了上述情况,还有可能和java语言本身的JIT机制优化,在服务初始化时,大部分代码执行过程都是通过解释后在运行的,只有在运行一段时间成为热点代码后才会生成机器码缓存,由此提升程序运行效率,针对该问题解决思路也有很多,例如:

  1. 提前在业务上运行这段代码进行预热。
  2. 使用JwarmUp技术保证上一次启动后的信息存储到文件中,确保下次启动时通过读取该文件提前完成JIT优化。

# 缓存与性能的提升

业务体量还在增加,特定场景下某些数据是被用户频繁查询的热点数据,在之前的架构下,获取这些信息的方式都是通过数据库查询获取,因此数据库在这个节点很可能称为系统的瓶颈。所以我们就考虑引入一个缓存中间件,针对热点数据或是通过预加载或是数据库查询后缓存的方式存放到内存中,从而提升热点数据的查询性能。

需要了解的是,一般情况下,缓存中间件可以和应用程序放在一起,但还是本着独立自治且合理利用资源的原则,我们一般建议将缓存也专门部署到一台服务器上,让其享有较大的内存空间以加载更多的数据:

有了缓存中间件之后,我们除了可以在服务启动时提前加载热点数据,对于某些不可提前预知的数据,我们可以通过如下步骤完成:

  1. 查看redis是否有热点数据,如果有则直接返回,如果没有则进入步骤2。
  2. 数据库查询,如果有则加载至缓存中,并将结果返回。

因为缓存数据位于内存,相较于数据库那种需要通过磁盘IO(大部分情况下,其实数据也有buffer pool)响应速度会更快一些。 但是随之而来的就是可用性和一致性等问题,例如:

  1. 缓存中间挂了怎么办?
  2. 缓存服务器宕机怎么办?
  3. 如何解决数据库和缓存中间件数据一致性问题。

这些笔者都会在后续系列文章中补充说明。

# 分布式负载均衡

# 分布式负载均衡架构模式

引入缓存中间件进一步提升了系统吞吐量,这时候就要考虑高并发请求性能瓶颈了,随着业务发展用户的请求量也会不断的提升,这也就是我们常说的高并发问题了.

此时我们的应用只单台服务器上,尽管各种通过各种参数调优和程序优化提升系统整体吞吐量,但毕竟应用是依赖于系统服务器的,最终都会在一个阈值上进入瓶颈而无法进一步优化,例如:

  1. 系统程序经过优化操作系统负载持续超过70%
  2. 内存资源严重告急,频繁超过70%以上涉及内存数据被swap到交换分区

所以我们还是采用水平拓展的方式构成服务器集群,即通过更多的服务器承载单位时间内的并发请求,从而提升系统整体的吞吐量。

如下图可以看到,本次架构本质上是通过横向拓展的方式让负载均衡器通过负载均衡算法将请求分散到不同的应用服务器上,借着负载均衡器,我们还可以针对系统整体做流控、鉴权、反向代理等统一请求管理,保证系统整体安全和稳定:

# 系统的QPS与服务器数量评估

针对分布式负载均衡,进行横向拓展时我们必须结合业务场景获得一个比较准确的估值进行服务器部署,假设每日有500w的请求,按照业界的二八原则即80%的流量都发生在20%的时间段,对此我们的推算系统QPS的步骤为:

一天24小时,而流量基本都发生在白天,所以我们实际要关注的时间段应该是12h。 对应20%的时间段即指代12*0.2即某个时间段的2h承载80%的流量,所以我们可以得到如下的计算:

(流量*80%)/(高峰时间段小时)/(每小时有多少秒)
(500_0000 * 0.8) / (12 * 0.2)/(60 * 60) ≈ 460
1
2

由此我们可以推算出系统日常情况下是QPS为460,为预防突发流量,所以峰值应该是平均高峰值的2~3倍数,所以我们认为当前场景下QPS最高应该是1500左右。 假设单台机器可承受的QPS为300,换算一下1500/300,我们大约需要5台左右的服务器,然后基于这个基准的值提前设置一下限流、熔断策略,由此高性能和高可用。

# 服务器选型

有了上述的服务器配算方案之后,我们就需要针对性选择何时的服务器,假设我们有4C8G *16台 和 8C16G*8台,我们该选择那种方案呢?

两者服务器各有各的优势,对此我们可以从以下几个角度考虑问题:

  1. 单机瓶颈:这一点很明显后者表现更加出色,假如遇到某些功能场景需要更多的核心数和内存,前者则会力不从心。
  2. 容错:前者机器更多,及时单台机器出现故障,对于系统的整体影响面相较于后者会小些。
  3. 负载均衡:因为前者有着更多的机器,所以对于负载均衡这种横向拓展问题发挥的空间会更大一些。
  4. 连接数:MySQL分配给单机的连接数是固定的,且大公司企业都不允许调整连接数,这也就意味着有着更多的机器总的连接数也就越多。
  5. GC效率:从垃圾回收器来说扫描垃圾的开销远小于回收垃圾的开销,单机有着更大的内存空间减少垃圾回收次数自然是更好的做法。

总体来说,4C8G *16台更符合现代微服务的理念,服务器更加轻量级,通过堆叠更多的服务器分散压力,对于并发处理能力、容错能力、负载均衡、连接数等方面更加友好,但还是需要考虑单机性能瓶颈和GC次数和扩容效率带来的影响。

# 分布式架构一定比单体架构要好

单体架构也就是我们上说数据一体化模式及其进阶版本,一般发生在企业创业初期,为了快速进入市场时所诞生的系统,它要求系统越简单越好,搭建过程也是越快越好,一般来说单体架构标配为:

  1. 一个应用程序
  2. 一个数据
  3. 一个文件服务器

它的优点如下:

1. 开发、测试、部署成本都非常低,只需针对一个项目开展,基本上可以做到前脚修改吼叫直接打包部署上线。
2. 单体程序网络基本都是数据库、redis等,不需要通过RPC与其他服务做交互,大大降低网络延迟。
3. 因为业务逻辑全部打包在单体上,不需考虑分布式锁、分布式事务、分布式id问题,只需专注解决单机并发问题即可。
1
2
3

由此缺点也很明显:

  1. 单体架构在业务量增加后容易导致性能瓶颈。
  2. 单体架构所有业务都耦合在一个程序上,随着业务演进,多人协作开发时代码耦合度非常高,测试回归成本也会急剧增加,随着时间推移可能导致开发节奏混乱、业务边界不清晰、分支合并各种冲突导致各种潜在的风险。
  3. 单点故障会导致业务全瘫。
  4. 这也是最为严重的一点,单体架构随着业务的拓展,按照用户展示层、业务逻辑层、数据访问层这种模式进行分层逻辑,在业务不断迭代之后,系统调用会构成下图所示的网状结构,在水平方向上来看确实比较精简,但是从垂直的角度来看,各层之间相互错中复杂的调用,导致各层都会存在依赖一个或者多个模块的情况,这对于后续的功能复用、维护、甚至是不同模块间的技术栈升级都是异常困难的。

而分布式架构对应的优点有:

  1. 不同服务分布在不同的服务器上,横向拓展方便,将一个复杂的问题拆解到不同的服务上,业务边界更加清晰,降低团队的协作成本。
  2. 可以灵活结合业务场景进行服务拆分、堆加服务器,快速拓展以抗住高并发流量。
  3. 模块化开发,易于功能拓展和维护。
  4. 单点故障问题相较于单体架构来说会相对少一些。

对应缺点:

  1. 运维成本高,分布式场景我们需要针对多个服务进行部署、监控、日志、故障恢复,增加系统的复杂度,且对于分布式场景风险众多,需要考虑的问题场景相较于前者更多,对于运维、开发要求会更高。
  2. 故障定位,分布式架构相较于前者更复杂,一个请求需要经过很多个服务,出现问题时的排查成本相较于单体架构来说会更高,由此还得借助分布式链路追踪。
  3. 服务边界拆分维度也很困难,拆分粒度小了对于多服务运维和监控成本会增加,拆分粒度过粗又会导致服务后期变为一个臃肿的单体。
  4. 分布式一致性问题,临界资源考虑的维度都是面向分布式场景,这其中就会面临分布式事务和分布式锁一致性问题。

所以对于开发周期短、业务量小、追求快速上线优先考虑使用单体架构,只有业务增长,需要考虑高并发和高可用的场景才需要考虑分布式和微服务这些。

# 读写分离

我们通过缓存中间件解决了热点数据问题,但是缓存中间件的容量毕竟是有限的,对于非热点数据我们还是需要通过数据库进行统一维护管理为了避免数据库写操作(update、insert、delete)阻塞其他事务读操作(select),因为现代主流系统架构基本都是读多写少的,所以我们更倾向于引入读写分离的方案,即让所有写操作都都面向master服务器,而读操作都通过slave服务器完成,slave通过订阅master库的bin.log进行数据实时同步操作。

在此基础上我们针对表进行优化设计,减小应用请求进行写操作时上X锁的粒度,保证写操作的吞吐量,与此同时因为读操作上的都是S锁,而S锁之间都是彼此兼容,由此通过读写分离加S锁兼容性,更进一步提升系统整体吞吐量。

# 引入CDN缓存

实际上,我们进行web网站浏览时,大部分都是基本不变的静态数据例如:JS脚本、HTML、图片文件等,考虑到访问的用户位于不同的城市,在针对这些系统资源加载的时可能会经过好几个网络路由转发才能完成资源下载,所以我们提出CDN技术即资源分发网络(Content Delivery Network),而CDN的大体工作流程是:

  1. 用户通过域名针对网站发起资源请求,首先向LDNS(本地DNS)进行域名请求。
  2. DNS解析域名得到对应的CNAME对应的IP地址,从而定位到的服务商的服务器。
  3. 重点来了,服务提供商通过DNS调取系统返回给用户最佳IP地址。
  4. 基于这个IP地址发起资源请求,资源服务器就会查看该服务器是否有请求的静态资源,如果没有则缓存并返回,若有则直接返回。

可以看到,通过CDN减轻了应用服务器的压力,大大提升的web页面的响应速度,保证了可用性和高性能:

# 分库分表

# 详解分库分表理论思路

经过上述几轮的架构演进,软件的系统架构已经趋于稳定,随着时间的推移数据库中的数据体量也会随之逐步增加,即使通过读写分离单表数据体量已无法保证大表的快速检索,同时也考虑到并发请求的体量也在逐步增加每个数据库所能承受的最大连接数也已经无法满足现有的业务需求,所以我们又不得不考虑更进一轮的水平拓展。即分库分表方案将大表拆小,增加几台数据库服务器来分摊这些数据管理。

因为数据库分散部署,所以在进行分库分表设计时我们还需要结合一定的算法保证数据维护和检索的开销,为此我们可能还需要引入分库分表中间件来管理应用程序的数据库访问工作:

# 如果单表数据量大,只能考虑分库分表吗

分库分表是综合解决并发和数据检索效率的综合方案,但是分库分表后会带来问题:

  1. 跨库表分页
  2. 分布式事务
  3. 非分片键值的数据查询
  4. 跨库表join关联查询

针对单表数据量大,我们可以从以下几个维度进行排查和按需设计:

  1. 并发量不是很大的场景下,针对单表做好设计,建立何时的索引并采取相对简单的轻量级分区设计保证查询检索效率即可。

  1. 单表数据量大,但是特定业务下这张表每日只有一些相对局限的热点数据查询请求,针对这些请求条件建立好表索引,然后借助缓存中间件来存储这些热点数据。

  1. 如果需要保证高并发和高吞吐量,我们则需要借助分库分表来分散并发量和单表体量提升检索性能。

# 分布式架构

# 详解分布式结构模式

此时我们就已经具备了一个性能性能较为出色的分布式系统架构,但是我们所有的业务都耦合在一个应用程序上,无法针对单个原子业务进行管理和优化,甚至说在高并发场景下,一些访问量和体量都比较小的业务会因为一些热点业务导致整体瘫痪,无法对外提供服务。

于是我们会尝试通过圈表并结合实际业务场景针对性的进行业务拆分,将不同的业务部署到不同的服务器上,因为这些应用之间还是存在的关联,相互之间还会存在着调用关系,所以我们还会考虑引入注册中心、配置中心、消息队列等中间件协调应用之间的通信:

# 分布式业务架构流量突增问题

分布式系统架构下势必存在的访问量暴增的特点,假设QPS突增100倍你会怎么处理?一般来说在上文中我们已经针对系统可承受的范围内做了评估并预设了指定数量服务器来承载这些流量,对于突增的流量大部分情况下都可以拒绝掉,以保证部分用户可用以及保证系统能够维稳运行。

对此该问题,一般出现业务流量突增我们必须考虑以下两种情况:

  1. 异常情况:服务被ddos攻击了。
  2. 正常情况:引流或者某些原因导致业务量暴增。

针对第一种情况,我们必须采取相应防护手段处理,例如:

  1. 识别攻击源。在防火墙服务器调整ACL(访问控制列表)阻断这些攻击源。
  2. nginx进行限流
  3. 适当增加服务器通过负载均衡分担流量。
  4. 针对带宽消耗型的攻击,增加带宽适当缓解问题。
  5. 路由器或防火墙启用一些反IP欺骗的功能,保证对所有IP源可见。
  6. 增加对该服务的网络和web流量监控,时刻观察变化。

针对正常的业务场景则考虑从高并发系统角度进行不断拓展优化了,大抵可以从以下几个角度考虑:

  1. 分布式:通过将服务拆分到不同的服务上构成分布式架构,分散管理不同业务的流量压力,进行针对性的优化,同时还能避免单功能导致服务宕机的影响面,也能提升系统的可伸缩性。
  2. 集群部署:通过集群部署分散单业务服务请求的流量,结合负载均衡技术提升服务的吞吐量和响应速度,提升系统性能和可用性。
  3. 缓存:对于热点数据提前缓存,提高程序读写性能和可靠性。
  4. 异步处理:采用异步处理机制,例如消息队列、事件等系统,减少响应耗时、提升系统吞吐量。
  5. 资源预热:将系统常见流量数据提前加载预热,减少请求的等待时间。
  6. 程序优化:针对每个功能代码进行功能优化,例如:异步IO、检索锁粒度提升并发性能、减少循环递归,减少事务的粒度等。
  7. 数据库优化:合理设计数据表索引、字段,以及对于一些需要join查询,我们可以结合场景进行冗余。
  8. 读写分离:大部分场景都是读多写少,所以我们的数据库一般建议采用读写分离的方式,将写请求打到主库,读取请求分散到读服务器上,提升程序并发度和可扩展性,同时即时主库出现故障,从库依然可以提供服务。
  9. 分库分表:为避免慢查询SQL和大量读请求,我们建议采用分库分表分散垂直和水平拆分分散请求流量和单表性能瓶颈。
  10. 通过使用限流、熔断、降级等技术,防止某个组件故障导致系统崩溃的雪崩效用。
  11. 监控:针对各种可能存在的风险点,通过监控建议监控观察,以保证能够及时针对做出调整和观察。

# 削峰填谷的流量控制策略

前几天和朋友谈及一个问题,针对互联网业务,遇到合理的流量在持续徒增,对应10w的qps请求全部打到原本只能承受5w qps的上游服务导致业务瘫痪要如何处理?

针对这种问题我们还是需要剖析一下这个问题,本质上就是让有限的资源承受了无法抵抗的流量冲击,针对这种问题常见的解决思路一般是:

  1. 流量是否正常,对于不正常的流量需要通过网络安全手段进行限制
  2. 上游服务是否存在优化空间,是否可以提升程序吞吐量
  3. 是否可以增加硬件资源分散流量

在明确上述方案无果后,我们就需要针对流量进行整顿了,最常见的手段就是将流量削减平整,保证上游服务能够准确处理该流量,结合目前的主流方案也就是添加一个可靠消息中间件,这也就是我们常说的削峰填谷:

# 关于服务限流的探讨

为什么针对流量需要进行特定的服务限流,增加服务器承载更多的流量不是更好吗?

原则上服务优先,针对这个问题要从以下两个角度考虑:

  1. 服务好客户没有错,但是我们要知晓客户是否是正常客户,请求突增的原因不一定是业务量上涨,也可能是被攻击了。
  2. 突发流量:出问题一般是由于突发流量,例如我们系统最高qps为1000,但是突发流量是远远高于这个数的,如果没有提前预测不做限流,服务可能直接被打卦了。
  3. 限流本质要做的就是自我保护,是系统的最后一道防线,只有通过限流保证服务器正常,然后在针对性排查流量来源,针对性扩容。

# 分布式微服务

# 详解分布式微服务架构特点

很多读者对于分布式和微服务两个概念会有所混淆,实际上微服务相较于分布式架构做了更精细的切割,通过拆分成精细的子模块保证模块之间的高内聚低耦合,让每个模块独立存在并拆解到不同团队进行专门的维护,各个模块按照自己协定开发进行开发,公开各自的协议实现和标准,某些热点模块也可以类似于分布式架构一样进行水平拓展,保证高性能和高可用。

在部署架构上,因为微服务拆分原则是分布式架构有所不同,它拆分的目的还包含模块间的解耦和团队自治维护,所以进行模块部署的时候,多个模块以容器化的方式部署在单台服务器,也可以多个模块部署上不同服务器上,相较于分布式架构有着更加灵活的搭配和管理。

总的来说微服务架构相较于分布式架构有着更精细的拆分、有着更独立的自治性和服务异构性等特点:

# 服务拆分后的接口机器预估

微服务架构通过更细粒度的拆分,使之业务维度有着更细粒度的解耦,所以对于特定服务的优化,我们甚至可以是针对到更细粒度的核心接口上,例如我们现在有一个查询接口,按照评估它大约是有5000QPS,经过优化后接口RT为大约是200ms,此时如果我们需要针对该模块进行水平拓展,请问需要增加几台服务器?

基于上述指标,我们首先需要针对单机性能进行大体的预估,首先接口响应实践大约是200ms,按照单台服务器单线程维护来看,每个线程在1s内可以处理5个请求:

完成线程处理能力大体评估之后,我们就需要从处理的维度进行更进一步的评估,假设这个接口CPU处理时间为2ms,而IO等待耗时为150ms,其余时间作为网络读写的耗时(读写redis数据等),这也就意味着一个线程在单位时间内只占用CPU大约10ms,也就是说单个CPU大约可以处理100个线程,也就是每个核心在理想情况下,每秒可以处理500个请求。

我们继续,默认情况下tomcat分配的线程是200,按照当前CPU处理能力每秒可以处理100个线程,所以2个核心即可在单位时间内处理掉这些线程,CPU使用率也不算很高,这个评估是合理的。

所以单机性能的核心计算还是回到了线程上,一共200个线程,每个处理5个请求,所以单机处理能力为1000QPS。

当然如果我们允许更高的CPU使用率,就可以开始使用更多的线程更高的QPS。

所以在理想情况下3000qps只需要3台服务器即可,但是我们的理论指标是基于所有理想情况,并没有考虑到应用GC情况、网络组件通信效率等综合考量做增减。

# 微服务界面长耗时问题

通过微服务拆解,我们得到了更加灵活组合式实现高性能、高吞吐、高可用的软件架构,假设线上出现用户进入缓慢,监控服务器cpu和缓存没有什么压力,可以从哪些方面排查?

针对线上服务器多节点分布,但是在cpu和缓存没有任何压力瓶颈的情况下出现访问速度缓慢,我们大体可以从以下几个角度考虑:

  1. 明确是否是用户端浏览器、网络问题。
  2. 检查服务器网络带宽等,明确是否存在网络延迟丢包或者带宽限制。
  3. 是否使用CDN,也有可能是CDN某个节点有问题导致用户资源加载慢。
  4. 检查复杂均衡是否正确,用户请求是否打到有问题的节点上。
  5. 查看期间是否存在进行耗时的GC。
  6. 查看应用此时是否存在耗时的IO操作。

# 小结

我是 SharkChili ,Java 开发者,Java Guide 开源项目维护者。欢迎关注我的公众号:写代码的SharkChili,也欢迎您了解我的开源项目 mini-redis:https://github.com/shark-ctrl/mini-redis (opens new window)。

为方便与读者交流,现已创建读者群。关注上方公众号获取我的联系方式,添加时备注加群即可加入。

# 参考

《分布式架构原理与实践 (崔皓) 》

场景题:4C8G 16台 和 8C16G8台,不考虑成本的情况怎么选? :https://blog.csdn.net/weixin_74770732/article/details/143839908 (opens new window)

线程池最优线程数计算公式 :https://blog.csdn.net/wangnanwlw/article/details/142756911#:~:text=线程数 %3D CPU核数 * CPU利用率 * (1 %2B,其中: 这个公式考虑了以下因素: CPU核数:更多的核心可以支持更多的并发线程。 CPU利用率:考虑到系统开销,通常不会将CPU利用到100%。 如果程序是计算密集型 (W%2FC接近0),那么线程数约等于CPU核数。 如果程序是I%2FO密集型 (W%2FC较大),则可以设置更多的线程数。 (opens new window)

搞懂MySQL分区 :https://www.cnblogs.com/helios-fz/p/13671682.html (opens new window)

软件开发中的上游和下游:https://segmentfault.com/a/1190000041894011 (opens new window)

编辑 (opens new window)
上次更新: 2026/03/26, 01:05:31
基于内网的Jenkins整合gitlab综合方案简记
SpringBoot集成Prometheus与Grafana监控

← 基于内网的Jenkins整合gitlab综合方案简记 SpringBoot集成Prometheus与Grafana监控→

最近更新
01
基于EasyExcel实现高效导出
03-25
02
从开源框架中学习那些实用的位运算技巧
03-25
03
SpringBoot集成Prometheus与Grafana监控
03-25
更多文章>
Theme by Vdoing | Copyright © 2025-2026 Evan Xu | MIT License | 桂ICP备2024034950号 | 桂公网安备45142202000030
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×
×