Hi, 我是 W10N

这里收集整理了一些技术资料(大部分是转载的,经常用到的有整理过),希望能帮助到有需要的人。

JDK 17 升级到 JDK 21 的变更汇总

JDK 17 到 JDK 21 跨越了 JDK 18、19、20 三个非 LTS 版本。本文汇总这四个版本引入的重要变更,重点关注 breaking change 和需要主动迁移的部分。 JDK 18(2022 年 3 月) Breaking Change UTF-8 成为默认字符集(JEP 400) 这是 17 → 21 迁移中最常见的隐性 breaking change。JDK 18 起,Charset.defaultCharset() 固定返回 UTF-8,不再跟随操作系统区域设置。 受影响的场景: new String(bytes) — 未指定编码,依赖平台默认值 new FileReader(file) — 未指定编码 System.out.println() 输出非 ASCII 字符 读写文件时未显式指定编码 修复方式:所有涉及字节/字符转换的地方显式指定 StandardCharsets.UTF_8。 // 修复前(行为依赖平台) String s = new String(bytes); new FileReader(file); // 修复后(行为确定) String s = new String(bytes, StandardCharsets.UTF_8); new FileReader(file, StandardCharsets.UTF_8); 新特性 JEP 408: 简单 Web 服务器 — jwebserver 命令,用于本地静态文件服务,开发调试用 JEP 413: Java API 文档中的代码片段(@snippet 标签) JEP 416: 使用方法句柄重新实现反射核心(内部实现变更,API 不变) JEP 417: 向量 API(第三次孵化) JEP 418: 互联网地址解析 SPI — 可插拔的地址解析器,InetAddress 行为可自定义 JEP 419: 外部函数与内存 API(第二次孵化) JEP 420: switch 模式匹配(第二次预览) JEP 421: 废弃 Finalization — finalize() 正式废弃,标记 forRemoval JDK 19(2022 年 9 月) 重要预览/孵化特性 JEP 425: 虚拟线程(第一次预览) — Project Loom 的核心成果,轻量级线程 JEP 428: 结构化并发(孵化) — 将多个并发任务作为一个工作单元管理 JEP 405: Record 模式(第一次预览) — 在 instanceof 和 switch 中解构 record JEP 427: switch 模式匹配(第三次预览) JEP 424: 外部函数与内存 API(预览) — 从孵化升为预览 JEP 426: 向量 API(第四次孵化) 移除/废弃 Thread.stop(boolean) 已移除(Thread.stop() 无参版本在后续版本移除) JDK 20(2023 年 3 月) 重要预览/孵化特性 JEP 436: 虚拟线程(第二次预览) JEP 437: 结构化并发(第二次孵化) JEP 432: Record 模式(第二次预览) JEP 433: switch 模式匹配(第四次预览) JEP 434: 外部函数与内存 API(第二次预览) JEP 438: 向量 API(第五次孵化) JEP 429: 作用域值(孵化) — 替代 ThreadLocal 的不可变线程绑定值 JDK 21(2023 年 9 月,LTS) Breaking Change Thread.stop() 等方法实际抛出异常 ...

2026-05-13 · 3 min · 578 words · -

Spring MVC

Spring MVC 是 Spring Framework 中负责处理 HTTP 请求的 Web 框架,实现了 MVC 设计模式。它是一个功能模块,而非独立框架。 Spring MVC 与 Spring Boot 的关系 这两者经常被混淆,理清层次是关键。 层次关系 Spring Framework(基础框架) └── Spring MVC(Web 层模块,属于 Spring Framework 的一部分) Spring Boot(构建在 Spring Framework 之上的脚手架/工具) └── spring-boot-starter-web(包含 Spring MVC + 内嵌 Tomcat + Jackson) Spring MVC 是 Spring Framework 中负责处理 HTTP 请求的 Web 框架,实现了 MVC 设计模式。它是一个功能模块。 Spring Boot 是一个构建工具/脚手架,它并不替代 Spring MVC,而是让配置 Spring MVC(以及其他模块)变得更简单。 对比:传统 Spring MVC vs Spring Boot 方面 传统 Spring MVC Spring Boot 配置方式 XML(web.xml、applicationContext.xml)或 Java Config 自动配置,几乎零 XML 部署方式 打包为 WAR,部署到外部 Tomcat 打包为可执行 JAR,内嵌 Tomcat 依赖管理 手动指定每个依赖及版本,容易版本冲突 Starter 统一管理,版本经过验证 启动入口 通过 Servlet 容器启动 @SpringBootApplication 主类 + main() 方法 学习曲线 较陡,需理解大量 XML 配置 较平,约定优于配置 底层请求处理链路 无论是传统 Spring MVC + WAR,还是 Spring Boot + JAR,处理 HTTP 请求的调用链从未改变: ...

