负载均衡基本改造,增加redis、miniio等基本中间件

This commit is contained in:
2026-02-24 11:16:03 +08:00
parent 26677972a6
commit 8d711dc3a2
13 changed files with 317 additions and 63 deletions

View File

@@ -10,9 +10,13 @@ services:
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/easyflow?useInformationSchema=true&useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/easyflow?useInformationSchema=true&useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai
- SPRING_DATASOURCE_USERNAME=root - SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=123456 - SPRING_DATASOURCE_PASSWORD=123456
- SPRING_REDIS_HOST=redis - SERVER_PORT=8080
- SPRING_REDIS_PASSWORD=${REDIS_PASSWORD:-easyflow_redis_2026} - SPRING_DATA_REDIS_HOST=redis
- SPRING_DATA_REDIS_PORT=6379
- SPRING_DATA_REDIS_PASSWORD=${REDIS_PASSWORD:-easyflow_redis_2026}
- SPRING_DATA_REDIS_DATABASE=0
- SPRING_WEB_RESOURCES_STATIC_LOCATIONS=file:/www/easyflow/attachment/ - SPRING_WEB_RESOURCES_STATIC_LOCATIONS=file:/www/easyflow/attachment/
- EASYFLOW_STORAGE_TYPE=local
- EASYFLOW_STORAGE_LOCAL_ROOT=/www/easyflow/attachment - EASYFLOW_STORAGE_LOCAL_ROOT=/www/easyflow/attachment
networks: networks:
- easyflow-net - easyflow-net

View File

