负载均衡基本改造,增加redis、miniio等基本中间件
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
// 当前业务未使用手动分片上传,不做持久化
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
34
pom.xml
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user