Nacos 2.5.2 在 macOS M1 上的内存下限实测:500MB 降不动

Nacos 2.5.2 在 macOS M1 上的内存下限实测:500MB 降不动

Nacos 2.5.2 standalone 模式默认只设了堆 -Xms64m -Xmx128m,Metaspace 和 DirectMemory 完全没上限,实际 RSS 在 500MB 左右。想压更低,试了一圈,结论是:500MB 基本是硬下限。

踩过的坑

试过把堆降到 96m,运行 70 秒后 OOM 退出,没有 heapdump,静默挂掉。试过把线程栈压到 192k,JDK 11 在 macOS arm64 上直接拒绝启动——最低 208k。试过 Metaspace 上限设 128m,启动到 Derby 加载阶段就挂,因为 Nacos 光启动就要 140-150MB 的类元数据。

用 NMT 拆解 RSS 构成

开启 -XX:NativeMemoryTracking=summary 后用 jcmd VM.native_memory summary 逐项看,500MB 的去向很清楚:

区域 占用 说明
Metaspace 93MB 16351 个类,Nacos 体积决定的硬需求
Java Heap 123MB Xmx 128m 几乎满,96m 运行时不够
线程栈 67MB 227 个线程,macOS 强制 208k/线程下限
Symbol 表 19MB 类加载的副产品,不可调
Code Cache 28MB JIT 编译代码
Direct Memory ~70MB gRPC/Netty 堆外内存
JVM 自身 + 共享库 ~50MB

几乎全是 native 内存,JVM 参数设上限只能防止失控,降不了实际占用。

最终配置

startup.sh 第 95 行 standalone 分支改为:

JAVA_OPT="${JAVA_OPT} ${CUSTOM_NACOS_MEMORY:- -Xms64m -Xmx128m -Xmn32m -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=192m -XX:MaxDirectMemorySize=96m -XX:+UseSerialGC -Xss256k -XX:ReservedCodeCacheSize=64m}"

每一项的作用:-XX:+UseSerialGC 替掉 G1GC 省 GC 元数据;-Xss256k 从默认 1m 砍到 1/4;MaxMetaspaceSize=192mMaxDirectMemorySize=96m 封顶防失控;ReservedCodeCacheSize=64m 从默认 240m 降到 64m。

实测 RSS 仍在 500MB 左右,但这套参数封住了所有可膨胀的 native 内存区域,长期运行不会因为 Metaspace 或 DirectMemory 无上限而持续增长。

还想往下压的三条路(超出 JVM 调参范畴)

  1. startup.sh -m standalone -f naming 只跑服务发现,跳过配置中心,实测 RSS 降到 485MB,省 50MB,代价是 config 不可用。
  2. 换 JDK 17,metaspace 管理更高效,预计省 30-50MB。
  3. 外接 MySQL 替代内嵌 Derby,省掉 Raft/嵌入式存储的堆内开销。

底线:Nacos 这种 Spring Boot 重应用,光 JVM 自身结构 + 类元数据 + gRPC 堆外就要 400MB+,这是物理约束。想突破 500MB 得从减少加载模块入手,不是调参能解决的。


另一台电脑复刻步骤

1. 备份原文件

cp nacos/bin/startup.sh nacos/bin/startup.sh.bak

2. 改 standalone 分支

编辑 nacos/bin/startup.sh,找到第 95 行(standalone 分支):

# 原始(只有堆)
JAVA_OPT="${JAVA_OPT} ${CUSTOM_NACOS_MEMORY:- -Xms64m -Xmx128m -Xmn32m}"

# 改为
JAVA_OPT="${JAVA_OPT} ${CUSTOM_NACOS_MEMORY:- -Xms64m -Xmx128m -Xmn32m -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=192m -XX:MaxDirectMemorySize=96m -XX:+UseSerialGC -Xss256k -XX:ReservedCodeCacheSize=64m}"

只改 standalone 那行,集群分支(第 101 行)不动。

3. 重启验证

sh nacos/bin/shutdown.sh
sh nacos/bin/startup.sh -m standalone
# 等 1 分钟,确认 HTTP 200
curl -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8848/nacos/

4. 如果另一台不是 M1 而是 Intel Mac

参数完全一样,但线程栈下限不同,Intel 上 -Xss256k 可以更低。如果还想压,试 -Xss208k,不过省不了多少。