@@ -17,6 +17,7 @@ import tech.easyflow.ai.service.DocumentCollectionService;
import tech.easyflow.ai.service.DocumentService; import tech.easyflow.ai.service.DocumentService;
import tech.easyflow.ai.service.ModelService; import tech.easyflow.ai.service.ModelService;
import tech.easyflow.common.annotation.UsePermission; import tech.easyflow.common.annotation.UsePermission;
import tech.easyflow.common.cache.RedisLockExecutor;
import tech.easyflow.common.domain.Result; import tech.easyflow.common.domain.Result;
import tech.easyflow.common.tree.Tree; import tech.easyflow.common.tree.Tree;
import tech.easyflow.common.util.RequestUtil; import tech.easyflow.common.util.RequestUtil;
@@ -29,6 +30,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigInteger; import java.math.BigInteger;
import java.time.Duration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@@ -44,14 +46,21 @@ import java.util.List;
@UsePermission(moduleName = "/api/v1/documentCollection") @UsePermission(moduleName = "/api/v1/documentCollection")
public class DocumentController extends BaseCurdController<DocumentService, Document> { public class DocumentController extends BaseCurdController<DocumentService, Document> {
private static final String DOCUMENT_ORDER_LOCK_KEY_PREFIX = "easyflow:lock:document:order:";
private static final Duration LOCK_WAIT_TIMEOUT = Duration.ofSeconds(2);
private static final Duration LOCK_LEASE_TIMEOUT = Duration.ofSeconds(10);
private final DocumentCollectionService knowledgeService; private final DocumentCollectionService knowledgeService;
@Autowired @Autowired
private DocumentService documentService; private DocumentService documentService;
@Autowired
private RedisLockExecutor redisLockExecutor;
@Value("${easyflow.storage.local.root}")
@Value("${easyflow.storage.local.root:}")
private String fileUploadPath; private String fileUploadPath;
@@ -132,6 +141,7 @@ public class DocumentController extends BaseCurdController<DocumentService, Docu
@PostMapping("update") @PostMapping("update")
@Override @Override
@Transactional
@SaCheckPermission("/api/v1/documentCollection/save") @SaCheckPermission("/api/v1/documentCollection/save")
public Result<Boolean> update(@JsonBody Document entity) { public Result<Boolean> update(@JsonBody Document entity) {
super.update(entity); super.update(entity);
@@ -158,28 +168,41 @@ public class DocumentController extends BaseCurdController<DocumentService, Docu
Integer orderNo = entity.getOrderNo(); Integer orderNo = entity.getOrderNo();
if (orderNo != null) { if (orderNo != null) {
if (orderNo <= 0) orderNo = 0; if (orderNo <= 0) orderNo = 0;
BigInteger knowledgeId = service.getById(entity.getId()).getCollectionId(); Document current = service.getById(entity.getId());
List<Document> list = service.list(QueryWrapper.create() if (current == null) {
.eq(Document::getCollectionId, knowledgeId) throw new BusinessException("文档不存在");
.orderBy(getDefaultOrderBy()) }
BigInteger knowledgeId = current.getCollectionId();
Integer targetOrderNo = orderNo;
redisLockExecutor.executeWithLock(
DOCUMENT_ORDER_LOCK_KEY_PREFIX + knowledgeId,
LOCK_WAIT_TIMEOUT,
LOCK_LEASE_TIMEOUT,
() -> {
List<Document> list = service.list(QueryWrapper.create()
.eq(Document::getCollectionId, knowledgeId)
.orderBy(getDefaultOrderBy())
);
list.removeIf(item -> item.getId().equals(entity.getId()));
if (targetOrderNo >= list.size()) {
list.add(entity);
} else {
list.add(targetOrderNo, entity);
}
List<Document> updateList = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
Document updateItem = new Document();
updateItem.setId(list.get(i).getId());
updateItem.setOrderNo(i);
updateList.add(updateItem);
}
service.updateBatch(updateList);
}
); );
list.removeIf(item -> item.getId().equals(entity.getId()));
if (orderNo >= list.size()) {
list.add(entity);
} else {
list.add(orderNo, entity);
}
List<Document> updateList = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
Document updateItem = new Document();
updateItem.setId(list.get(i).getId());
updateItem.setOrderNo(i);
updateList.add(updateItem);
}
service.updateBatch(updateList);
} }
return true; return true;

View File

@@ -20,7 +20,7 @@ import java.nio.file.Files;
public class FilePreviewController { public class FilePreviewController {
// 定义图片存储的基础路径 // 定义图片存储的基础路径
@Value("${easyflow.storage.local.root}") @Value("${easyflow.storage.local.root:}")
private String fileUploadPath; private String fileUploadPath;
@SaIgnore @SaIgnore

View File

@@ -33,6 +33,10 @@
<groupId>cn.dev33</groupId> <groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot3-starter</artifactId> <artifactId>sa-token-spring-boot3-starter</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.squareup.okhttp3</groupId> <groupId>com.squareup.okhttp3</groupId>
@@ -53,6 +57,10 @@
<groupId>org.apache.httpcomponents.client5</groupId> <groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId> <artifactId>httpclient5</artifactId>
</dependency> </dependency>
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -3,40 +3,82 @@ package tech.easyflow.common.filestorage.impl;
import org.dromara.x.file.storage.core.FileInfo; import org.dromara.x.file.storage.core.FileInfo;
import org.dromara.x.file.storage.core.recorder.FileRecorder; import org.dromara.x.file.storage.core.recorder.FileRecorder;
import org.dromara.x.file.storage.core.upload.FilePartInfo; import org.dromara.x.file.storage.core.upload.FilePartInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.Date;
/** /**
* 文件记录器 * 文件记录器(基于 Redis 存储上传记录,满足多实例共享)
*/ */
@Service @Service
public class FileRecoderImpl implements FileRecorder { public class FileRecoderImpl implements FileRecorder {
private static final Logger LOG = LoggerFactory.getLogger(FileRecoderImpl.class);
private static final String FILE_RECORD_KEY_PREFIX = "easyflow:xfile:record:";
@Autowired(required = false)
private RedisTemplate<String, Object> redisTemplate;
private String buildKey(String url) {
return FILE_RECORD_KEY_PREFIX + url;
}
@Override @Override
public boolean save(FileInfo fileInfo) { public boolean save(FileInfo fileInfo) {
if (fileInfo == null || !StringUtils.hasText(fileInfo.getUrl())) {
return false;
}
if (fileInfo.getCreateTime() == null) {
fileInfo.setCreateTime(new Date());
}
if (redisTemplate != null) {
redisTemplate.opsForValue().set(buildKey(fileInfo.getUrl()), fileInfo);
}
return true; return true;
} }
@Override @Override
public void update(FileInfo fileInfo) { public void update(FileInfo fileInfo) {
save(fileInfo);
} }
@Override @Override
public FileInfo getByUrl(String url) { public FileInfo getByUrl(String url) {
if (!StringUtils.hasText(url) || redisTemplate == null) {
return null;
}
Object value = redisTemplate.opsForValue().get(buildKey(url));
if (value == null) {
return null;
}
if (value instanceof FileInfo) {
return (FileInfo) value;
}
LOG.warn("FileInfo redis记录类型异常url={}, class={}", url, value.getClass().getName());
return null; return null;
} }
@Override @Override
public boolean delete(String url) { public boolean delete(String url) {
return true; if (!StringUtils.hasText(url) || redisTemplate == null) {
return false;
}
Boolean deleted = redisTemplate.delete(buildKey(url));
return Boolean.TRUE.equals(deleted);
} }
@Override @Override
public void saveFilePart(FilePartInfo filePartInfo) { public void saveFilePart(FilePartInfo filePartInfo) {
// 当前业务未使用手动分片上传,不做持久化
} }
@Override @Override
public void deleteFilePartByUploadId(String uploadId) { public void deleteFilePartByUploadId(String uploadId) {
// 当前业务未使用手动分片上传,不做持久化
} }
} }

View File

@@ -25,7 +25,7 @@ public class LocalFileStorageServiceImpl implements FileStorageService {
@Value("${easyflow.storage.local.root:}") @Value("${easyflow.storage.local.root:}")
private String root; private String root;
@Value("${easyflow.storage.local.prefix}") @Value("${easyflow.storage.local.prefix:}")
private String prefix; private String prefix;
@EventListener(ApplicationReadyEvent.class) @EventListener(ApplicationReadyEvent.class)

View File

@@ -5,6 +5,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import tech.easyflow.common.filestorage.FileStorageService; import tech.easyflow.common.filestorage.FileStorageService;
import tech.easyflow.common.filestorage.utils.PathGeneratorUtil; import tech.easyflow.common.filestorage.utils.PathGeneratorUtil;
@@ -22,17 +23,33 @@ public class XFIleStorageServiceImpl implements FileStorageService {
@Override @Override
public String save(MultipartFile file) { public String save(MultipartFile file) {
return save(file, null);
}
@Override
public String save(MultipartFile file, String prePath) {
String uploadPath = PathGeneratorUtil.generateUserPath("");
if (StringUtils.hasText(prePath)) {
String normalized = prePath.replaceAll("^/+", "").replaceAll("/+$", "");
uploadPath = "/" + normalized + uploadPath;
}
FileInfo fileInfo = fileStorageService.of(file) FileInfo fileInfo = fileStorageService.of(file)
.setPath(PathGeneratorUtil.generateUserPath("")) .setPath(uploadPath)
.setSaveFilename(file.getOriginalFilename()) .setSaveFilename(file.getOriginalFilename())
.setContentType(getFileContentType(file)) .setContentType(getFileContentType(file))
.upload(); .upload();
return fileInfo == null ? "上传失败!" : fileInfo.getUrl(); if (fileInfo == null || !StringUtils.hasText(fileInfo.getUrl())) {
throw new RuntimeException("文件上传失败");
}
return fileInfo.getUrl();
} }
@Override @Override
public void delete(String path) { public void delete(String path) {
fileStorageService.delete(path); boolean deleted = fileStorageService.delete(path);
if (!deleted) {
LOG.warn("删除文件失败或文件不存在path={}", path);
}
} }
@Override @Override

View File

@@ -68,6 +68,10 @@
<groupId>org.yaml</groupId> <groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId> <artifactId>snakeyaml</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@@ -6,3 +6,13 @@ spring:
url: jdbc:mysql://127.0.0.1:3306/easyflow?useInformationSchema=true&characterEncoding=utf-8 url: jdbc:mysql://127.0.0.1:3306/easyflow?useInformationSchema=true&characterEncoding=utf-8
username: easyflow username: easyflow
password: 123456 password: 123456
data:
redis:
host: 127.0.0.1
port: 6379
database: 0
password: ${REDIS_PASSWORD:123456}
easyflow:
storage:
type: xFileStorage

View File

@@ -10,14 +10,24 @@ server:
enabled: true enabled: true
charset: UTF-8 # 必须设置 UTF-8避免 WebFlux 流式返回AI 场景)会乱码问题 charset: UTF-8 # 必须设置 UTF-8避免 WebFlux 流式返回AI 场景)会乱码问题
force: true force: true
spring: spring:
profiles: profiles:
active: dev active: dev
lifecycle:
timeout-per-shutdown-phase: 30s
datasource: datasource:
# 注意useInformationSchema=true 是必须的,用于支持 MyBatis-Flex 正确读取表注释。 # 注意useInformationSchema=true 是必须的,用于支持 MyBatis-Flex 正确读取表注释。
url: jdbc:mysql://127.0.0.1:23306/easyflow?useInformationSchema=true&characterEncoding=utf-8 url: jdbc:mysql://127.0.0.1:23306/easyflow?useInformationSchema=true&characterEncoding=utf-8
username: root username: root
password: root password: root
data:
redis:
host: 127.0.0.1
port: 6379
database: 0
password: ${REDIS_PASSWORD:123456}
timeout: 5s
servlet: servlet:
multipart: multipart:
max-file-size: 100MB max-file-size: 100MB
@@ -42,16 +52,23 @@ spring:
properties: properties:
org: org:
quartz: quartz:
scheduler:
instanceName: easyflowScheduler
instanceId: AUTO
jobStore: jobStore:
misfireThreshold: 1000 misfireThreshold: 1000
isClustered: true
clusterCheckinInterval: 15000
# 如果数据库大小写敏感可将ddl里的相关表名改为大写 # 如果数据库大小写敏感可将ddl里的相关表名改为大写
tablePrefix: TB_QRTZ_ tablePrefix: TB_QRTZ_
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
threadPool: threadPool:
threadCount: 20 threadCount: 20
threadPriority: 5 threadPriority: 5
threads: threads:
virtual: virtual:
enabled: true enabled: true
easyflow: easyflow:
# 语音播放、识别服务(阿里云) # 语音播放、识别服务(阿里云)
audio: audio:
@@ -65,26 +82,30 @@ easyflow:
# 放行接口路径 # 放行接口路径
excludes: /api/v1/auth/**, /static/**, /userCenter/auth/**, /userCenter/public/** excludes: /api/v1/auth/**, /static/**, /userCenter/auth/**, /userCenter/public/**
storage: storage:
type: local # xFileStorage / local # local / xFileStorage
# 本地文件存储配置 type: xFileStorage
# 本地文件存储配置(兼容保留,可作为回退)
local: local:
# 示例windows【C:\easyflow\attachment】 linux【/www/easyflow/attachment】 # 示例windows【C:\easyflow\attachment】 linux【/www/easyflow/attachment】
root: /Users/slience/postgraduate/easyflow/attachment root: /Users/slience/postgraduate/easyflow/attachment
# 后端接口地址,用于拼接完整 url # 后端接口地址,用于拼接完整 url
prefix: http://localhost:8080/attachment prefix: http://localhost:8111/attachment
# xFileStorage存储文件配置 # xFileStorage存储文件配置
# 文档https://x-file-storage.xuyanwu.cn/
dromara: dromara:
x-file-storage: #文件存储配置 x-file-storage:
default-platform: aliyun-oss-1 #默认使用的存储平台 default-platform: minio-1
aliyun-oss: minio:
- platform: aliyun-oss-1 # 存储平台标识 - platform: minio-1
enable-storage: true # 启用存储 enable-storage: true
access-key: yourAccessKeyId access-key: ${MINIO_ACCESS_KEY:easyflowadmin}
secret-key: yourAccessKeySecret secret-key: ${MINIO_SECRET_KEY:easyflowadmin123}
end-point: yourEndpoint # 示例:https://oss-cn-beijing.aliyuncs.com end-point: ${MINIO_ENDPOINT:http://127.0.0.1:9000}
bucket-name: yourBucketName bucket-name: ${MINIO_BUCKET:easyflow}
domain: yourDomain # 访问域名,注意“/”结尾,例如:https://bucketname.oss-cn-shanghai.aliyuncs.com/ domain: ${MINIO_DOMAIN:http://127.0.0.1:9000/easyflow/}
base-path: attachment # 基础路径 base-path: attachment
# 自定义节点相关配置 # 自定义节点相关配置
node: node:
# 文件内容提取节点,默认使用简单文档读取器,可自行实现 ReadDocService # 文件内容提取节点,默认使用简单文档读取器,可自行实现 ReadDocService
@@ -95,9 +116,10 @@ node:
# 搜索引擎节点 - 目前只支持博查搜索 # 搜索引擎节点 - 目前只支持博查搜索
bochaai: bochaai:
apiKey: 'xxx' apiKey: 'xxx'
jetcache: jetcache:
# 缓存类型可选值local/remote/both CacheConfig 类初始化 # 缓存类型可选值local/remote/both CacheConfig 类初始化
cacheType: local cacheType: remote
statIntervalMinutes: 15 statIntervalMinutes: 15
areaInCacheName: false areaInCacheName: false
local: local:
@@ -108,17 +130,18 @@ jetcache:
default: default:
type: redis type: redis
keyConvertor: fastjson2 keyConvertor: fastjson2
broadcastChannel: projectA broadcastChannel: easyflow-cache
valueEncoder: java valueEncoder: java
valueDecoder: java valueDecoder: java
poolConfig: poolConfig:
minIdle: 5 minIdle: 5
maxIdle: 20 maxIdle: 20
maxTotal: 50 maxTotal: 50
host: 127.0.0.1 host: ${spring.data.redis.host}
port: 6379 port: ${spring.data.redis.port}
password: pwd password: ${spring.data.redis.password}
database: 0 database: ${spring.data.redis.database}
# 多路召回搜索引擎配置 # 多路召回搜索引擎配置
rag: rag:
searcher: searcher:
@@ -130,6 +153,7 @@ rag:
userName: elastic userName: elastic
password: elastic password: elastic
indexName: easyflow indexName: easyflow
logging: logging:
file: file:
path: .logs/ path: .logs/
@@ -137,6 +161,7 @@ logging:
level: level:
root: info root: info
tech.easyflow.ai: debug tech.easyflow.ai: debug
# 行为验证码配置 # 行为验证码配置
captcha: captcha:
# 初始化默认资源 # 初始化默认资源
@@ -144,3 +169,14 @@ captcha:
# 开启二次验证 # 开启二次验证
secondary: secondary:
enabled: true enabled: true
management:
endpoint:
health:
probes:
enabled: true
show-details: always
endpoints:
web:
exposure:
include: health,info

View File

@@ -40,6 +40,17 @@ http {
# text/javascript; #设置压缩的文件类型 # text/javascript; #设置压缩的文件类型
# gzip_vary on; # gzip_vary on;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# 如需多机负载均衡,在此增加多个后端地址
upstream easyflow_api {
server easyflow-api:8080;
keepalive 64;
}
server { server {
listen 8080; listen 8080;
server_name localhost; server_name localhost;
@@ -60,20 +71,47 @@ http {
} }
} }
location /api/ { # WebSocket语音链路
proxy_pass http://easyflow-api:8080; location /api/v1/bot/ws/audio {
proxy_pass http://easyflow_api;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
# SSE/HTTP API
location /api/ {
proxy_pass http://easyflow_api;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
proxy_cache off;
} }
location /userCenter/ { location /userCenter/ {
proxy_pass http://easyflow-api:8080; proxy_pass http://easyflow_api;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
proxy_cache off;
} }
error_page 500 502 503 504 /50x.html; error_page 500 502 503 504 /50x.html;

View File

@@ -40,6 +40,17 @@ http {
# text/javascript; #设置压缩的文件类型 # text/javascript; #设置压缩的文件类型
# gzip_vary on; # gzip_vary on;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# 如需多机负载均衡,在此增加多个后端地址
upstream easyflow_api {
server easyflow-api:8080;
keepalive 64;
}
server { server {
listen 8080; listen 8080;
server_name localhost; server_name localhost;
@@ -60,20 +71,47 @@ http {
} }
} }
location /api/ { # WebSocket语音链路
proxy_pass http://easyflow-api:8080; location /api/v1/bot/ws/audio {
proxy_pass http://easyflow_api;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
# SSE/HTTP API
location /api/ {
proxy_pass http://easyflow_api;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
proxy_cache off;
} }
location /userCenter/ { location /userCenter/ {
proxy_pass http://easyflow-api:8080; proxy_pass http://easyflow_api;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
proxy_cache off;
} }
error_page 500 502 503 504 /50x.html; error_page 500 502 503 504 /50x.html;

34
pom.xml
View File

@@ -33,12 +33,15 @@
<commonmark.version>0.18.0</commonmark.version> <commonmark.version>0.18.0</commonmark.version>
<jsoup.version>1.16.1</jsoup.version> <jsoup.version>1.16.1</jsoup.version>
<commons-io.version>2.18.0</commons-io.version> <commons-io.version>2.18.0</commons-io.version>
<commons-compress.version>1.28.0</commons-compress.version>
<fastexcel.version>1.2.0</fastexcel.version> <fastexcel.version>1.2.0</fastexcel.version>
<hutool.version>5.8.36</hutool.version> <hutool.version>5.8.36</hutool.version>
<websocket.version>1.5.3</websocket.version> <websocket.version>1.5.3</websocket.version>
<snakeyaml.version>2.4</snakeyaml.version> <snakeyaml.version>2.4</snakeyaml.version>
<x-file-storage.version>2.2.1</x-file-storage.version> <x-file-storage.version>2.2.1</x-file-storage.version>
<aliyun-oss.version>3.16.1</aliyun-oss.version> <aliyun-oss.version>3.16.1</aliyun-oss.version>
<minio.version>8.5.2</minio.version>
<jackson.version>2.19.4</jackson.version>
<netty.version>4.1.130.Final</netty.version> <netty.version>4.1.130.Final</netty.version>
</properties> </properties>
<dependencyManagement> <dependencyManagement>
@@ -216,6 +219,26 @@
<artifactId>spring-boot-starter-validation</artifactId> <artifactId>spring-boot-starter-validation</artifactId>
<version>${spring-boot.version}</version> <version>${spring-boot.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
@@ -247,6 +270,12 @@
<version>${commons-io.version}</version> <version>${commons-io.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>${commons-compress.version}</version>
</dependency>
<dependency> <dependency>
<groupId>cn.idev.excel</groupId> <groupId>cn.idev.excel</groupId>
<artifactId>fastexcel</artifactId> <artifactId>fastexcel</artifactId>
@@ -420,6 +449,11 @@
<artifactId>aliyun-sdk-oss</artifactId> <artifactId>aliyun-sdk-oss</artifactId>
<version>${aliyun-oss.version}</version> <version>${aliyun-oss.version}</version>
</dependency> </dependency>
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>${minio.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.easyagents</groupId> <groupId>com.easyagents</groupId>