2026-05-12 · 3 min · 587 words · -

POSA1 架构模式

POSA1 是什么 《Pattern-Oriented Software Architecture, Volume 1: A System of Patterns》(简称 POSA1),1996 年出版,作者为 Frank Buschmann、Regine Meunier、Hans Rohnert、Peter Sommerlad、Michael Stal。 POSA1 关注的是架构模式(Architectural Patterns),粒度比 GoF(1994)的 23 种设计模式更大——GoF 解决的是类与对象之间如何协作,POSA1 解决的是整个系统应该如何组织。 GoF(1994) POSA1(1996) 模式级别 对象/类设计 系统/架构 典型模式 Strategy、Observer、Chain of Responsibility Pipes & Filters、Layers、Broker 解决问题 类之间如何协作 整个系统如何组织 POSA1 中的主要模式 Layers(分层) 将系统分解为若干层,每层只依赖下层,对上层屏蔽实现细节。典型实现:OSI 网络模型、TCP/IP 协议栈、三层架构(表现层 / 业务层 / 数据层)。 Pipes and Filters(管道-过滤器) 将数据处理拆分为一系列独立的 Filter,每个 Filter 负责单一转换,通过 Pipe 传递数据。整个系统是可组合的处理管道。 特征: 每个 Filter 独立,不依赖其他 Filter 的内部状态 Filter 可以任意组合、复用、替换 任何一个 Filter 可以短路,中断后续处理 经典实现: ...

2026-05-12 · 1 min · 141 words · -

Spring Security