5. 如果另一台是 Linux/Windows

-Xss256k 可能可以降到更激进(某些 Linux 平台最低 160k),但也省不了几 MB,不值得折腾稳定性。

macOS chronod 占用 100% CPU 的一次排查记录

macOS chronod 占用 100% CPU 的排查与修复

现象:活动监视器中 chronod 长时间占用 100% 以上 CPU,重启系统后仍然存在。

进程路径:

/System/Library/PrivateFrameworks/ChronoCore.framework/Support/chronod

chronod 主要和 macOS 小组件、通知中心、App Intents、时间线数据同步有关。日志中如果反复出现这些关键词,通常说明它卡在小组件同步或缓存处理上:

com.apple.chrono
NotificationCenter
ReplicatorServices
remoteArchives
widget-relevance-cache

可先尝试关闭 iPhone 小组件:

系统设置 -> 桌面与程序坞 -> 小组件 -> 使用 iPhone 小组件

然后重启相关进程:

killall chronod 2>/dev/null
killall NotificationCenter 2>/dev/null

如果仍然高占用,清理 chronod 缓存和数据库,让系统自动重建:

mkdir -p ~/Desktop/chronod-backup

killall chronod 2>/dev/null
killall NotificationCenter 2>/dev/null

mv "$HOME/Library/Caches/com.apple.chrono" \
   "$HOME/Desktop/chronod-backup/com.apple.chrono-$(date +%Y%m%d-%H%M%S)"

mv "$HOME/Library/Group Containers/group.com.apple.chronod/chronod" \
   "$HOME/Desktop/chronod-backup/chronod-$(date +%Y%m%d-%H%M%S)"

killall chronod 2>/dev/null
killall NotificationCenter 2>/dev/null

如果执行时提示 Operation not permitted,需要先给终端完整磁盘访问权限:

系统设置 -> 隐私与安全性 -> 完全磁盘访问权限

给 Terminal 或 iTerm 授权后重新执行。

这个操作会重建小组件和通知中心相关缓存,一般不会影响应用数据。部分小组件可能需要重新加载或重新添加。

macOS 透明压缩工具 applesauce 安装与使用指南

前言

在 Windows 上,我们可以通过 NTFS 压缩功能让文件“原地变小”而不改变使用方式。macOS 虽然底层文件系统(APFS/HFS+)也支持透明压缩,但系统并没有提供图形界面开关。

applesauce 是一个命令行工具,可以调用 macOS 原生压缩能力,实现对文件的透明压缩——压缩后的文件仍在原位置,双击正常打开,但磁盘占用空间显著减小。

Continue reading macOS 透明压缩工具 applesauce 安装与使用指南

DeepSeek Sidebar – 一键在 Chrome 侧边栏打开 DeepSeek

一键在 Chrome 侧边栏打开 DeepSeek,支持页面缩放并记忆缩放比例。

功能

  • 一键打开 — 点击扩展图标即可在侧边栏加载 DeepSeek
  • 自由缩放 — 工具栏按钮或 Ctrl/Cmd +/-/0 快捷键,30%-200% 范围调节
  • 记忆缩放 — 自动保存缩放比例,下次打开立即恢复
  • 简洁工具栏 — 深色主题,不干扰对话体验

安装

从 Chrome Web Store 安装

即将上架

开发者模式加载

  1. 克隆本仓库
    git clone https://github.com/misswell/deepseek-sidebar.git
  2. 打开 chrome://extensions
  3. 开启右上角「开发者模式」
  4. 点击「加载已解压的扩展程序」,选择项目目录

文件结构

├── manifest.json       # MV3 扩展清单
├── background.js       # Service Worker,处理图标点击
├── sidepanel.html      # 侧边栏页面
├── sidepanel.js        # 缩放控制逻辑
├── rules.json          # 移除 X-Frame-Options 响应头
├── privacy-policy.html # 隐私政策
└── icons/              # 扩展图标
    ├── icon16.png
    ├── icon48.png
    └── icon128.png

权限说明

权限 用途
sidePanel 在 Chrome 侧边栏中展示 DeepSeek 页面
activeTab 点击扩展图标时获取当前标签页以打开侧边栏
storage 本地保存用户的缩放比例设置
declarativeNetRequest 移除 DeepSeek 的 X-Frame-Options 响应头,使其可在侧边栏中加载
host_permissions 访问 chat.deepseek.com 以实现上述头部修改

