精选文章
从 Cloudflare 11.18 全局崩溃事件深度剖析:分布式系统中的容错哲学与配置管理实践
Vibe Coding 实战指南:与 AI 共创、保持流畅、持续成长
在Linux上快速创建虚拟机
今天我们来聊一聊,怎么在 KVM 上快速创建虚拟机,首先什么是 KVM 呢?
KVM 的全称是 Kernel-based Virtual Machine,即基于内核的虚拟机。它是一种内建于 Linux 内核的开源虚拟化技术。不过 KVM 只是一个内核模块,单独的 KVM 不能看作一个完整的虚拟机软件。好在 Linux 中还有另一个强大的工具 QEMU。QEMU 提供了完整的虚拟化能力,但原始的 QEMU 只提供软件模拟,性能不是很高。而当我们在 QEMU 中集成 KVM 后,就能获得接近裸机的性能,这正是我们想要的。
Redis8.0 新特性深度解析
1. 摘要
Redis 8.0 的发布标志着其发展历程中的一个重要里程碑,不仅带来了显著的性能提升和功能扩展,更体现了平台战略层面的重新定位。此版本最引人注目的变化包括:将先前独立的 Redis Stack 功能(如 JSON、时间序列、概率数据结构及查询引擎)整合进核心,统一命名为 Redis Open Source;引入全新的 Vector Set 数据结构(目前处于 Beta 阶段),显著增强了其在人工智能(AI)和机器学习(ML)领域,特别是向量相似性搜索方面的能力 ;实施了超过 30 项性能优化,涵盖命令延迟、吞吐量、复制效率和查询处理能力等多个维度 ;以及在许可模式上做出的重大调整,在保留原有 RSALv2 和 SSPLv1 的基础上,增加了 OSI 批准的 AGPLv3 选项 。
Server-Sent Events: 实现高效的实时Web通信
Server-Sent Events 概述
Server-Sent Events(SSE)是一种基于 HTTP 协议的服务器推送技术,它允许服务器以流的方式向客户端实时推送数据。与 WebSocket 等双向通信技术不同,SSE 专注于单向通信(从服务器到客户端),特别适合需要服务器主动推送数据的场景,如:
- 社交媒体的实时通知(评论、点赞、关注提醒)
- 股票价格、体育比分的实时更新
- 日志和事件流的实时监控
- 聊天应用中的消息提醒
SSE 与 WebSocket 的对比
| 特性 | Server-Sent Events | WebSocket |
|---|---|---|
| 通信方向 | 单向(服务器到客户端) | 双向 |
| 协议 | 标准 HTTP | WebSocket 协议(基于 HTTP 握手) |
| 实现复杂度 | 低,使用现有的 HTTP 基础设施 | 相对较高,需要特殊的服务器支持 |
| 重连机制 | 内置自动重连 | 需要手动实现 |
| 浏览器支持 | 所有现代浏览器(IE 需要 polyfill) | 所有现代浏览器 |
| 数据格式 | 文本(通常是 JSON) | 文本或二进制 |
| 适用场景 | 服务器频繁更新客户端 | 需要频繁双向数据交换 |
SSE 工作原理
SSE 的实现原理非常简单。客户端通过 JavaScript 的 EventSource 接口发起请求,服务器保持连接打开并定期发送事件。这种连接具有以下特点:
Mac平台虚拟化神器:Orbstack
OrbStack](https://orbstack.dev/) 是一种快速、轻便和简单的方式来运行容器和 Linux 机器。Mac 平台中强烈建议用它替换 Docker Desktop,它比 Docker Desktop 占用更少的资源,官方有对比,感兴趣可以在这里查看https://docs.orbstack.dev/benchmarks,从图中对比来看,直接吊打。
OrbStack 占用的资源很少。OrbStack 在空闲时使用大约 0.1% 的 CPU,通常会降至 0%,这比大多数应用程序的后台 CPU 使用率更低!并且还可以在运行容器或者虚拟机的时候使用 orb config命令来限制 cpu 的最大使用量。当然啦,如果我们想尽量减少 CPU 的占用,那停止任何没有使用的容器或者关闭任何没有使用的虚拟机。OrbStack 是按需分配内存的,并会根据需要增长,并且后面没有使用的内存会自动返回给 macOS,这对于内存堪比黄金的 mac 电脑,真的是非常适合。OrbStack 磁盘占用也比较少,全新安装的 OrbStack 占用不到 10MB 的磁盘空间,并且它采用了完全动态的磁盘管理,几乎没有额外开销,其占用空间会根据需要自动增减。
普通人为什么缺乏奋斗精神和执行力?
1. 看不到希望
当人感觉前路渺茫,做什么都可能失败时,就很难鼓起勇气去行动。
1.1 习得性无助 (Learned Helplessness)
- 概念:就像实验里的大象,小时候被细绳拴住无法挣脱,长大后即使有力气挣脱了,也不会再去尝试,因为它“学会”了自己是无助的。
- 表现:当人经历多次挫折或失败后,可能会认为自己无法掌控局面,从而放弃努力,即使机会来临也不去尝试。
- 启示:要对抗这种心态,关键在于重建希望感。要相信自己有改变现状的能力,即使面对困难也不要轻易放弃。要认识到“趋利避害”虽然是本能,但有时需要克服这种本能去争取。
1.2 破窗理论 (Broken Windows Theory) - 应用于个人边界
- 概念:这个理论(常用于社会学)在这里可以理解为:如果第一次受到不合理的对待或侵犯时没有反抗,那么后续就可能招致更多得寸进尺的行为,底线会被不断突破。
- 表现:不敢拒绝别人的不合理要求,一味退让,导致自己的时间和精力被无谓消耗。
- 启示:要勇于维护自己的边界,在第一次遇到不公正或不合理情况时,就要明确表达“不”,进行反抗。这样才能避免被他人随意“踩踏”。
1.3 螃蟹效应 (Crab Bucket Effect)
- 概念:就像桶里的螃蟹,当一只快要爬出去时,其他的螃蟹会把它拉下来。
- 表现:身边的人(有时甚至是亲友)可能会因为嫉妒、不理解或其他原因,打击你的积极性,阻碍你前进。
- 启示:要远离那些不断消耗你、拖你后腿的人或环境。寻找积极向上、能互相鼓励的圈子。
2. 看不到结果
行动迟迟得不到正反馈,也会让人失去动力。
Hammerspoon使用入门
Hammerspoon(https://www.hammerspoon.org/) 是一款基于 Lua 脚本的自动化工具,它能够让 Mac 上的各种操作变得更加智能和自动化。无论是自动化日常任务,还是创建复杂的自定义快捷操作,Hammerspoon 都能轻松实现。它通过提供对系统事件的访问、窗口管理、键盘快捷键、自定义菜单等功能,帮助我们大大提高工作效率。
Hammerspoon 的核心特点
- Lua 脚本引擎 Hammerspoon 的最强大之处在于它使用 Lua 脚本,这意味着你可以通过编写 Lua 代码来控制 Mac 上的几乎所有操作。无论是简单的文件操作,还是复杂的自动化任务,都可以通过 Hammerspoon 的脚本来实现。
- 高度自定义 用户可以通过 Lua 脚本编写自己想要的功能,灵活性极高。例如,你可以为特定的应用程序创建快捷键、设置自动化任务、控制窗口的大小和位置等。Hammerspoon 还允许你将各种任务结合起来,以实现更为复杂的自动化流程。
- 与 macOS 深度集成 Hammerspoon 不仅可以操作系统的基本功能(如窗口管理、键盘操作),还能够与其他应用程序进行交互。比如,它可以控制 iTunes、Spotify 等音频应用的播放,或者让它与外部设备进行连接。
- 丰富的插件支持 Hammerspoon 本身并没有过多的限制,它拥有丰富的社区支持和插件库。用户可以安装各种插件来扩展功能,像是自动化桌面布局、快速启动应用程序、控制系统亮度等,几乎可以满足各种需求。
如何安装和配置 Hammerspoon?
- 安装 你可以通过 Hammerspoon 官网(hammerspoon.org)下载安装包,或者通过 Homebrew 进行安装:
brew install hammerspoon- 配置 安装完 Hammerspoon 后,你需要编辑配置文件来编写脚本。默认的配置文件位于~/.hammerspoon/init.lua。你可以通过文本编辑器打开该文件,并开始编写 Lua 脚本。 3. 加载配置 配置文件编辑完成后,你可以重新加载配置,使修改立即生效。点击 Hammerspoon 图标,在菜单中选择“Reload Config”即可。
一些使用场景分享
根据不同的应用自动切换输入法
可以写一个脚本来实现自动切换输入法,切换窗口的时候自动选择对应的输入法。 例如,我想在 kitty 这个应用中总是使用英文输入法,在微信这个应用中总是使用中文输入法,可以使用下面的代码来实现。
Spring Boot Web Test
创建一个 Controller 类
package com.example.testingweb;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HomeController {
@GetMapping("/")
public String greeting() {
return "Hello, World";
}
}如何测试这个 Controller
直接注入对应的 HomeController
@SpringBootTest
public class HomeControllerTest {
@Autowired
private HomeController homeController;
@Test
public void should_return_hello_world() {
String expected = "Hello, World";
String actual = homeController.greeting();
assertEquals(expected, actual);
}
}启动一个随机端口进行测试
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.test.web.server.LocalServerPort;
import static org.junit.jupiter.api.Assertions.assertEquals;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class HttpRequestTest {
@LocalServerPort
private int port;
@Autowired
private TestRestTemplate restTemplate;
@Test
public void should_return_hello_world() {
String expected = "Hello, World";
String actual = restTemplate.getForObject("http://localhost:" + port + "/", String.class);
assertEquals(expected, actual);
}
}使用 WebEnvironment.RANDOM_PORT 在测试时启动一个真实的服务器,但使用随机端口。这种方式有以下优点:
Jpa中自定义枚举映射
Jpa 中默认自带了@Enumerated 注解,它默认提供了两种形式 String 和 ordinal,表示按照枚举的名字和枚举值的顺序 ,但是有时候我们需要自定义枚举映射,比如枚举的值不是枚举的名字,而是枚举的某个属性值。这时候我们可以使用@Convert 注解来实现自定义枚举映射。
使用默认的@Enumerated 注解实现字段映射
@Entity
public class User{
@Id
private Integer userId;
private String name;
private Integer age;
@Enumerated(STRING)
private Status status;
}
public enum Status{
ACTIVE,DELETED,BANED
}使用自定义枚举映射
创建一个用于映射的枚举
public enum Status{
ACTIVE(1),DELETED(0),BANED(-1);
private final int value;
public int getValue(){
return this.value;
}
public static Status of(int value){
for(Status status:Status.values()){
if(status.getValue() == value){
return status;
}
}
throw new IllegalArgumentException("Invalid value: "+value);
}
}实现一个枚举转换器
//@Converter(autoApply=true)
public class StatusConverter implements AttributeConverter<Status,Integer>{
@Override
public Integer convertToDatabaseColumn(Status attribute){
return attribute.getValue();
}
@Override
public Status convertToEntityAttribute(Integer dbData){
return Status.of(dbData);
}
}使用@Convert 注解 � 用
@Entity
public class User{
@Id
private Integer userId;
private String name;
private Integer age;
@Convert(converter = StatusConverter.class, attributeName = "status")
private Status status;
}在上面的例子中使用了@Convert 注解,它有两个属性,一个是 converter,用于指定转换器,另一个是 attributeName,用于指定要转换的属性名,如果转换器设置了 autoApply,则可以省略这个注解。 配置完之后,我们就可以在实体类中使用自定义的枚举映射了。
