《AgentX 专栏》10-生产部署:3台2C4G云服务器把企业级Agent真正跑起来的完整方案

生产部署:3 台 2C4G 云服务器,把企业级 Agent 真正跑起来的完整方案|AgentX 专栏⑩

本文是 AgentX 技术专栏 第十篇,也是收官篇。基于真实项目部署产物(Dockerfile / docker-compose.yml / deploy.sh / server-init.sh / .env.example),从技术简介到设计思路,从核心脚本到生产踩坑,循序渐进拆解 AgentX 如何用 3 台 2C4G 低配云服务器,把一个企业级 Agent 平台真正跑起来------让 Java 程序员一次性看懂"从代码到上线"的最后一公里。


本文速览:

  • 为什么"本地能跑"和"生产能跑"是两回事?AI 应用部署的独特难点
  • 三节点拓扑:推理节点 / 存储节点 / 监控节点,每台机器干什么
  • Dockerfile 多阶段构建:为什么编译镜像和运行镜像要分开
  • ZGC + MaxRAMPercentage=75%:低配机器上的 JVM 调优
  • server-init.sh 裸机初始化:动态 Swap、Docker 镜像加速、NVIDIA 残留清理
  • deploy.sh 一键部署:git pull → 构建 → 健康验证的完整闭环
  • 三个生产部署大坑:容器访问宿主机 Ollama、内存超配 OOM、健康检查误杀

文章约 40 KB,是整个专栏的落地收尾------建议从头读。读完文末有完整部署代码包(含全部脚本 + 三节点配置)获取方式。


一、先抛个问题:为什么"本地能跑"不等于"能上线"

很多人做 AI 应用,本地 mvn spring-boot:run 跑得好好的,一到部署就傻眼。因为本地和生产之间隔着一条鸿沟:

维度 本地开发 生产环境
依赖服务 都在一台机器(localhost) 分散在多台服务器,跨网络
资源 16G 内存随便造 2C4G,抠着用
启动 IDE 点一下 要能一键部署、自动重启
故障 重启 IDE 要能自愈、要有监控
配置 写死在代码里 要能按环境注入
GPU 无所谓 没有 GPU,CPU 跑大模型

尤其是 AI 应用,还有几个独特的部署难点:

  1. 大模型推理吃资源------Ollama 跑 qwen2.5 即使是 CPU 版也要好几 G 内存
  2. 依赖组件多------LLM、向量库(Milvus)、缓存(Redis)、追踪(Jaeger),一个都不能少
  3. 启动慢------大模型加载 + 向量库初始化,冷启动可能要分钟级
  4. 长连接------SSE 流式对话,健康检查不能误判

这篇文章就来拆解 AgentX 怎么在3 台 2C4G 的低配云服务器上,把这些难点逐个解决,做到"一行命令上线、挂了自动重启、出问题能追踪"。

这是整个专栏的收官篇。前面 9 篇讲的是"怎么写",这一篇讲"怎么上线"------没有这一步,再好的代码也只是个 demo。


二、技术简介:AI 应用的生产部署需要什么

2.1 部署的本质是"环境复制 + 依赖编排 + 故障自愈"

一个生产级部署方案,至少要回答三个问题:

问题 解决手段
怎么保证哪台机器都能跑? 容器化(Docker)------ 把运行环境打包进镜像
多个依赖组件怎么协同? 编排(docker compose)------ 一份配置拉起所有服务
挂了怎么办? 健康检查 + 自动重启 + 监控告警

2.2 AgentX 的部署技术栈

技术 作用 为什么选它
Docker 多阶段构建 打包应用 编译/运行分离,镜像瘦身
docker compose 单机编排 比 K8s 轻,2C4G 跑得动
Shell 脚本(deploy/init) 自动化 无依赖,任何 Linux 都能跑
环境变量(.env) 配置注入 一份镜像跑多环境
ZGC JVM 垃圾回收 低延迟,停顿亚毫秒级

2.3 为什么不用 K8s?

这是很多人的第一反应------"上生产不就该上 K8s 吗?"

