AWS EKS 与阿里云 ACK 托管对比:计费差异、产品线布局与中小企业选型

两大云托管 K8s 摆一起:差在哪,小公司怎么选 上一篇《Java 开发工程师的 K8s 职责清单》里用一小节对比了 AWS EKS 和阿里云 ACK,写的时候发现这个题目值得单独成篇——两家都在做"托管",但计费模型、产品线布局、生态绑定的差异直接决定学习成本和选型结果,尤其对预算敏感的中小企业。 这篇把两家云托管 K8s 摊开对比:先看产品线布局,再看计费模型(最影响选型的部分),然后是全维度差异表,最后给中小企业三档推荐配置。文末记录了本次调研的时间与文档版本,方便读者核对时效。 ⚠️ 声明:本文所有对比数据来自对两家官方文档的实际检索(检索时间见文末附录),不依赖二手资料。价格可能随时调整,实际以云厂商账单为准。 1. 产品线布局:两家各摆了几个形态 先说总览。两家都从"标准托管集群"出发,各自长出了一整条产品线: %% EKS 与 ACK 产品线对照 flowchart LR EKS["AWS EKS 家族"] ACK["阿里云 ACK 家族"] E1["标准 EKS\n控制面托管 + 自管/托管节点"] E2["EKS Auto Mode\n控制面+关键组件全托管"] E3["EKS Fargate\n无服务器, 按 Pod 计费"] E4["EKS Anywhere / Distro\n私有云/自建发行版"] A1["ACK 托管集群\nPro 版 / 基础版"] A2["ACK Auto Mode\n控制面+关键组件全托管"] A3["ACK Serverless (ASK)\nECI 弹性容器实例"] A4["ACK 专有集群\n已停止新建"] A5["ACK One / 边缘版\n多云统一 / 边缘节点"] EKS --> E1 EKS --> E2 EKS --> E3 EKS --> E4 ACK --> A1 ACK --> A2 ACK --> A3 ACK --> A4 ACK --> A5 style EKS fill:#0f172a,stroke:#3b82f6,stroke-width:2.5px,color:#ffffff,font-weight:bold style ACK fill:#0f172a,stroke:#3b82f6,stroke-width:2.5px,color:#ffffff,font-weight:bold style E1 fill:#1e1e24,stroke:#6b7280,stroke-width:2px,color:#ffffff style E2 fill:#1e1e24,stroke:#6b7280,stroke-width:2px,color:#ffffff style E3 fill:#1e1e24,stroke:#6b7280,stroke-width:2px,color:#ffffff style A1 fill:#1e1e24,stroke:#6b7280,stroke-width:2px,color:#ffffff style A2 fill:#1e1e24,stroke:#6b7280,stroke-width:2px,color:#ffffff style A3 fill:#1e1e24,stroke:#6b7280,stroke-width:2px,color:#ffffff style E4 fill:#052e16,stroke:#16a34a,stroke-width:2px,color:#ffffff,font-weight:bold style A4 fill:#052e16,stroke:#16a34a,stroke-width:2px,color:#ffffff,font-weight:bold style A5 fill:#052e16,stroke:#16a34a,stroke-width:2px,color:#ffffff,font-weight:bold 几个值得注意的点: ...

二月 12, 2024 · 3 分钟 · 619 字 · yaomingye

监控接入三方案原理对比:SSH 隧道、堡垒机与云原生监控

