Spring Cloud+vue3 整合 Comfyui 实战:从零搭建AI人物写真工厂,实现光影复刻与发型穿搭定制》
·
本项目技术架构介绍
前端
- Vue3 + Element Plus
后端
- Spring Cloud 2023.0.3
- Spring Boot 3.3.4
- Java 21
服务治理
- Nacos(注册中心+配置中心)
- OpenFeign(服务调用)
- Spring Cloud Gateway(统一网关)
认证授权
- Spring Security + OAuth2
- 独立认证中心
业务微服务
- 认证中心(OAuth2)
- Gateway网关
- 积分系统(增减/流水)
- 微信支付(V3 Native支付)
- 登录服务
- 图生图(ComfyUI对接)
AIGC核心
- 对接ComfyUI工作流API
- RabbitMQ/RocketMQ异步解耦
- 提供img2img工作流JSON示例
一. 图生图微服务整体架构: 异步任务+模型调度+对象存储
人物写真图生图的耗时通常在 5-15秒 之间(取决于显存和分辨率)。如果让前端HTTP同步等,必然超时或阻塞线程。
正确做法:异步任务模式,这是大厂AI中台的标准方案。
流程拆解:
- 用户提交原图 + 选择风格(古风/证件照/赛博朋克)。
- 后端返回taskId,立即响应“生成中”。
- 后端异步消费队列,调用图生图服务。
- 生成完成后,图片上传OSS/本地,更新任务状态为“已完成”。
- 前端轮询或WebSocket拿到结果URL。
这套架构,Spring Boot只做调度和状态管理,不阻塞主线程,能撑住上千并发
二. Java 实现随机、轮询、最小连接数三策略,高可用图生图调度中心
假设你接了一个AI写真小程序的私活,峰值期 100 个用户同时上传照片生成写真。单机 ComfyUI:
- 显存 24G 最多同时跑 2-3 个任务
- 第 4 个请求直接 OOM 或排队 5 分钟+
- 节点宕机后整个服务不可用
解决方案 - 节点动态注册/摘除
- 实时感知每个节点的当前连接数
- 智能调度:让空闲节点多干活,繁忙节点少干活
核心代码
@Slf4j
@Component
public class ComfyUILoadBalancer {
private final CopyOnWriteArrayList<String> healthyServers = new CopyOnWriteArrayList<>();
private final AtomicInteger roundRobinCounter = new AtomicInteger(0);
private final ConcurrentHashMap<String, AtomicInteger> connectionCounts = new ConcurrentHashMap<>();
private final ComfyUIServerConfig config;
public ComfyUILoadBalancer(ComfyUIServerConfig config) {
this.config = config;
initializeServers();
}
private void initializeServers() {
if (config.getServers() != null && !config.getServers().isEmpty()) {
healthyServers.addAll(config.getServers());
for (String server : config.getServers()) {
connectionCounts.putIfAbsent(server, new AtomicInteger(0));
}
log.info("初始化 ComfyUI 服务器列表: {}", healthyServers);
} else {
log.warn("未配置 ComfyUI 服务器列表");
}
}
public String selectServer() {
if (healthyServers.isEmpty()) {
throw new IllegalStateException("没有可用的 ComfyUI 服务器");
}
switch (config.getStrategy()) {
case ROUND_ROBIN:
return selectByRoundRobin();
case RANDOM:
return selectByRandom();
case LEAST_CONNECTIONS:
return selectByLeastConnections();
default:
return selectByRoundRobin();
}
}
private String selectByRoundRobin() {
int index = Math.abs(roundRobinCounter.getAndIncrement() % healthyServers.size());
String server = healthyServers.get(index);
log.debug("轮询选择服务器: {}, 当前连接数: {}", server, getConnectionCount(server));
incrementConnection(server);
return server;
}
private String selectByRandom() {
int index = (int) (Math.random() * healthyServers.size());
String server = healthyServers.get(index);
log.debug("随机选择服务器: {}, 当前连接数: {}", server, getConnectionCount(server));
incrementConnection(server);
return server;
}
private String selectByLeastConnections() {
String selectedServer = healthyServers.get(0);
int minConnections = getConnectionCount(selectedServer);
for (String server : healthyServers) {
int connections = getConnectionCount(server);
if (connections < minConnections) {
minConnections = connections;
selectedServer = server;
}
}
log.debug("最少连接选择服务器: {}, 当前连接数: {}", selectedServer, minConnections);
incrementConnection(selectedServer);
return selectedServer;
}
public void markServerHealthy(String server) {
if (!healthyServers.contains(server)) {
healthyServers.add(server);
connectionCounts.putIfAbsent(server, new AtomicInteger(0));
log.info("服务器标记为健康: {}", server);
}
}
public void markServerUnhealthy(String server) {
if (healthyServers.remove(server)) {
connectionCounts.remove(server);
log.warn("服务器标记为不健康: {}", server);
}
}
public void incrementConnection(String server) {
AtomicInteger count = connectionCounts.get(server);
if (count != null) {
int newCount = count.incrementAndGet();
log.debug("服务器 {} 连接数增加到: {}", server, newCount);
}
}
public void decrementConnection(String server) {
AtomicInteger count = connectionCounts.get(server);
if (count != null) {
int newCount = count.decrementAndGet();
if (newCount < 0) {
count.set(0);
}
log.debug("服务器 {} 连接数减少到: {}", server, newCount);
}
}
public int getConnectionCount(String server) {
AtomicInteger count = connectionCounts.get(server);
return count != null ? count.get() : 0;
}
public List<String> getHealthyServers() {
return healthyServers;
}
public Map<String, Integer> getAllConnectionCounts() {
ConcurrentHashMap<String, Integer> result = new ConcurrentHashMap<>();
for (Map.Entry<String, AtomicInteger> entry : connectionCounts.entrySet()) {
result.put(entry.getKey(), entry.getValue().get());
}
return result;
}
public void updateServers(List<String> newServers) {
healthyServers.clear();
connectionCounts.clear();
healthyServers.addAll(newServers);
for (String server : newServers) {
connectionCounts.putIfAbsent(server, new AtomicInteger(0));
}
roundRobinCounter.set(0);
log.info("更新 ComfyUI 服务器列表: {}", healthyServers);
}
}
项目页面预览,提供与sd相同的提示词
来展示一下效果图
原图
生成之后的图片
由于节约成本 本项目 只部署单个comfyui节点,仅供娱乐
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)