方案 资源开销 学习成本 适合规模
docker compose 极低 单机 / 几台机器
K8s 高(光控制面就吃 1-2G) 陡峭 几十台 + 弹性伸缩

对 3 台 2C4G 的机器来说,K8s 的控制面开销就能吃掉一台机器的资源。 个人项目、中小企业的 Agent 平台,docker compose 足够了。技术选型的核心是"匹配规模",不是"追新"------这也呼应了专栏②讲的预算约束哲学。


三、设计思路:四条低成本生产部署的核心原则

原则一:职责分离,三节点拓扑

把所有东西堆一台机器上,2C4G 必然撑不住。AgentX 按职责把服务拆到三台机器:

arduino 复制代码
┌─────────────────────────────────────────────────────────────────┐
│  Server A · 推理节点(124.223.22.34)                            │
│    ├── AgentX 后端(Spring Boot 容器)                          │
│    └── Ollama(同机独立部署,qwen2.5 + bge-m3)                  │
│    特点:CPU 密集,大模型推理的主战场                            │
├─────────────────────────────────────────────────────────────────┤
│  Server B · 存储节点(10.0.0.15,内网)                          │
│    ├── Redis(短期记忆 / 会话)                                  │
│    └── Milvus(长期记忆 / RAG 向量库)                          │
│    特点:内存 + 磁盘密集,数据持久化的主战场                     │
├─────────────────────────────────────────────────────────────────┤
│  Server C · 监控节点(8.140.221.150,北京)                      │
│    ├── Jaeger(链路追踪,呼应专栏⑦)                            │
│    └── Nginx(反向代理 / 入口)                                  │
│    特点:独立隔离,监控不与业务争资源                            │
└─────────────────────────────────────────────────────────────────┘

为什么这样分? 三类负载的资源特征完全不同:

  • 推理(A)吃 CPU
  • 存储(B)吃内存和磁盘 IO
  • 监控(C)需要独立,不能业务一崩监控也跟着崩

分开之后,每台 2C4G 各司其职,互不抢资源。

原则二:容器化,但只容器化"无状态"的部分

AgentX 后端是无状态的(状态都在 Redis/Milvus),适合容器化。但有两个东西故意不放进容器

组件 是否容器化 原因
AgentX 后端 ✅ 容器 无状态,随便重启
Ollama ❌ 宿主机独立部署 大模型文件几个 G,容器化反而麻烦;且要复用宿主机的 CPU 优化
Redis/Milvus ❌ 独立节点 有状态,数据要持久化,单独管理更稳

容器化不是越多越好。 有状态、重量级、需要复用宿主机资源的组件,独立部署往往更省心。

原则三:配置外置,一份镜像跑多环境

绝不把 IP、密码写死在代码或镜像里。所有环境相关配置走 .env 文件 + 环境变量注入:

bash 复制代码
镜像(不变)  +  .env(按环境变化)  =  跑在任何环境

开发环境一份 .env,生产环境一份 .env,同一个镜像不用重新构建。这是十二要素应用(12-Factor App)的核心原则之一。

原则四:一切自动化,从裸机到上线两条命令

部署不应该是"照着 100 步文档手敲"。AgentX 把整个流程压缩成两个脚本:

bash 复制代码
# 1. 裸机第一次:初始化服务器环境
bash server-init.sh

# 2. 之后每次部署/更新:一键
bash deploy.sh

自动化的价值不只是省事,更是消除"人肉操作的不确定性"------脚本每次执行结果一致,不会因为忘了某一步而出错。


四条原则讲完,看具体落地。


四、代码解析:从裸机到上线的完整链路

4.1 Dockerfile:多阶段构建

第一块拼图是把 AgentX 后端打包成镜像。关键是多阶段构建

dockerfile 复制代码
# ── Stage 1: 编译(Maven + JDK 21)──
FROM maven:3.9-eclipse-temurin-21 AS builder

# 配置阿里云 Maven 镜像,加速依赖下载
COPY maven-settings.xml /root/.m2/settings.xml

WORKDIR /build
COPY pom.xml .
RUN mvn dependency:go-offline -B -q 2>/dev/null || true   # 先下依赖(利用缓存层)
COPY src ./src
RUN mvn clean package -DskipTests -B