三条路看监控:隧道、堡垒机,还是数据上云? 在之前的文章里,我们为了"看一眼监控面板"折腾过不少事:部署在内网的 Prometheus/Grafana 不能直接访问,要开 SSH 隧道;隧道会断,断了要重连;连上之后还有账号密码、端口、地址一堆细节。这些"问题太多"的感慨,根源其实是同一个问题——监控系统放在私有网络里,人在外面,怎么合法地看到它? 围绕这个问题,行业给出了三种主流答案,恰好代表三种完全不同的网络哲学: SSH 隧道(人带着加密通道进内网看数据) 堡垒机(把入口收敛到一台"守门员",人过安检后进内网) 云原生监控(数据送出来给人看,人根本不用进内网) 这篇把三种方案的原理讲透,再放到同一张对比表里,最后给一张决策地图。它们没有优劣,只有"你愿意把哪一边放到公网上"的选择。 1. 方案 A:SSH 隧道 + 自建内网监控 原理 监控组件(Prometheus/Grafana)部署在内网,监听地址是内网 IP,公网完全摸不到。运维人员通过 SSH 端口转发(本地转发 -L 或反向转发 -R )把内网端口"搬"到自己笔记本的 localhost 上,浏览器访问 localhost:32090 时,流量顺着 SSH 加密通道流到内网。 这套方案的核心组件: 中转机:一台有公网 IP 的机器作为唯一入口,只开 SSH; 反向隧道:内网服务器主动用 autossh (自动重连的 SSH)连到中转机,建立常驻加密通道——这样即使内网没有公网 IP、人在任何网络,通道都在; 本地转发:运维人员笔记本再 ssh -L 把通道接回 localhost。 %% 方案A: SSH 隧道 + 自建内网监控(本系列学习环境的真实形态) flowchart TD LAP["运维人员笔记本\n浏览器访问 localhost:32090"] ECS["中转机(公网 IP)\n唯一公网入口\n只开放 SSH"] DEB["内网服务器\n无公网 IP"] MON["Prometheus / Grafana\n仅监听内网地址"] AUT["autossh 反向隧道\n常驻 + 自动重连"] LAP -->|"SSH -L 本地转发\n(端口搬到 localhost)"| ECS ECS -->|"加密隧道字节流"| AUT AUT -->|"经 SSH 通道"| DEB DEB --> MON LAP -.->|"浏览器流量实际路径"| MON style LAP fill:#0f172a,stroke:#3b82f6,stroke-width:2.5px,color:#ffffff,font-weight:bold style ECS fill:#0f172a,stroke:#3b82f6,stroke-width:2.5px,color:#ffffff,font-weight:bold style DEB fill:#0f172a,stroke:#3b82f6,stroke-width:2.5px,color:#ffffff,font-weight:bold style AUT fill:#052e16,stroke:#16a34a,stroke-width:2px,color:#ffffff,font-weight:bold style MON fill:#052e16,stroke:#16a34a,stroke-width:2px,color:#ffffff,font-weight:bold 特性 数据全程在内网:指标、日志不出内网,只有加密隧道里流动的"查看请求"; 暴露面最小化:公网只有中转机一个 SSH 端口,内网零暴露; 零新增组件:复用系统自带的 SSH,不需要额外部署任何产品; 认证模型:SSH 密钥对,个人密钥直连。 真实的坑(来自本系列实践) 隧道是这条链路上最脆弱的环节。SSH 双重跳转(笔记本 → 中转机 → 内网)空闲一段时间后,中转机侧可能重置连接,症状是 Read from remote host: Connection reset by peer ,浏览器打开看板立刻 HTTP 000 。解法是 autossh 保活 + 心跳参数,但自动重连只解决内网侧的反向隧道,笔记本侧的本地转发断了还是得手动拉起——这就是"单点"的代价。 ...

十二月 2, 2023 · 3 分钟 · 539 字 · yaomingye

微信支付 vs 支付宝:聚合支付渠道集成中的十一处暗坑

渠道集成的痛:微信和支付宝处处不一样 聚合支付系统要同时对接支付宝和微信支付。初看两边的官方文档,觉得差不多——都是「下单→拿凭证→前端拉起→回调通知」这个流程。真到写代码的时候才发现,每一步都不一样,甚至同是微信生态,App 和小程序之间还有差异。 这篇文章把两渠道在 SDK 选型、下单参数、签名机制、回调处理、退款流程、对账单格式六个环节的具体差异整理出来,顺便也记录微信 App 和小程序之间那几处让人想砸键盘的细节。 一、SDK 选型和核心对象 先看 SDK 本身的差异,这决定了后面所有代码怎么组织。 支付宝 微信支付 Maven artifact alipay-sdk-java:4.40.308.ALL wechatpay-java:0.2.17 核心对象 DefaultAlipayClient (就是 HTTP 客户端) RSAAutoCertificateConfig (配置 + 签名 + 证书管理) HTTP 层 自带老版 HttpClient 自带 OkHttp,可注入自定义实例 证书管理 无(公钥手动配) AutoCertificateService 自动下载平台证书 + 后台线程轮换 Service 封装 无,裸调 client.execute(request) AppService / JsapiService / RefundService 封装请求-响应对映 ⚠️ 新手提示:支付宝的 DefaultAlipayClient 就是个 HTTP 客户端,一行 new 就行。微信的 RSAAutoCertificateConfig 是重量级对象——创建时会初始化证书下载、后台轮询线程,要通过工厂 + Caffeine 缓存复用,别每次请求都 new。 两者最大的思维差异:支付宝把 SDK 当 HTTP 工具用,微信把 SDK 当基础设施用。 ...

十月 31, 2023 · 4 分钟 · 641 字 · yaomingye