SecurityFilterChain SecurityFilterChain 是 Spring Security 的核心抽象,代表一条作用于 HTTP 请求的安全过滤器链。每个进入应用的请求都会依次经过链中的若干 Filter,完成认证(Authentication)、授权(Authorization)、CSRF 防护、会话管理等工作。 底层机制:从 Servlet Filter 到 Spring Security Servlet 规范本身有 Filter 接口和 FilterChain 接口。Spring Security 通过以下两层代理接入这套机制: DelegatingFilterProxy:在 Servlet 容器(Tomcat)层面注册的 Filter,作用是把请求桥接到 Spring 容器中的 Bean。它本身不做安全逻辑,只是一个"入口代理"。 FilterChainProxy:Spring 容器中的真正实现,也是一个特殊的 Filter。它持有所有注册的 SecurityFilterChain Bean,收到请求后,按顺序匹配第一条能处理该 URL 的链,然后依次执行链中的每个 Filter。 HTTP 请求 → Tomcat FilterChain → DelegatingFilterProxy(Servlet Filter,桥接到 Spring) → FilterChainProxy(Spring Bean) → SecurityFilterChain 1(匹配 /api/**) UsernamePasswordAuthenticationFilter BearerTokenAuthenticationFilter ExceptionTranslationFilter AuthorizationFilter ... → SecurityFilterChain 2(匹配 /**) ... 定义一个 SecurityFilterChain @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain apiSecurityChain(HttpSecurity http) throws Exception { http .securityMatcher("/api/**") // 只匹配 /api/** 路径 .authorizeHttpRequests(auth -> auth .requestMatchers("/api/public/**").permitAll() .anyRequest().authenticated() ) .sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 无状态,适合 JWT ) .csrf(csrf -> csrf.disable()); // REST API 通常关闭 CSRF return http.build(); } } HttpSecurity 是 SecurityFilterChain 的构建器,调用 .build() 后生成链实例并注册为 Bean。 ...

2026-05-12 · 2 min · 358 words · -

Lombok

Lombok 是一个 Java 编译器插件,通过注解在编译期自动生成 getter/setter、构造器、equals/hashCode、toString、Builder 等样板代码,让源文件保持简洁。 发音:来自印度尼西亚龙目岛(Lombok Island),读作 LOM-bok,重音在第一个音节。 出现时间:2009 年首次发布,比 Spring Boot(2014 年)早了五年,与 Spring 没有直接关系,是独立的 Java 工具。 原理:利用 Java 编译器的注解处理器(Annotation Processing)在 javac 编译时修改语法树,将生成的方法直接写入 .class 字节码,源文件里没有这些方法但编译产物里有。IDE 需要安装 Lombok 插件才能识别生成的方法。 解决了什么问题 Java 要求显式写大量与业务无关的样板代码,一个普通的 JavaBean 需要: // 不用 Lombok:一个 User 类要写几十行 public class User { private Long id; private String name; private String email; public User() {} public User(Long id, String name, String email) { ... } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } // ... 还有 equals / hashCode / toString ... } 用 Lombok: ...

2026-05-12 · 2 min · 392 words · -

Spring IoC 与依赖注入

IoC(Inversion of Control,控制反转)是 Spring 的核心机制。它把"创建和管理对象"的控制权从应用代码交给 Spring 容器,应用代码只需声明依赖,容器负责提供。 IoC 的具体实现方式叫 DI(Dependency Injection,依赖注入),容器通过构造器、字段或 Setter 方法将依赖对象注入进来。 IoC 解决了什么问题 传统写法中,对象自己负责创建依赖: // 传统写法:自己创建依赖,紧耦合 public class OrderService { private UserDao userDao = new UserDaoImpl(); // 自己 new,换实现要改代码 private EmailService email = new EmailService("smtp.example.com", 465); } 这带来三个问题: 紧耦合:OrderService 直接依赖具体实现类,换实现必须修改源码 难以测试:无法替换成 Mock 对象,单元测试困难 对象生命周期散乱:每次 new 都产生新对象,无法复用单例 IoC 写法: // IoC 写法:声明需要什么,容器负责提供 @Service public class OrderService { @Autowired private UserDao userDao; // 容器注入,不关心具体实现 @Autowired private EmailService emailService; } 切换实现时只需修改容器配置,OrderService 代码本身不用动。 ...

2026-05-12 · 3 min · 432 words · -

企业应用架构模式

什么是企业应用架构模式 企业应用架构模式(Patterns of Enterprise Application Architecture,简称 PoEAA) 由 Martin Fowler 在 2002 年出版的同名书中系统整理,专门解决企业级应用中反复出现的架构问题。 它与 GoF 23 种设计模式的区别: GoF 设计模式(1994) 企业应用架构模式(2002) 关注层面 对象级别,类与类之间的协作 应用架构级别,层与层之间的设计 典型问题 如何创建对象、如何解耦行为 如何组织 Web 层、如何访问数据库、如何处理并发 典型模式 Factory、Observer、Strategy Front Controller、Repository、Unit of Work 两套模式不冲突,可以同时使用。 Web 表现层模式 Front Controller(前端控制器) 所有 HTTP 请求通过单一入口,集中处理身份验证、日志、权限等横切关注点,再路由到具体处理器。 所有请求 → Front Controller → Dispatcher → 具体 Handler Spring MVC 实现:DispatcherServlet 是标准的 Front Controller 实现,映射到 / 接收所有请求,通过 HandlerMapping 路由到对应的 @Controller 方法。 详见 Front Controller Pattern。 Page Controller(页面控制器) 每个页面或 URL 对应一个独立的控制器类。原始 Servlet 就是这种模式——/users 对应 UsersServlet,/orders 对应 OrdersServlet。 ...

2026-05-11 · 1 min · 190 words · -

Spring Boot

Spring Boot 是什么 Spring Boot 是 Pivotal (现为 VMware/Broadcom)在 2014 年推出的框架,建立在 Spring Framework 之上,目标是简化整个 Spring 生态的开发、配置和部署。它不只是简化 Spring MVC,同样简化了 Spring Data(数据库访问)、Spring Security(认证授权)、Spring Messaging(消息队列)等全家桶的配置。 核心理念是 “约定优于配置”(Convention over Configuration):框架提前定好"默认约定",只要遵循这些约定,就不需要写任何配置;只有想偏离默认行为时,才需要显式配置。 例如,classpath 里有 spring-boot-starter-web,Spring Boot 就约定你要启动一个 Web 服务,自动完成:注册 DispatcherServlet、内嵌 Tomcat 监听 8080 端口、注册 Jackson 用于 JSON 序列化。你什么都不写,java -jar app.jar 就能跑起来。需要覆盖默认行为时,只在 src/main/resources/application.yml 中写偏离默认值的部分: server: port: 9090 # 只需声明偏离默认值的配置 也可通过命令行参数临时覆盖:java -jar app.jar --server.port=9090,优先级高于 application.yml。 出现背景 Spring Boot(2014)与微服务架构的兴起同期出现。2014 年 Martin Fowler 发表了微服务架构的奠基性文章,微服务要求每个服务独立部署、快速启动、进程隔离。传统的 WAR 包 + 外部 Tomcat 的部署方式与这一需求存在明显矛盾,Spring Boot 正是为了解决这一问题而生。 ...

2026-05-11 · 8 min · 1557 words · wiloon

Cypress vs Playwright: E2E 测试框架对比

概述 Cypress 和 Playwright 是目前最主流的两个 E2E(端到端)测试框架。两者都能模拟真实用户操作来测试 Web 应用,但在架构、能力和适用场景上有明显差异。 核心对比 维度 Cypress Playwright 开发商 Cypress.io Microsoft 首发年份 2017 2020 语言支持 JS / TS JS / TS / Python / Java / C# 浏览器支持 Chrome、Firefox、Edge、Electron Chrome、Firefox、Safari (WebKit)、Edge 移动端浏览器 不支持 支持(模拟移动设备) 多标签页 有限支持 原生支持 iframe 支持 受限 完整支持 并发执行 收费云服务 / 第三方插件 内置,免费 API 测试 支持 支持(更完整) 组件测试 成熟 实验性 架构差异 Cypress Cypress 运行在浏览器内部,测试代码与应用代码共享同一个 JavaScript 运行时。这一设计带来了极低的延迟和实时调试能力,但也造成了一些限制: 历史上不支持跨域(cross-origin)场景(v12 起已大幅改善) 同一时间只能操作一个标签页 不支持 Safari / WebKit Playwright Playwright 运行在浏览器外部,通过 Chrome DevTools Protocol(Chrome/Edge)和各浏览器原生协议(Firefox、WebKit)远程控制浏览器。这种架构更接近真实用户操作,且: ...

2026-05-11 · 2 min · 244 words · -

网站访问统计:Umami + Cloudflare Web Analytics

背景 Hugo 博客(PaperMod 主题)默认没有访问统计。为了了解谁在访问、访问了哪些页面,选择同时接入两套统计: Umami:隐私友好,无 cookie,数据存储在 Umami 服务器 Cloudflare Web Analytics:与 Cloudflare 基础设施集成,数据存储在 Cloudflare 两者不冲突,可以同时运行,便于对比数据。 Umami 特点 无 cookie,无跨站追踪,不需要 GDPR 同意弹窗 免费 Hobby 计划:100K 事件/月,3 个站点,6 个月数据保留 地理位置精度:国家级别 统计维度 页面浏览量(PV)、独立访客数(UV) 每次会话浏览页数、跳出率、平均停留时间 引荐来源、UTM 参数 国家/地区、操作系统、浏览器、设备类型 各页面访问量排行 接入步骤 注册 cloud.umami.is Settings → Websites → Add website,填入域名 获取 <script> 标签 Hugo PaperMod 接入方式 PaperMod 主题提供了 extend_head.html 扩展点,在项目根目录创建: layouts/_partials/extend_head.html 内容: <script defer src="https://cloud.umami.is/script.js" data-website-id="YOUR_WEBSITE_ID"></script> 将 YOUR_WEBSITE_ID 替换为 Umami 后台生成的 ID。 Cloudflare Web Analytics 特点 同样无 cookie,隐私友好 数据不设过期限制(免费) 地理位置精度:城市级别(比 Umami 更精细) Automatic setup vs Manual setup 方式 条件 操作 Automatic setup 域名 DNS 托管在 Cloudflare(橙云代理) 后台开关,无需改代码 Manual setup 任意域名 手动添加 <script> 标签 如果域名 DNS 不在 Cloudflare 托管,只能用 Manual setup。 ...

2026-05-10 · 1 min · 175 words · W10N

iptables basic

iptables basic iptables 是 Linux 内核集成的 IP 信息包过滤系统。该系统用于在 Linux 系统上控制 IP 数据包过滤和防火墙配置 iptables 操作的是 2.4 以上内核的 netfilter。所以需要 linux 的内核在 2.4 以上。其功能与安全性远远比其前辈 ipfwadm, ipchains 强大,iptables大致是工作在OSI七层的二、三、四层,其前辈ipchains不能单独实现对tcp/udp port以及对mac地址的的定义与操作 iptables-nft iptables vs. iptables-nft https://developers.redhat.com/blog/2020/08/18/iptables-the-two-variants-and-their-relationship-with-nftables#the_iptables_rules_appear_in_the_nftables_rule_listing iptables 包含4个表,5个链 其中表是按照对数据包的操作区分的,链是按照不同的Hook点来区分的,表和链实际上是netfilter的两个维度. 4个表: filter, nat, mangle, raw,默认表是 filter (没有指定表 ( -t ) 的时候就是filter表) 。 表的处理优先级: raw>mangle>nat>filter 4 个表 filter: 一般的过滤功能, 这是默认的表,包含了内建的链 INPUT (处理进入的包)、FORWARD (处理通过的包) 和OUTPUT (处理本地生成的包) 。 nat: 用于nat功能 (端口映射,地址映射等),对应的链: PREROUTING (修改到来的包)、OUTPUT (修改路由之前本地的包) 、POSTROUTING (修改准备出去的包) ,centos6没有input链,centos7 有 input 链。 mangle: 用于对特定数据包的修改, 对应的链: PREROUTING (修改路由之前进入的包) ,input, OUTPUT (修改路由 IPTABLES 之前本地的包), forward, postrouting raw: 优先级最高,设置raw时一般是为了不再让iptables做数据包的链接跟踪处理,提高性能 5 个链: PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING PREROUTING: 数据包进入路由表之前 INPUT: 通过路由表后目的地为本机 FORWARD: 通过路由表后, 目的地不为本机 OUTPUT: 由本机产生, 向外转发 POSTROUTIONG: 发送到网卡接口之前 iptables 规则的语法 iptables [-t table] COMMAND chain CRETIRIA -j ACTION -t table : 3个filter nat mangle COMMAND: 定义如何对规则进行管理 chain: 指定你接下来的规则到底是在哪个链上操作的,当定义策略的时候,是可以省略的 CRETIRIA:指定匹配标准 -j ACTION :指定如何进行处理 iptables [-t table] COMMAND chain CRETIRIA -j ACTION iptables [-t table] -[AD] chain rule-specification [options] iptables [-t table] -I chain [rulenum] rule-specification [options] iptables [-t table] -R chain rulenum rule-specification [options] iptables [-t table] -D chain rulenum [options] iptables [-t table] -[LFZ] [chain] [options] # 创建新的链 iptables [-t table] -N chain iptables [-t table] -X [chain] iptables [-t table] -P chain target [options] iptables [-t table] -E old-chain-name new-chain-name # 创建链 iptables -t mangle -N chain0 指定链 iptables -t filter -L FORWARD nf_conntrack iptalbes 会使用 nf_conntrack 模块跟踪连接,而这个连接跟踪的数量是有最大值的,当跟踪的连接超过这个最大值,就会导致连接失败。 通过命令查看 ...

2026-05-10 · 8 min · 1523 words · -

IPv6 地址类型与配置

GUA(Global Unicast Address,全局单播地址) GUA 是 IPv6 中可在公网上路由的地址类型,相当于 IPv4 的公网 IP。 地址格式 GUA 地址以 2000::/3 开头,即前 3 位为 001,实际分配中几乎所有 GUA 地址都以 2 或 3 开头。 | 48 位全局路由前缀 | 16 位子网 ID | 64 位接口 ID | 全局路由前缀(Global Routing Prefix):由 ISP 或 RIR 分配,用于全球路由 子网 ID(Subnet ID):由站点管理员划分子网 接口 ID(Interface ID):标识同一子网内的主机,通常通过 SLAAC(EUI-64)或随机生成 典型示例 2001:0db8:85a3:0000:0000:8a2e:0370:7334 其中 2001:0db8::/32 是文档示例专用前缀(RFC 3849),不会在公网上实际路由。 与 IPv4 公网 IP 的对比 特性 IPv4 公网 IP IPv6 GUA 全球可路由 ✓ ✓ 地址数量 约 43 亿 约 $3.4 \times 10^{38}$ NAT 需求 通常需要 通常不需要 分配方式 ISP 分配(动态/静态) ISP 分配前缀,设备自动生成 常见 GUA 前缀段 ...

2026-05-09 · 3 min · 428 words · -

关于本站/关于我

本站主要是个人使用的读书笔记,因为早期使用了 Wordpress 所以申请了域名,转到 Github + Markdown 后也保留了公开访问, 本人使用频率比较高的技术文档都有仔细整理和验证过,希望能帮助到有需要的同学。当然……也有大量的转载未整理的内容,在不断完善整理中…… 收集综合症/转载 基本上是我接触过的知识的一个集合 大部分内容是转载的 70%+ 一般第一次接触的知识会找质量比较好的或者能解决问题的文档收集进来 有一部分原因是防止源站消失(比如……已经消失的一个站点http://www.yining.org/2010/05/04/http-get-vs-post-and-thoughts/),还有方便查找,省掉重新 Google 的过程 有仔细读过的会修正 typo 日常遇到问题会逐渐整理,也会补充其它引用来源 有明显整理痕迹的都是仔细读过的,比如有段落标题,有代码语法高亮 会有合并摘抄 一个文档可能有多个引用来源,对同一个问题也有可能有相互矛盾的来源,会补充验证后的结果 前期不太注意知识共享协议,最近在有意识的识别有共享协议的文档并按协议转载 没有明显的知识共享协议的文档会逐渐转移到私有仓库 Obsidian + AWS S3 转载内容的 Author 会标记为 “-” 会不定期删除本人使用频率低的内容,比如早期接触过的 ASP.net, Wordpress, PHP…… 本站点对应的 GitHub 仓库:https://github.com/wiloon/blog 转载内容有侵权可以随时联系我删除 整理过的 在转载的基础上整理过的 记录了一部分常用的命令 平时经常使用的工具、命令、脚本,使用过程中遇到问题,解决问题的过程中会频繁修改,会补充命令的示例 一般会有语法高亮 有段落标注 可能有 N 个引用来源 以 Tag(remix) 方式标记整理过的转载内容 – 逐渐整理中,要花些时间从收集的文档里捞出来。 日常记录 少量的原创或原创比例比较高的文档 日常遇到的问题和解决过程 以 Tag(original) 方式标记 – 逐渐整理中,要花些时间从收集的文档里捞出来。 Author 会标记为 “w1100n” Blog 实现 Markdown GitHub GitHub Action Hugo PaperMod theme Cloudflare Pages 关于我 王越 ...

2026-05-09 · 1 min · 198 words · W10N

软件工程师的能力与素质

技术能力 扎实的基础:数据结构、算法、操作系统、网络、数据库原理 系统设计能力:能权衡取舍,设计可扩展、可维护的系统 调试与排障:能快速定位问题,善用工具(profiler、日志、监控) 阅读代码:能快速理解陌生代码库,而不只是写代码 持续学习:技术演进快,能主动跟进新技术而不盲目追新 工程素养 写可读代码:代码是写给人看的,命名清晰,逻辑直白 测试意识:主动写测试,而不是依赖 QA 兜底 版本控制规范:清晰的 commit message,合理的分支策略 文档意识:在合适的地方写合适的文档(不是每行都注释) 安全意识:代码层面的 OWASP 意识,不把安全留给"以后再说" 协作能力 沟通清晰:能向非技术人员解释技术问题,能在 code review 中表达具体意见 估时准确:能分解任务,给出相对可靠的工时估算 主动暴露问题:遇到 blocker 早说,而不是默默卡住 思维方式 系统思维:看到局部问题时,能思考对整体的影响 务实:不追求完美设计,在"够好"和"完美"之间找到正确点 ownership:对自己负责的东西有主人翁意识,上线后持续关注 简单优先:倾向于简单方案,而不是过度设计;代码越少越好 软技能 抗压与专注:在复杂问题面前不慌,能保持有效的思考 接受反馈:对 code review 意见开放,不把技术讨论变成自我防卫 好奇心 好奇心是一个底层驱动力(meta-driver),不是和其他素质并列的加分项,而是在它们之上的一层——其他很多素质都可以被好奇心解释: 为什么愿意深挖 bug?→ 对根因有好奇心 为什么写好测试?→ 对"这段代码真的对吗"有好奇心 为什么沟通顺畅?→ 对同事的想法和 enduser 的真实需求有好奇心 好奇心不只是对新技术的好奇,它覆盖技术、协作、产品三个维度: 好奇心的方向 驱动的行为 对新技术 主动学习,不等培训 对异常日志 追根溯源,不绕过问题 对业务逻辑 理解 why,不只是 how 对同事的想法 真正倾听,不是等自己开口 对 enduser 产品感,不只是功能完成度 没有好奇心的工程师可以把当前的工作做得"够用",但很难做到深入——他们写的代码能跑,但不理解为什么。 好奇心本身还不够,它需要配上自律和落地能力。有些人什么都好奇,但浅尝辄止,或者永远在学新东西却从不完成一件事——这是好奇心失控的版本。 更完整的表述是:有边界的好奇心——对核心领域深挖,对周边领域保持开放,但不被新鲜感分散焦点。 好奇心 vs 好胜心 很多工程师有强烈的好胜心——想赢、想证明自己——但好奇心不足。他们学新东西是为了"会",不是真的想搞懂。这两种人外表相似,但遇到真正难的问题时会分叉:好胜心驱动的人倾向于绕过难点或表演能力,好奇心驱动的人会停下来真正弄清楚。 ...

2026-05-09 · 1 min · 117 words · -

ping command, fping

ping command, fping ping6 ping6 是用于测试 IPv6 网络连通性的工具,功能与 ping 相同,但基于 ICMPv6 协议。 使用 ICMPv6 Echo Request/Reply 报文 目标地址为 IPv6 地址(如 ::1、2001:db8::1)或支持 IPv6 的域名 在现代 Linux 系统中,ping 已整合 IPv6 支持,可直接用 ping -6 替代 ping6 # 测试本地 IPv6 回环 ping6 ::1 # 等价写法(现代系统) ping -6 ::1 # ping 链路本地地址时需指定网络接口(fe80:: 开头的地址必须指定接口) ping6 -I eth0 fe80::1 # 指定发送次数 ping6 -c 4 2001:4860:4860::8888 主要选项与 ping 基本相同,如 -c(次数)、-i(间隔)、-s(包大小)、-I(指定接口)。 options -s<数据包大小>:设置数据包的大小; -M hint 设置MTU(最大传输单元)分片策略。 可设置为: ‘do’:禁止分片,即使包被丢弃; ‘want’:当包过大时分片; ‘dont’:不设置分片标志(DF flag); install # ubuntu apt install iputils-ping # archlinux install fping pacman -S fping windows 长 ping ping 192.168.1.100 -t 指定网络设备 ping -c 1 -I veth0 192.168.3.102 同时显示统计信息 fping -l google.com 什么是 ping PING (Packet Internet Grope),因特网包探索器,用于测试网络连接量的程序。Ping发送一个ICMP回声请求消息给目的地并报告是否收到所希望的ICMP回声应答。 ...

2026-05-08 · 2 min · 382 words · -

drill, dns tool, dig/drill, dnsutils to ldns dig -> dirll

drill, dns tool, dig/drill, dnsutils to ldns dig -> dirll drill if you can, dig if you have to, nslookup if you must https://imdjh.github.io/toolchain/2015/10/07/drill-if-you-can-dig-if-you-have-to.html # install drill ## macOS brew install ldns ## aws linux dnf install ldns-utils ## archlinux sudo pacman -S ldns # ubuntu sudo apt install ldnsutils # alpine apk add drill # install dig ## cenos yum install bind-utils # DNS 解析跟踪 dig +trace wiloon.com dirll -T wiloon.com drill -TD wiloon.com drill wiloon.com @192.168.50.1 drill wangyue.dev NS dig,其实是一个缩写,即Domain Information Groper。 ...

2026-05-08 · 1 min · 206 words · -

curl command

curl command curl [kɜrl] options --version, print version -s, --silent, 不显示下载进度, 不显示 error message -S, --show-error 在使用 -s 时, 打印 curl error message -C, --continue-at, 断点续传 -o, --output <file>, write output to <file> instead of stdout --connect-timeout <fractional seconds>, 建连接超时, 比如 tcp 三次握手 -m, --max-time <fractional seconds>, 单位: 秒, 可以用小数 0.5 代表 500ms, 传输超时, 比如 http 请求发送之后长时间没有响应, tcp 的 ack 收到了, 但是长时间没收到 http response. -G/--get 以 get 的方式来发送数据 -i, --include 输出时包括 protocol 头信息, 显示 response header, 例如: HTTP/1.0 200, Content-Type: text/plain -v, verbos -N, Disables the buffering of the output stream -I, --head 只返回头信息, 比如 FTP 服务器只返回文件大小. -H, --header LINE Custom header to pass to server (H) -d, --data # DATA HTTP POST data, 如果使用 -d 命令,curl 会以 application/x-www-url-encoded 格式上传参数。 从文件中读取数据 -d @/path/to/foo.json -b, --cookie <data|filename>, 发送请求时附带 cookie。可以直接传入 cookie 字符串,或从文件中读取 cookie --retry, 重试次数 -F curl 会以 multipart/form-data 的方式发送 POST 请求。-F 以 key=value 的形式指定要上传的参数,如果是文件,则需要使用 key=@file 的形式。 -k, --insecure flag to skip certificate validation. -L, --location: 追踪重定向, 如果服务器报告请求的页面已移动到其他位置(用 location: header 和 3xx 响应代码),此选项将使 curl 在新位置上重新执行请求。 -x, 参数指定 HTTP 请求的代理 -X, --request <method> Specify request method to use, -X POST, -X PUT -w, 完成请求传输后,使 curl 在 stdout 上显示自定义信息 --cacert, curl 用来验证对端的 CA 证书 -E, --cert, 客户端证书 --key, 客户端私钥 --pass, 客户端私钥的密码 --trace-ascii /tmp/curl.log, 把交互的数据打印到日志里, https 协议也能把明文打在日志里 -tlsv1.x 这个参数并不是说客户端按你指定的tls版本去跟服务端匹配,不是==的关系,是在≥的关系里面desc降序匹配, 比如支持tls1.0/1.1/1.2的Server,客户端分别以--sslv3、--tlsv1.0、--tlsv1.1、--tlsv1.2这些参数去请求,最终的结果都是以--tlsv1.2去建联,这就是我说的“在≥的关系里面desc降序匹配” --tls-max 1.x 这个参数则是限定死了,最大按哪个来, 比如说服务端最大支持到tlsv1.2,客户端限定最大按tlsv1.3来,那最终肯定就是以tlsv1.2建联了;如果服务端不变,我指定客户端以--tls-max 1.1请求,那最终肯定是以tlsv1.1建联了 -f, --fail 快速失败, 在服务器出错时不显示HTTP错误信息, 直接返回 error 22 -w -w 的作用 完成请求传输后,使 curl 在 stdout 上显示自定义信息 格式是一个字符串,可以包含纯文本和任意数量的变量 ...

2026-05-08 · 6 min · 1261 words · -

清空文件

清空文件 在处理服务器磁盘占用时, 比如有比较大的日志文件, 服务还在运行, 所以文件是不能删的, 又因为文件太大了不适合用文本编辑器打开, 比如 vi 之类, 想清空文件就要用以下方法了. BTW: 删除一个正在使用的文件是另外一个问题… wiloon.com/deleteonwrite truncate truncate -s 0 foo.log -s 0 表示将文件大小设置为 0 字节,即清空文件内容。也可以指定其他大小,truncate 从文件末尾截断,保留开头部分(即最旧的数据): truncate -s 100M foo.log # 保留前 100MB(最旧的数据) truncate -s 1G foo.log # 保留前 1GB truncate -s 500K foo.log # 保留前 500KB 如果想保留最新的 100MB,需要用 tail: tail -c 100M foo.log > foo.log.tmp && mv foo.log.tmp foo.log truncate 可被用来将一个文件缩小或者扩展到某个给定的大小。 你可以利用它和 -s 参数来特别指定文件的大小。要清空文件的内容, 则在下面的命令中将文件的大小设定为 0 本命令缩减或扩充指定文件的大小为指定值。 参数所指定的文件如果不存在, 那么该命令会创建这个文件。 如果一个文件的大小比参数指定的大, 那么超出的部分就会被丢弃。 如果一个文件比参数指定的小, 那么文件会被扩充, 并且被扩充的部分 (空洞) 在被读取的时候是字节0。 truncate 函数使用前不需要使用 open 函数打开文件 ...

2026-05-07 · 4 min · 789 words · -

centos basic

centos basic RHEL-based 发行版(CentOS EOL 后) CentOS 在 2024 年完全 EOL 后,主流的 RHEL 下游发行版: 免费的 1:1 RHEL 重建版(CentOS 直接替代): AlmaLinux — 社区驱动,由 CloudLinux 公司支持,目前最流行 Rocky Linux — 由 CentOS 原创始人 Gregory Kurtzer 创建,同样非常流行 商业版: RHEL(Red Hat Enterprise Linux)— 上游源,通过 Red Hat 开发者计划可免费用于最多 16 个生产系统 Oracle Linux — Oracle 的重建版,免费使用,付费支持 其他: CentOS Stream — 仍然存在,但现在是下一个 RHEL 版本的滚动预览(位于 RHEL 上游而非下游),稳定性不如旧版 CentOS AlmaLinux 和 Rocky Linux 都提供迁移工具(almalinux-deploy / migrate2rocky),可将现有 CentOS 系统原地转换。 AlmaLinux AlmaLinux 是 CloudLinux 公司主导的 RHEL 下游发行版。 ...

2026-05-07 · 3 min · 554 words · -

ssh client config

后量子密钥交换警告 连接到旧版 OpenSSH 服务器时,新版客户端(OpenSSH 9.9+)会显示如下警告: ** WARNING: connection is not using a post-quantum key exchange algorithm. ** This session may be vulnerable to "store now, decrypt later" attacks. ** The server may need to be upgraded. See https://openssh.com/pq.html 原因: OpenSSH 9.9 引入了后量子密钥交换算法(如 mlkem768x25519-sha256),当服务端不支持该算法时,连接回退到经典算法,客户端发出警告,提示存在「先存后解」攻击风险。 推荐解决方案: 升级服务端 OpenSSH 到 9.9 或更高版本。 临时屏蔽警告(仅客户端): 如果无法升级服务端,可以在 ~/.ssh/config 中对该主机设置 LogLevel ERROR,屏蔽 WARNING 级别的提示: Host bwg LogLevel ERROR 注意:此方法只是屏蔽了警告输出,并不能消除安全风险,仅适合临时或已评估风险的场景。 SSH 连接的两个阶段 SSH 建立连接时分为两个独立阶段,使用完全不同的密钥: 阶段一:密钥交换(Key Exchange) 在连接建立之初(握手阶段),客户端和服务器通过密钥交换算法协商出一个临时的共享会话密钥,用来加密后续所有通信。这个过程发生在身份认证之前,使用的是 DH/ECDH 等算法(如 curve25519-sha256)。 ...

2026-05-07 · 2 min · 350 words · -