隐私

本扩展不收集任何用户数据。详见 隐私政策

License

MIT

Yarn 安装完成后存在超时提示处理

Yarn 安装完成后存在超时提示

success Already up-to-date.
✨  Done in 0.11s.
info There appears to be trouble with your network connection. Retrying...
info There appears to be trouble with your network connection. Retrying...

问题 :Yarn 的版本检查机制
Yarn 每次运行时可能会尝试连接网络检查自身版本或发送统计数据,即使不需要下载包。

解决方案:禁用版本检查和统计

# 禁用 Yarn 的版本检查
yarn config set disable-self-update-check true

# 禁用匿名统计数据上报
yarn config set analytics false

VMware Workstation 虚拟机自动开机攻略:Win11 不显示的坑与解法

前言

最近想给电脑设置开机后自动启动 VMware 里的几个虚拟机(Win7、CentOS、Win11),结果发现了一个让人抓狂的问题:明明在“配置自动启动虚拟机”里添加了,但重启后只有 Win7 和 CentOS 乖乖启动了,Win11 却纹丝不动。更诡异的是,在自动启动配置列表里压根就找不到 Win11 的身影!

经过一番折腾,终于把这个坑填平了。下面把踩过的坑和解决办法分享给大家。

Continue reading VMware Workstation 虚拟机自动开机攻略:Win11 不显示的坑与解法

mybatis 创建临时表

mybatis 创建临时表

    <insert id="dropTempTable">
        DROP TEMPORARY TABLE IF EXISTS temp_table${uuid};
    </insert>
    <insert id="createTempTable">
        CREATE TEMPORARY TABLE IF NOT EXISTS temp_table${uuid} (
        id VARCHAR(50) PRIMARY KEY
    );
    </insert>
    <!-- 插入数据到临时表 -->
    <insert id="insertTempTableData">
        INSERT INTO temp_table${uuid} (id)
        VALUES
        <foreach collection="orgIdList" item="id" separator=",">
            (#{id})
        </foreach>
    </insert>

MySQL 一对多 in 查询

mysql 第一张表为用户表,第二张表为用户与组织的关系表,用户与组织一对多的关系,已知多个用户组织id,查询哪些用户属于这些组织

你希望从组织 ID 为 1、2、3 的用户中查询,同时列出他们所有的组织 ID,包括那些不在 1、2、3 之中的,如 45。这样,我们需要一个两步的查询:

  1. 首先,找到组织 ID 为 1、2、3 的用户。
  2. 然后,查询这些用户所拥有的所有组织 ID。

我们可以使用子查询来实现这一点:

SQL 查询示例

SELECT u.user_id, u.user_name, GROUP_CONCAT(uo.organization_id ORDER BY uo.organization_id) AS organization_ids
FROM users u
JOIN user_organization uo ON u.user_id = uo.user_id
WHERE u.user_id IN (
    SELECT uo.user_id
    FROM user_organization uo
    WHERE uo.organization_id IN (1, 2, 3)
)
GROUP BY u.user_id, u.user_name;

解释

  1. 子查询部分SELECT uo.user_id FROM user_organization uo WHERE uo.organization_id IN (1, 2, 3) 用于找到所有组织 ID 为 1, 2, 3 的用户 ID。
  2. 主查询部分
    • JOIN 连接 users 表和 user_organization 表,以获取用户及其所有组织 ID。
    • WHERE u.user_id IN (...) 仅选择在子查询中找到的用户 ID。
    • GROUP_CONCAT(uo.organization_id ORDER BY uo.organization_id) 聚合用户的所有组织 ID,并按升序排列。

示例

假设 Alice 拥有组织 ID 1, 2, 4, 5,Bob 拥有组织 ID 2, 3,Charlie 拥有组织 ID 1, 2, 3, 4,而你查询的组织 ID 是 1, 2, 3,那么查询结果会是:

user_id user_name organization_ids
1 Alice 1,2,4,5
2 Bob 2,3
3 Charlie 1,2,3,4

在这个结果中,organization_ids 列包括用户所拥有的所有组织 ID,而不仅仅是查询条件中的那些组织 ID。