数据库金额字段该用 decimal 还是 bigint:从历史惯例到现代支付栈的选型之路

钱的字段到底该用 decimal 还是 bigint 某开发者最近在设计一套统一支付服务,走到金额字段这一步,跟数据库里的老订单表吵了一架:新表想用 bigint 存"分",老表是 decimal(10,2)。写代码前先把这个历史遗留问题捋清楚,发现这背后是一整段软件史。 数据库里的金额字段,可能是除了主键之外被争论最多的一种类型。打开任何一本数据库教材,都会看到一句名言——“钱的字段千万别用 float”。但这句话的下半句往往没人讲:不用 float,那到底用 decimal 还是 bigint? 教科书里写的是 decimal。现代支付 API 的契约里写的是"整数最小单位"——也就是 bigint 存分。两边都合理,为什么结论会分叉? 从一次选型冲突说起 设计支付服务时,金额字段出现了两个候选人: ** decimal(10,2) ** —— 存的就是 100.00 ,肉眼可读 ** bigint ** —— 存 10000 ,单位是分,代码里到处都是 ÷100 老 ERP 系统的订单表选了前者,支付服务想选后者。这不是口味问题,是两个时代的设计碰撞。要理解它,得先从 float 为什么被禁说起——因为 float 才是那个真正不配碰钱的类型。 📌 前置知识:浮点数、定点数、IEEE 754 这三个概念是本文的地基,建议先有个印象再往下看。 float 的罪与罚:二进制算不清十进制 先复现那个经典翻车现场: SELECT 0.1 + 0.2; 结果是 0.30000000000000004 。 float / double 用二进制科学计数法存储: M × 2^E ,M 是尾数,E 是指数。但十进制小数 0.1 转成二进制是无限循环小数: ...

十月 25, 2023 · 3 分钟 · 631 字 · yaomingye

从 Java/Go 到 React:一个后端程序员的 TypeScript 受难与破壁实录(附 Flutter 做中间翻译器)

从 Java/Go 到 React,顺便拉 Flutter 垫背 一、前言:为什么后端程序员学 React 想骂人? 某后端组有天接了个需求:用 React + TypeScript 写个管理后台。组里人均三年 Spring Boot 或 Go Gin 经验,前端认知停留在 jQuery 版本。一开始想的是"TS 不就是带类型的 JS 嘛,有类型就不慌"——结果打开第一个 React 教程就傻了:函数组件、Hooks、闭包陷阱、依赖数组、JSX 里嵌逻辑……这哪是前端,这分明是另一个世界。 后端思维高度固化:类继承、接口实现、线程阻塞、强类型、反射——这些概念在 Spring 和 Go 里是护城河,在 React 里是全都没用的东西。类?函数组件不需要。接口?TS 的结构化类型不需要显式 implements。线程?JS 单线程事件循环,根本没有多线程。 Flutter 被拉进来做"中间翻译器":Dart 语法像 Java,但框架思维像 React。先写 Flutter 再写 React,会发现很多映射:Widget 树 >= 虚拟 DOM,setState >= useState,initState/dispose >= useEffect。把 Flutter 当"桥梁",Java/Go 当"起点",React 就没那么陌生。 为什么不直接对比?因为 Java 和 TS 差距太大——标称类型 vs 结构类型,多线程阻塞 vs 单线程事件循环。中间垫一个 Flutter(标称类型 + 单线程异步 + 声明式 UI),过渡就平滑了。 ...

十月 11, 2023 · 16 分钟 · 3256 字 · yaomingye

Go Runtime vs JVM:调度、GC、反射全方位对比

Go 运行时 vs JVM 运行时 一个 JVM 调优经验丰富的开发者第一次部署 Go 服务,看到监控数据时的反应: 这进程怎么只占 4MB? -Xmx 在哪设置?GC 日志怎么看? 接着打开 top ,看到 Go 服务起了几千个 goroutine,内存和 CPU 都低得离谱。而旁边跑了类似流量的 Spring Boot 服务, -Xmx512m 、GC 日志一大堆。 这不是魔法,是 Go runtime 和 JVM 的设计哲学完全不同。本文把两个运行时的核心差异讲清楚。 📌 前置知识:本文假定读者了解 JVM 的基本运行时概念(堆/栈/GC/类加载/JIT)和 Go 的 goroutine 基础知识。Go 版本为 1.22,对比 JVM HotSpot 17/21。 进程内存:4MB vs 512MB 的真相 维度 Go JVM(HotSpot) 最小内存 ~2-4MB ~50-200MB(含堆 + 元空间) 内存控制 自动,GOGC 环境变量 -Xmx / -Xms + 大量 JVM 参数 启动时间 毫秒级(AOT 编译) 秒级(类加载 + 解释执行 + JIT 预热) 部署产物 单一静态二进制(~10-20MB) JAR(需要 JRE/JDK 运行时) 内存占用大头 goroutine 栈 + 堆 + GC 元数据 堆 + 类元数据 + JIT 代码缓存 + 线程栈 两张图看清两个运行时各自的内存里到底装了什么: ...