# ── Stage 2: 运行(最小的 JRE 镜像)──
FROM eclipse-temurin:21-jre

WORKDIR /app
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# 只复制编译产物,不带 Maven 和源码
COPY --from=builder /build/target/agentx-1.0.0.jar app.jar

EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
  CMD curl -s --fail http://localhost:8080/api/v1/agents/health || exit 1

ENTRYPOINT ["java", \
  "-server", \
  "-XX:+UseZGC", \
  "-XX:MaxRAMPercentage=75.0", \
  "-Djava.security.egd=file:/dev/./urandom", \
  "-jar", "app.jar"]

为什么要分两个 Stage?

单阶段(错误做法) 多阶段(正确做法)
镜像内容 Maven + JDK + 源码 + 依赖 + jar 只有 JRE + jar
镜像大小 800MB+ 200MB 左右
安全性 源码、构建工具全暴露 只有运行时,攻击面小

Stage 1 用完整的 Maven 镜像编译,Stage 2 用最小的 JRE 镜像运行,最终镜像只保留 Stage 2 的内容。编译用的 Maven、源码全部丢弃。

三个 JVM 参数的讲究:

ini 复制代码
-XX:+UseZGC               # ZGC 垃圾回收器,停顿亚毫秒级
-XX:MaxRAMPercentage=75.0 # 最多用 75% 容器内存(留 25% 给堆外/系统)
-Djava.security.egd=file:/dev/./urandom  # 用非阻塞随机源,加速启动
  • ZGC:传统 G1 在大堆下 GC 停顿可能几百毫秒,对 SSE 流式对话是灾难。ZGC 停顿亚毫秒级,无论堆多大。
  • MaxRAMPercentage=75% :容器里绝不能-Xmx 写死内存。容器内存限制变了,写死的 -Xmx 不会跟着变,容易 OOM。用百分比让 JVM 自适应容器内存。留 25% 给 Metaspace、线程栈、堆外内存。
  • egd=urandom :JVM 启动时初始化 SecureRandom 会读 /dev/random,没有足够熵时会阻塞。换成 /dev/urandom 非阻塞,启动快好几秒。

4.2 docker-compose.yml:编排与配置注入

有了镜像,用 compose 拉起服务并注入配置:

yaml 复制代码
services:
  agentx-app:
    build: .
    container_name: agentx-app
    ports:
      - "${SERVER_PORT:-8080}:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=${SPRING_PROFILES_ACTIVE:-prod}

      # Redis(Server B: 10.0.0.15)
      - REDIS_HOST=${REDIS_HOST:-10.0.0.15}
      - REDIS_PASSWORD=${REDIS_PASSWORD:-}

      # 统一数据节点 IP(application.yml 通过 DATA_SERVER_IP 引用)
      - DATA_SERVER_IP=${DATA_SERVER_IP:-10.0.0.15}

      # Milvus(Server B)
      - MILVUS_HOST=${MILVUS_HOST:-10.0.0.15}
      - MILVUS_PORT=${MILVUS_PORT:-19530}

      # 监控节点(Server C: 北京 Jaeger)
      - MONITOR_SERVER_IP=${MONITOR_SERVER_IP:-8.140.221.150}

      # OTel 语义标签(呼应专栏⑦)
      - OTEL_SERVICE_NAME=agentx
      - OTEL_RESOURCE_ATTRIBUTES=service.version=1.0.0,deployment.environment=production

      # Ollama(同机独立部署,通过 host.docker.internal 访问宿主机)
      - AI_SERVER_IP=${AI_SERVER_IP:-host.docker.internal}
      - OLLAMA_HOST=${OLLAMA_HOST:-http://host.docker.internal:11434}

    volumes:
      - ./logs:/app/logs          # 日志挂出来,容器删了日志还在
    restart: unless-stopped       # 自愈:非人为停止就自动重启
    extra_hosts:
      - "host.docker.internal:host-gateway"   # 关键:让容器能访问宿主机
    healthcheck:
      test: ["CMD", "curl", "-s", "--fail", "http://localhost:8080/api/v1/agents/health"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 60s           # 关键:给冷启动 60s 宽限期

networks:
  default:
    name: agentx-network

几个关键设计:

配置 作用
${VAR:-default} 环境变量优先,没有就用默认值------配置外置
restart: unless-stopped 容器挂了自动重启,除非人为停止
extra_hosts: host.docker.internal 让容器访问宿主机的 Ollama(坑一会细讲)
start_period: 60s 冷启动宽限期,避免健康检查误杀(坑三会细讲)
volumes: ./logs 日志持久化到宿主机

注意 DATA_SERVER_IPMONITOR_SERVER_IP 这些------三节点的 IP 全部通过环境变量注入,application.yml 里用 ${DATA_SERVER_IP} 引用。改 IP 不用动代码。


4.3 server-init.sh:裸机一键初始化

一台刚买的云服务器,什么都没有。server-init.sh 把它变成能跑 AgentX 的环境。核心片段:

bash 复制代码
#!/bin/bash
set -euo pipefail

# ── 动态 Swap:低配机器的救命稻草 ──
TOTAL_MEM=$(awk '/MemTotal/{printf "%d", $2/1024}' /proc/meminfo)
if ! swapon --show | grep -q .; then
    if [ "$TOTAL_MEM" -le 4096 ]; then
        SWAP_SIZE="4G"          # 4G 内存配 4G swap
    elif [ "$TOTAL_MEM" -le 8192 ]; then
        SWAP_SIZE="2G"
    else
        SWAP_SIZE="0"           # 内存充足不配
    fi
    if [ "$SWAP_SIZE" != "0" ]; then
        fallocate -l "$SWAP_SIZE" /swapfile
        chmod 600 /swapfile
        mkswap /swapfile && swapon /swapfile
        echo '/swapfile none swap sw 0 0' >> /etc/fstab
        sysctl vm.swappiness=10              # 尽量用内存,swap 兜底
        echo "vm.swappiness=10" >> /etc/sysctl.conf
    fi
fi

# ── Docker 安装:走阿里云源 ──
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor \
    -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [...signed-by=...] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
    $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list
apt update -y && apt install -y docker-ce docker-ce-cli containerd.io

# ── 阿里云 ECS 镜像加速 ──
cat > /etc/docker/daemon.json <<EOF
{ "registry-mirrors": ["https://registry.cn-hangzhou.aliyuncs.com"] }
EOF
systemctl restart docker

为什么这些细节重要?

  • 动态 Swap :2C4G 机器跑 Java + 偶尔的内存尖峰,没有 swap 极易 OOM。但 swap 太多又会拖慢,所以 swappiness=10------优先用物理内存,swap 只兜底。
  • swap 大小按内存动态算:4G 内存配 4G swap,8G 配 2G,16G 不配。不是一刀切。
  • 阿里云镜像加速:国内拉 Docker Hub 镜像慢到崩溃,配了加速器才能正常拉镜像。
  • NVIDIA 残留清理(脚本里还有):阿里云 ECS 有时带 NVIDIA 驱动残留,会干扰 apt,开头先清理。

这些都是"国内低配云服务器"才会踩的真实坑,脚本把它们一次性处理掉。


4.4 deploy.sh:一键部署闭环

环境就绪后,deploy.sh 负责"拉代码 → 构建 → 启动 → 验证"的完整闭环:

bash 复制代码
#!/bin/bash
set -e

PROJECT_PATH="/usr/service/agentx"
CONTAINER_NAME="agentx-app"

# ── 1. 拉取最新代码 ──
if [ ! -d "$PROJECT_PATH" ]; then
    git clone --branch main git@github.com:SuniaW/agentx.git "$PROJECT_PATH"
else
    cd "$PROJECT_PATH"
    git fetch --all
    git reset --hard origin/main      # 强制同步到最新,避免本地冲突
fi
cd "$PROJECT_PATH"

# ── 2. 准备环境变量 ──
[ -f set-env.sh ] && source set-env.sh
[ ! -f .env ] && cp .env.example .env

# ── 3. 构建并启动 ──
docker compose down 2>/dev/null || true
docker compose up -d --build --force-recreate

# ── 4. 健康验证 ──
sleep 10
STATUS=$(docker inspect -f '{{.State.Running}}' "$CONTAINER_NAME")
HEALTH=$(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{else}}running{{end}}' "$CONTAINER_NAME")

if [ "$STATUS" == "true" ]; then
    echo "✅ 部署成功!(health: $HEALTH)"
    docker logs --tail 5 "$CONTAINER_NAME"
else
    echo "❌ 容器未能正常启动,查看:docker logs $CONTAINER_NAME"
fi

# ── 5. 清理过期镜像 ──
docker image prune -f >/dev/null 2>&1 || true

这个脚本体现了"幂等部署"的思想:

  • 首次和更新统一 :目录不存在就 clone,存在就 git reset --hard 强制同步。不管是第一次还是第一百次,跑同一个命令。
  • --force-recreate:强制重建容器,确保新代码生效(避免 Docker 缓存导致跑旧代码)。
  • 部署后自动验证 :不是 up -d 完就完事,还要 docker inspect 确认容器真的 Running + Healthy。
  • 自动清理docker image prune 删掉旧镜像,防止磁盘被占满(低配机器磁盘也小)。

一行 bash deploy.sh,从拉代码到验证上线全自动。


4.5 整体部署流程串起来

csharp 复制代码
裸机服务器
   │ bash server-init.sh
   ▼
环境就绪(Docker / Swap / 镜像加速 / Git)
   │ 配置 GitHub SSH key
   ▼
bash deploy.sh
   │ git pull → docker compose up --build
   ▼
容器启动 → HEALTHCHECK 探测(60s 宽限)
   │ 健康
   ▼
✅ 上线(access http://124.223.22.34:8080)
   │ 挂了?
   ▼
restart: unless-stopped 自动拉起

从一台空服务器到生产可用,两条命令


五、问题解决:三个生产部署的实战大坑

坑一:容器里的 AgentX 连不上宿主机的 Ollama

现象

本地开发时 OLLAMA_HOST=http://localhost:11434 一切正常。打成容器部署后,AgentX 疯狂报 Connection refused,连不上 Ollama。

原因

容器有自己独立的网络命名空间。容器里的 localhost 指的是容器自己 ,不是宿主机。而 Ollama 跑在宿主机上(我们故意不容器化它,见原则二)。容器里访问 localhost:11434,等于在容器内部找 Ollama------当然找不到。

解决

用 Docker 提供的特殊域名 host.docker.internal 访问宿主机,并在 compose 里显式声明映射:

yaml 复制代码
environment:
  - OLLAMA_HOST=http://host.docker.internal:11434   # 不是 localhost!
extra_hosts:
  - "host.docker.internal:host-gateway"             # Linux 上必须显式声明
写法 容器里指向 结果
localhost:11434 容器自己 ❌ 连不上
host.docker.internal:11434 宿主机 ✅ 连得上

注意host.docker.internal 在 Docker Desktop(Mac/Win)上自带,但Linux 上必须加 extra_hosts: host-gateway 才能用------这是最容易漏的一步。

教训:容器化一个组件时,要想清楚它依赖的其他服务在哪。容器的网络隔离是把双刃剑------隔离带来干净,也带来"localhost 不再是你以为的 localhost"。


坑二:JVM 内存超配,容器被 OOMKilled

现象

容器跑着跑着突然消失,docker inspect 显示 OOMKilled: true。但应用日志里没有任何 Java 的 OutOfMemoryError------是被系统直接杀掉的。

原因

最初 Dockerfile 里写死了 -Xmx3g。但 2C4G 机器实际可用内存可能只有 3.5G(系统占一部分),JVM 堆 3G + Metaspace + 线程栈 + 堆外内存(ZGC 也用堆外)+ Ollama 偶尔的内存尖峰,加起来超过物理内存。Linux OOM Killer 直接把容器进程杀了------它不管你 Java 内部怎么想,物理内存不够就杀。

解决

绝不写死 -Xmx,用 MaxRAMPercentage 让 JVM 按容器内存的百分比自适应:

dockerfile 复制代码
# ❌ 危险:写死,容器内存变了它不变
ENTRYPOINT ["java", "-Xmx3g", "-jar", "app.jar"]

# ✅ 安全:按容器内存的 75% 自适应,留 25% 给堆外和系统
ENTRYPOINT ["java", "-XX:MaxRAMPercentage=75.0", "-jar", "app.jar"]

为什么是 75% 而不是 90%?因为堆只是 JVM 内存的一部分:

erlang 复制代码
容器内存 100%
├── JVM 堆(MaxRAMPercentage=75%)
└── 剩余 25%:Metaspace + 线程栈 + ZGC 堆外 + JIT 缓存 + ...

留 25% 给"堆之外的一切",才不会被 OOM Killer 盯上。

教训容器里的 JVM 内存管理和裸机完全不同 。裸机你知道总内存多少,容器里内存是被 cgroup 限制的。永远用百分比(MaxRAMPercentage),永远留足堆外空间。


坑三:冷启动太慢,健康检查把刚启动的容器误杀

现象

部署后容器反复重启,日志显示应用其实正常启动了,但每次刚启动就被 restart 拉走重来。陷入"启动→被杀→重启→被杀"的死循环。

原因

AgentX 冷启动慢------要连 Redis、初始化 Milvus 集合、加载 LangChain4j、连 Ollama,全部就绪可能要 40-50 秒。但健康检查从容器一启动就开始探测:

yaml 复制代码
healthcheck:
  test: [...]
  interval: 30s
  retries: 3
  # 没有 start_period!

容器启动后 30s 第一次探测------这时应用还没起好,失败。再 30s、再 30s,连续 3 次失败,Docker 判定 unhealthy,restart 把它杀了重启。但重启后还是同样的慢启动,再次被杀。死循环。

解决

start_period------给冷启动一个"宽限期",这段时间内的探测失败不计入失败次数:

yaml 复制代码
healthcheck:
  test: ["CMD", "curl", "-s", "--fail", "http://localhost:8080/api/v1/agents/health"]
  interval: 30s
  timeout: 5s
  retries: 3
  start_period: 60s     # ✅ 前 60s 是宽限期,探测失败不算数
配置 含义
start_period: 60s 启动后 60s 内,健康检查失败不计数、不触发重启
interval: 30s 宽限期过后,每 30s 探测一次
retries: 3 连续 3 次失败才判 unhealthy

start_period 要设得比"最坏冷启动时间"略长。AgentX 冷启动约 40-50s,设 60s 留足余量。

教训AI 应用冷启动普遍慢 (大模型加载、向量库初始化)。健康检查一定要配 start_period,否则慢启动会被自愈机制误判成"启动失败",陷入重启死循环。自愈机制本是好事,配错了反而成了帮凶。


六、总结:一张表 + 五条经验

设计决策回顾

设计决策 解决什么问题
三节点拓扑(推理/存储/监控) 三类负载资源特征不同,分开互不抢资源
Docker 多阶段构建 编译/运行分离,镜像从 800MB 瘦到 200MB
Ollama/Redis/Milvus 不容器化 有状态、重量级组件独立部署更稳
配置全外置(.env + 环境变量) 一份镜像跑多环境,改 IP 不动代码
ZGC + MaxRAMPercentage=75% 低延迟 GC + 容器内存自适应,防 OOM
server-init.sh 裸机初始化 动态 Swap + 镜像加速,国内低配云的坑一次处理
deploy.sh 幂等部署 首次/更新统一,拉代码到验证全自动
start_period + restart 自愈 冷启动宽限 + 自动重启,挂了能起来又不误杀

五条核心经验

  1. "本地能跑"和"生产能跑"差着一整套工程 ------ 容器化、编排、配置外置、健康检查、自愈,一个都不能少
  2. 技术选型要匹配规模 ------ 3 台 2C4G 用 docker compose 而非 K8s,K8s 的控制面开销能吃掉一台机器
  3. 容器里的 JVM 必须用百分比内存 ------ 写死 -Xmx 在容器里是 OOM 的头号元凶
  4. 容器网络的 localhost 不是宿主机的 localhost ------ 访问宿主机服务用 host.docker.internal + host-gateway
  5. AI 应用冷启动慢,健康检查必须配 start_period ------ 否则自愈机制会误杀慢启动的容器

部署演进路线

如果你要部署自己的 AI 应用,建议这样推进:

  • 第一阶段:单机 docker compose 把所有组件跑起来,先通
  • 第二阶段:拆分有状态组件(Redis/Milvus/Ollama)到独立节点
  • 第三阶段:写 server-init.sh + deploy.sh,把部署自动化
  • 第四阶段:配健康检查 + 自愈 + 监控(接专栏⑦的 Jaeger)
  • 第五阶段:规模上来后再考虑 K8s + CI/CD 流水线

七、写在最后:专栏收官

这是 AgentX 技术专栏的第十篇,也是收官篇

回顾这一路,从专栏②的技术选型,到架构、工具、RAG、记忆、可观测、工作流、MCP,再到这一篇的生产部署------我们完整地走过了一个企业级 Agent 平台"从 0 到上线"的全过程

解决的问题
②③ 怎么选型、怎么设计架构
④⑤⑥ 工具、知识、记忆------Agent 的核心能力
⑦⑧ 可观测、工作流------让它可控、可编排
MCP------接入全球工具生态
部署上线------让前面所有的努力真正跑起来

写这个专栏最大的感受是:做 AI 应用,难的从来不是调用大模型那一行 API,而是把它工程化------让它稳定、可观测、可部署、可演进 。而这些恰恰是我们 Java 程序员的看家本领。大模型时代不是要抛弃工程经验,而是把工程经验用在新场景。

如果这个专栏对你有帮助,希望它能成为你做 AI 工程的一份参考。代码全部开源,每一篇都有配套代码包。

专栏会暂告一段落,但 AgentX 项目会持续演进------后续可能会写一些进阶专题(多 Agent 协作、Agent 评估、成本优化等)。欢迎关注,我们下个专题再见。

  • 本文部署代码包 --- 公众号回复「部署」获取(含全部脚本 + 三节点配置模板)
  • 完整专栏代码 --- 每篇都有独立代码包,回复对应关键词获取
  • 欢迎交流 --- 评论区或公众号私信,一起把 AI 工程做扎实

感谢一路读到这里的你。🙏


💬 互动话题:你的 AI 应用部署在什么环境?踩过哪些部署的坑?或者你最想看的下一个专题是什么?评论区聊聊。

关注公众号 【SuniaCoder-AI全栈架构实战】 ,回复「部署 」获取本文完整部署代码包,回复「MCP 」获取 MCP 互通代码,回复「工作流」获取工作流引擎代码。


🎉 专栏完结:感谢一路相伴。AgentX 全系列 10 篇,从选型到上线,希望对你做 AI 工程有所帮助。


Tags#AgentX #生产部署 #Docker #DockerCompose #JVM调优 #ZGC #运维部署 #SpringBoot3 #Java21 #云服务器

相关推荐
ZhengEnCi2 小时前
J7A-高级Java工程师面试三道灵魂拷问-深度广度与工程素养的终极检验
java·后端
狼爷20 小时前
吃透 Java Function 接口,搞定 99% 的 Stream 场景
java·函数式编程
祎雪双十Gy1 天前
从 DataX 的配置加载说起:我用 FastJson2 做了一个轻量级动态配置管理库
java·后端
小锋java12341 天前
分享一套锋哥原创的SpringBoot4+Vue3宠物领养网站系统
java
ZhengEnCi1 天前
Q01-高并发点赞系统架构设计
架构
考虑考虑1 天前
Java实现hmacsha1加密算法
java·后端·java ee
掉鱼的猫1 天前
Spring Boot → Solon 注解迁移实战指南:一张对照表说清楚
java·spring boot
笨鸟飞不快1 天前
从 MVC 到 DDD:一次真实的渐进式迁移实录
后端·架构
plainGeekDev1 天前
广播接收器 → Flow + Lifecycle
android·java·kotlin