使用 k8s 搭建一个小巧但健全的 cicd 系统
使用 k8s 搭建一个小巧但健全的 cicd 系统引言本文将以作者的个人小项目“易导游”(e-tour) 为例,介绍作者目前正在使用的 cicd 方案。实现了自动更新部署、自动资源调度、日志系统、告警系统等功能。 总览 架构图如上,我们简单介绍一下图中的关键组件: git 仓库:使用 github 私有仓库,利用 github action 实现 push 后自动构建镜像并更新部署的功能 前端:以静态网页的形式托管在阿里云 oss 上。以节省服务器带宽和流量资源。 镜像仓库:在 infra 服务器自建私有镜像仓库。 k8s:主要目的是充分利用多台低配服务器的内存资源。 后端:以容器的形式运行在 k8s 集群中。 中间件:由于 k8s 并不适合运行有状态应用,所以像数据库、loki 这种中间件我放在一台内存足够大的安装了 docker 的服务器上(下文称之为 infra服务器) 监控告警: 优秀国产开源项目 hertzbeat,当检测到服务下线后通过飞书机器人告警。 日志:loki + promtail + grafana 可以查看 k8s 和 infra 中所有容器的标准输出日...
Docker 健康检查的目的、影响和处理
前言网上关于 Docker 的教程往往只会讲容器、镜像、网络、数据卷。对于健康检查往往只是一笔带过:在 Dockerfile 中写一个 HEALTHCHECK 命令,然后看到容器状态变成了 “healthy” 就万事大吉。而对于不健康的容器会造成什么影响、如何处理不健康的容器则很少提及。 如果想充分发挥容器化的健壮性优势,我们就需要认真审视 Docker 提供的健康检查功能。 结论先行Docker 健康检查是保障容器化应用可靠性的关键机制。 不健康的容器会被 Docker 网络自动隔离,但 Docker 本身不会重启它们。我们需要结合 autoheal 工具实现自动重启,并通过 Prometheus + Alertmanager 实现告警监控。 为什么需要健康检查?默认检查方式的局限性默认情况下,Docker 判断一个容器是否存活的方式是通过检测容器内 PID = 1 的进程是否存活(这个进程就是 Dockerfile 的 ENTRYPOINT 中启动的进程)。 这个检查方式非常粗放,因为有时容器已经失去了正常对外提供服务的能力,但是进程仍然存活。例如: 应用陷入死锁...
安全地远程调用Docker API
安全地远程调用Docker API引言你也许知道如何在一台安装了 docker 的机器上创建、停止、删除容器。但是如果发号施令的程序和 docker 不在同一台机器上该怎么办? 本文将介绍如何开启 docker api 远程调用、使用 http api 或者 java sdk 操作另一台机器上的 docker、以及如何确保 docker api 不被他人调用。 开启 docker api 远程调用(简单,不鉴权,快速体验)默认 docker 只允许本机使用docker命令进行操作,我们现在来开启 http api 调用,使得其他机器可以通过 http 请求来操作 docker。 注意:这种方法不对调用者权限进行校验,也就是说互联网上任何一个人都可以控制你的 docker。我们这里为了快速体验临时使用这种方法,长期使用请务必使用 tls 来鉴权,具体方法下文会介绍。 vim /lib/systemd/system/docker.service 编辑 docker 启动命令,找到 service 模块下的 ExecStart=xxx 这一行,在其末尾添加`-H=tc...
轻松配置 https:Let‘s Encrypt 介绍及 Nginx Proxy Manager 实用操作教程
轻松配置 https:Let‘s Encrypt 介绍及 Nginx Proxy Manager 实用操作教程前言一般我们在本地进行 web 开发时用的都是 http 协议,而部署到服务器上之后为了安全都要配置 https,以保证客户端和服务器之间的通信内容得到加密,不会被泄露或篡改。 本文将介绍 https 协议的基本知识(如果有基础可以跳过),以及如何使用 Let’s Encrypt 给你的服务优雅地配置 https。 HTTPShttps本质上还是http,只不过https使用了ssl协议来加密通信内容。 ssl是一个介于TCP和应用层的协议,基于非对称加密算法,用于确保通信双方的交流是私密的 对称加密加密解密使用同一把密钥,但是如何安全地传输这个密钥是个问题 非对称加密有三条原则: 私钥加密,公钥解密 公钥加密,私钥解密 公钥加密,公钥无法解密 服务端给客户端发放公钥,客户端使用公钥加密请求,只有服务端的私钥能解密。服务端使用私钥加密响应,客户端使用公钥解密。 看起来很美好,但这样存在很一个很大的问题:如果有一个坏人(中间人)像下图这样操作,你们的通讯还是会被窃听甚至...
ThreadLocal 内存泄漏问题
前言ThreadLocal 是 Java 中常见的线程隔离工具,但使用不当容易引发内存泄漏。这是一道经典的面试题,涉及 GC、引用类型、线程池等核心知识点。 结论先行使用不当可能导致内存泄漏,但只要及时调用 remove() 就可以避免。 ThreadLocal 的工作原理数据存储结构每个 Thread 对象都有一个类似哈希表的属性 threadLocals,用于存储该线程的私有变量。虽然这个哈希表的 Entry 结构与 HashMap 不同,但可以用哈希表的思想来理解: Key:ThreadLocal 对象的弱引用 Value:实际存储的数据 这样设计的好处是,同一个 ThreadLocal 对象在不同线程的 threadLocals 中对应不同的 value,从而实现了数据隔离。 为什么 Key 使用弱引用?这里最关键的设计是:为什么 Key 是弱引用,而不是 ThreadLocal 对象本身? 考虑这样的场景: 在 Web 服务器中,处理请求的线程通常是池化的,生命周期很长。如果不断有新的 ThreadLocal 对象被添加到线程的 threadLocals 中,而且...
深入理解 Java 虚拟机-学习笔记
前言《深入理解 Java 虚拟机》是周志明老师的又一力作,系统深入地讲解了 Java 虚拟机的内部原理。本文是我阅读本书的学习笔记,涵盖内存管理、垃圾回收、类加载、并发等核心主题。 我所践行的知识整理方法是”将思考具象化”。做技术不仅要去看、去读、去想、去用,更要去说、去写。将自己”认为掌握了的”知识叙述出来,在此过程之中,会挖掘出很多潜藏在”已知”背后的”未知”。 如无特殊说明,本文默认使用 HotSpot 虚拟机(目前最常见的 Java 虚拟机)。 结论先行理解 JVM 的核心在于理解内存管理和垃圾回收机制。 掌握 JVM 内存模型、GC 算法、类加载机制和锁优化策略,是 Java 开发者进阶的必经之路。这些知识不仅能帮助你写出高性能的代码,更能在生产环境中快速定位和解决内存溢出、性能瓶颈等问题。 一、内存区域 Java 内存分为图中几个区域,各个区域的功能如下: 方法区(Method Area)功能:存储常量值、静态变量、类信息(类的元数据)。 特点:所有线程共享。 堆(Heap)功能:存储对象实例。 特点: 所有线程共享 GC 的主要工作区域 通常是 JVM 中最大...
《凤凰架构》阅读笔记
前言《凤凰架构》是周志明老师撰写的一本关于软件架构演进的著作,不仅内容质量极高,而且阅读起来就像小说一样畅快。本书从单体架构到微服务、从 Spring Cloud 到 Kubernetes,系统地讲述了现代软件架构的演进历程和设计哲学。本文记录了书中的核心思想以及我的思考。 结论先行软件架构的本质是管理复杂性。 没有完美的架构,只有适合当前阶段的架构。架构应该随着业务的发展而演进,而不是一开始就追求最先进的技术栈。理解这一点,就理解了架构设计的核心智慧。 一、架构设计的核心理念非业务功能下沉到基础设施问题背景: 业务代码本身已经足够复杂了,如果一些技术性的代码(例如去重、事务、日志、负载均衡、数据同步)也参与进来,就会显得层次不清晰。 解决方案: 把非业务的功能下沉到基础设施层面去实现。例如: 使用 MySQL 的 ON UPDATE CURRENT_TIMESTAMP 来给 updateTime 字段自动赋值,而不是每次写数据时手动赋值 使用数据库的唯一索引来实现去重,而不是在应用层判断 好处: 代码可以专注于业务实现:应用层代码更简洁、更易维护 更可靠:用基础设施来代替...
C语言网络编程
C语言网络编程以前目光只盯着应用层的东西看, 对于c语言和linux等底层知识一直抱着抵触的态度, 现在因为考试不得不恶补这些知识, 才发现这些”原始”的知识所蕴含的设计思想是很有价值的, 它完善着我们的”计算机思维”. 而且本文所涉及到的知识点, 在后端开发岗的面试中也是很常见的考点, 我现在深有体会: “背八股文”和”具体学习过代码”在面试中的表现是完全不同的. 背八股文你只能记住作者所说的内容, 而理解了代码, 你就理解了这种技术的使用场景 socketsocket是一种进程间通信的方式, 和信号, 共享内存等方式不同的是, 这种方式允许两个不同主机上的进程相互通信. 可以理解为socket就是一个插口, 两个主机的插口通过一根管道连接起来, 向socket写入数据就是发送数据, 从socket读取数据就是接收数据. 在linux中, socket以文件的形式存在的, 通过文件描述符(通常用一个整数表示)可以操作socket. socket通信流程图: 字节序网络字节序是一种标准化的字节序,用于在不同主机之间进行数据传输和通信。它采用的是大端字节序(Big-Endian)...
新Java项目开发环境搭建常见问题
新Java项目开发环境搭建常见问题学习/接手新项目的第一件事就是把项目跑起来. 这里记录一下我实习时的一些经验. 以供大家和自己参考. 项目的jdk版本是否正确? (可以通过idea的文件->项目结构->项目设置->项目->SDK查看) maven的运行jre版本是否正确? maven是使用java开发的, 需要依赖于java运行环境 公司可能会给你一份hosts配置文件, 里面是公司自定义的dns规则. 所以当你发现找不到某台机器时, 检查以下hosts文件是否配置正确 公司maven私服的jar包不一定是最新的, 可以尝试把依赖模块的源码拉下来, 然后使用mvn install安装最新代码 如果还是报错, 可以尝试删除idea缓存并重启 到这里, 项目里应该没有飘红的地方了 尝试在本地运行项目(一般项目里都会带一份本地运行的配置文件) 如果运行出错, 并且看日志无法判断原因, 可以问一下同事该项目有没有特殊的jvm参数 如果半小时内自己还没有配置好, 就向同事讲述你的思考和实践, 并请求他帮你配置, 一般几分钟就搞定了...
大三寒假实习收获
大三寒假实习收获我12月份进入正大集团的供应链部门做 Java 实习生. 学到了很多学校里不教但十分必要的知识. 这里做一下总结, 以供各位朋友以及自己未来参考. Communication comes first上班以后才发现, 写代码只占程序员很少一部分的时间. 其余大部分时间被用来沟通. 互相准确地理解对方的意思是一件重要且困难的事情.(不要自卑或懊恼, 这是一个困扰全人类的长久存在的难题) 这对于木讷的工科生来说的确是一个挑战, 但是请尽快适应. 下面是一些常用沟通场景以及经验. 力求准确, 高效. 求助/需要他人做事简要描述自己的情况, 然后说明期望对方做的事. 我曾经犯的一个错误是, 在请教问题时, 把整个思考过程描述一遍. 对方还没听完就迷糊了. 实际上他根本不需要关注那些细节, 我只要把我的思考结论和自己遇到的困难告诉他, 然后表示我需要他帮助找出问题, 就可以了. 领任务mentor在描述任务时, 最好用纸或者电子设备对任务进行一个简单记录, 他说完以后当场用你自己的语言去复述一遍你对任务的理解, 避免因为理解偏差导致南辕北辙. 还要问ddl, 以...