二月 10, 2023 · 7 分钟 · 1322 字 · yaomingye

Go Web 开发全栈:从 Gin 到微服务

Go Web 开发:从 Gin 到微服务 一个 Spring Boot 程序员打开 Go 的 Web 项目,看到的是这样的代码: // 这是什么?Controller 在哪?@Autowired 在哪? func main() { db, _ := sql.Open("mysql", "user:pass@/dbname") repo := NewUserRepo(db) svc := NewUserService(repo) handler := NewUserHandler(svc) r := gin.Default() r.GET("/users/:id", handler.GetUser) r.Run(":8080") } 没有 @Controller 、没有 @Service 、没有 @Autowired 、没有 application.yml 。依赖是一个个手动拼起来的,路由是函数式注册的,连配置文件都得自己选库来读。 习惯 Spring Boot 全家桶的开发者,第一次面对 Go 的 Web 生态,大概有两类困惑: 框架选型:Gin、Echo、Fiber、Iris、go-zero、Kratos……每个都说自己性能好,到底该用哪个? 组织方式:没有注解驱动的 DI、没有 AOP、没有 Filter 接口——同样的需求在 Go 里怎么写? 本文用 Spring Boot/Spring Cloud 的对应视角,把 Go Web 开发的技术栈讲清楚。 ...

二月 8, 2023 · 9 分钟 · 1846 字 · yaomingye

Go 网络编程与 IO 模型

Go 网络编程 Java 程序员写网络服务,技术栈大概是这样的: // Java —— Netty 写一个 HTTP 服务 EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) { ch.pipeline() .addLast(new HttpServerCodec()) .addLast(new HttpObjectAggregator(65536)) .addLast(new SimpleChannelInboundHandler<FullHttpRequest>() { @Override protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) { // 业务逻辑... } }); } }); b.bind(8080).sync().channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } 配置 EventLoopGroup、Channel Pipeline、Codec、Handler……对于一个简单的 HTTP 服务,一半代码在处理 Netty 的样板。 ...

二月 6, 2023 · 5 分钟 · 1011 字 · yaomingye

Go 并发编程:Goroutine、Channel 与 CSP 模型

Go 并发编程 写了 5 年 Java 并发,你手上的工具大概是这样的: // Java —— 线程池 + Future + BlockingQueue var executor = Executors.newFixedThreadPool(10); var future = executor.submit(() -> { return remoteService.query(); }); try { var result = future.get(5, TimeUnit.SECONDS); } catch (TimeoutException e) { future.cancel(true); } 现在看 Go 的等价写法: // Go —— goroutine + channel + select func queryWithTimeout() { ch := make(chan string, 1) go func() { ch <- remoteService.Query() }() select { case result := <-ch: fmt.Println(result) case <-time.After(5 * time.Second): fmt.Println("超时了") } } 没有 Executor ,没有 Future ,没有 BlockingQueue 。 go 关键字一写,协程就启动了。 chan 一建,数据就在协程间流动。 这是 Go 语言最独特的基因 。 ...

二月 4, 2023 · 7 分钟 · 1383 字 · yaomingye

Java vs Go 语法快速对比

Java vs Go:语法对比 打开 .go 文件,第一眼看到这些,脑子直接宕机: func getUser(id int) (*User, error) { if user, ok := cache.Load(id); ok { return user.(*User), nil } defer func() { metrics.Record("getUser") }() // ... } := 是什么? *User 和 error 为什么挤在返回值里? defer 又是什么鬼? ok 从哪冒出来的? 写了 5 年 Spring Boot,习惯了 var user = new User() 、 try-catch-finally 、 public class 之后,Go 的语法看起来像是故意反着来。这篇文章的目的就是一句话:把所有 Java 里习以为常的语法点,在 Go 里找到对应写法 。没有废话,全是代码对比。 📌 前置知识:本文假定读者有 Java 基础(Java 8+),了解基本的编程概念(变量、函数、循环、异常)。Go 版本为 1.22。 ...

二月 2, 2023 · 10 分钟 · 1994 字 · yaomingye
Cat Radio