迁移服务器;分开开发端与生产端;去除废弃接口;对象存储、Kong网关使用SSL;修改所有使用内网地址的代码;切换域名;更新Ktor、ws-scrcpy启动服务;修改Prometheus配置;

This commit is contained in:
BBIT-Kai
2025-10-28 16:33:54 +08:00
parent 08eb2d84eb
commit 2e0a2633bc
23 changed files with 153 additions and 119 deletions
+3
View File
@@ -6,4 +6,7 @@
<option name="sdkName" value="bbit_ai_lab" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="bbit_ai_lab" project-jdk-type="Python SDK" />
<component name="PyPackaging">
<option name="earlyReleasesAsUpgrades" value="true" />
</component>
</project>
+1 -5
View File
@@ -4,7 +4,6 @@ from fastapi.middleware.cors import CORSMiddleware
from routers.Bot import botRouter
from routers.Chat import chatRouter
from routers.Datasource import reportDataRouter
from routers.F8 import f8Router
from routers.Knowledge import knowledgeRouter
from routers.Public import publicRouter
from routers.RabbitMQ import rqRouter
@@ -18,8 +17,7 @@ app = FastAPI(title="BBIT_AI")
origins = [
"http://localhost:8090", # Vite dev 默认端口
"http://127.0.0.1:5173",
"http://s1.ronsunny.cn:8089",
"https://ai.ronsunny.cn:8090",
"*", # ⚠️ 生产环境不要用
]
@@ -44,8 +42,6 @@ routers = [
for r in routers:
app.include_router(r, prefix="/llm", tags=["llm"])
app.include_router(f8Router, prefix="/f8", tags=["f8"])
app.include_router(publicRouter, prefix="/api/public", tags=["api"])
MyUtils.async_new_task(mq_pull_analysis)
-2
View File
@@ -1,3 +1 @@
SERVER_PATH_OSS = "s1.ronsunny.cn"
F8_SERVER_USER_ID = "da33efb9-776a-443b-b1ec-dbbbf08793d7"
+3 -4
View File
@@ -1,7 +1,8 @@
from langchain_milvus import BM25BuiltInFunction, Milvus
from langchain_milvus import Milvus
from config.llm import llmEmbeddings
URI = "http://10.10.10.9:19530"
URI = "http://ce_milvus:19530"
knVectorstore = Milvus(
embedding_function=llmEmbeddings,
@@ -10,7 +11,6 @@ knVectorstore = Milvus(
index_params={"index_type": "FLAT", "metric_type": "L2"},
consistency_level="Strong",
auto_id=True,
primary_field="id",
text_field="text",
vector_field="vector",
@@ -25,7 +25,6 @@ memVectorstore = Milvus(
index_params={"index_type": "FLAT", "metric_type": "L2"},
consistency_level="Strong",
auto_id=True,
primary_field="id",
text_field="text",
vector_field="vector",
+3 -2
View File
@@ -4,10 +4,11 @@ from minio import Minio
# MinIO 客户端初始化
minio_client = Minio(
"s1.ronsunny.cn:9000",
"ai.ronsunny.cn:9000",
access_key="minioadmin",
secret_key="minioadmin",
secure=False,
region="Chengdu",
secure=True,
)
+5 -2
View File
@@ -1,13 +1,14 @@
import logging
import time
from contextlib import contextmanager
from typing import Optional
import psycopg
from psycopg_pool import ConnectionPool
logger = logging.getLogger("PGPool")
logger.setLevel(logging.INFO)
class PGPool:
"""
PostgreSQL 连接池封装
@@ -62,8 +63,10 @@ class PGPool:
logger.error(f"SQL执行异常: {e}")
raise
raise psycopg.OperationalError("无法获取数据库连接,多次重试失败")
pg_pool = PGPool(
uri="postgresql://postgres:123456@10.10.10.9/ktor2",
uri="postgresql://postgres:123456@ce_postgres/ktor2",
min_size=1,
max_size=20,
)
+1 -1
View File
@@ -1,4 +1,4 @@
RABBIT_HOST = "10.10.10.9"
RABBIT_HOST = "ce_rabbitmq"
RABBIT_VHOST = "/bbit_ai"
RABBIT_USER = "bbit_ai"
RABBIT_PASSWORD = "123456"
-54
View File
@@ -1,54 +0,0 @@
import base64
from fastapi import APIRouter
from config.app import F8_SERVER_USER_ID
from models.BaseResponse import BaseResponse
from models.F8ImageRequest import F8ImageRequest
from models.F8ImageRequestV2 import F8ImageRequestV2
from service.vision import process_ticket_image
from utils import MyUtils
f8Router = APIRouter()
@f8Router.post("/createTicketImageTask")
async def cocoonTicket(data: F8ImageRequest):
input_data = data.image
if "," in input_data:
input_data = input_data.split(",")[1]
try:
img_bytes = base64.b64decode(input_data)
json_data = await MyUtils.async_task(
process_ticket_image,
1,
True,
img_bytes,
f"{data.title}.jpg",
data.title,
F8_SERVER_USER_ID,
)
return BaseResponse(data=json_data)
except Exception as e:
return BaseResponse(status=False, message=f"解析失败: {str(e)}", data=None)
@f8Router.post("/createTicketImageTaskV2")
async def cocoonTicket(data: F8ImageRequestV2):
input_data = data.image
if "," in input_data:
input_data = input_data.split(",")[1]
try:
img_bytes = base64.b64decode(input_data)
json_data = await MyUtils.async_task(
process_ticket_image,
2,
data.needBarcode,
img_bytes,
f"{data.title}.jpg",
data.title,
F8_SERVER_USER_ID,
)
return BaseResponse(data=json_data)
except Exception as e:
return BaseResponse(status=False, message=f"解析失败: {str(e)}", data=None)
+45
View File
@@ -0,0 +1,45 @@
# 使用官方 Python 镜像
FROM python:3.10-slim
WORKDIR /app
RUN apt-get update && \
apt-get install -y --no-install-recommends \
libpq5 \
unixodbc \
curl \
gnupg \
apt-transport-https \
lsb-release && \
# 导入微软 GPG key(使用 keyrings 方式)
curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /usr/share/keyrings/microsoft.gpg && \
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/microsoft.gpg] https://packages.microsoft.com/ubuntu/22.04/prod jammy main" > /etc/apt/sources.list.d/mssql-release.list && \
apt-get update && \
ACCEPT_EULA=Y apt-get install -y msodbcsql18 && \
rm -rf /var/lib/apt/lists/*
COPY ./bbit_ai/docker/requirements.txt .
# 安装 Python 依赖
RUN pip install --no-cache-dir -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
# 复制并解压 JRE
COPY ./bbit_ai/docker/OpenJDK17U-jre_x64_linux_hotspot_17.0.16_8.tar.gz /opt/
RUN tar -xzf /opt/OpenJDK17U-jre_x64_linux_hotspot_17.0.16_8.tar.gz -C /opt/ && \
rm /opt/OpenJDK17U-jre_x64_linux_hotspot_17.0.16_8.tar.gz
# 配置 Java 环境
ENV JAVA_HOME=/opt/jdk-17.0.16+8-jre
ENV PATH="$JAVA_HOME/bin:$PATH"
# 复制项目代码
COPY ./bbit_ai/app/ .
# 复制 pyzxing 的 jar 文件到默认路径
COPY ./bbit_ai/docker/javase-3.4.1-SNAPSHOT-jar-with-dependencies.jar /root/.local/pyzxing/javase-3.4.1-SNAPSHOT-jar-with-dependencies.jar
EXPOSE 13011
# 启动命令(使用 uvicorn 启动 FastAPI
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "13011", "--reload"]
@@ -38,7 +38,7 @@ import kotlin.text.Charsets.UTF_8
// 配置和初始化 Redis 客户端
fun setupRedis(): RedissonClient {
val config = Config()
config.useSingleServer().setAddress("redis://10.10.10.9:6379")
config.useSingleServer().setAddress("redis://localhost:6379")
return Redisson.create(config)
}
@@ -9,7 +9,8 @@ import java.util.concurrent.TimeUnit
object OSSUtils {
private val client: MinioClient = MinioClient.builder()
.endpoint("http://10.10.10.9:9000") // 你的MinIO地址
.endpoint("ai.ronsunny.cn",9000,true) // 你的MinIO地址
.region("Chengdu")
.credentials("minioadmin", "minioadmin") // 账号密码
.build()
@@ -14,7 +14,7 @@ fun Application.configureCORS() {
allowHost("localhost:8089")
allowHost("127.0.0.1:8089")
allowHost("171.212.101.199:8089")
allowHost("s1.ronsunny.cn:8089")
allowHost("ai.ronsunny.cn:8089")
// 进一步配置 CORS
allowMethod(HttpMethod.Get)
+2 -2
View File
@@ -16,8 +16,8 @@ ktor:
realm: "Snowflake Server"
secret: "secret_jwt"
database:
url: "jdbc:postgresql://10.10.10.9:5432/ktor2"
# url: "jdbc:postgresql://localhost:5432/ktor2"
# url: "jdbc:postgresql://10.10.10.9:5432/ktor2"
url: "jdbc:postgresql://localhost:5432/ktor2"
driver: "org.postgresql.Driver"
user: "postgres"
password: "123456"
@@ -29,19 +29,20 @@ scrape_configs:
- job_name: 'redis'
static_configs:
- targets:
- ce_redis_exporter:9121
- targets: ['ce_redis_exporter:9121']
- job_name: 'node_exporter'
static_configs:
- targets: ['10.10.10.9:9100']
- targets: ['172.17.0.1:9100']
- job_name: 'minio'
scheme: https
metrics_path: /minio/v2/metrics/cluster
static_configs:
- targets: ['10.10.10.9:9000']
- targets: ['ai.ronsunny.cn:9000']
- job_name: 'docker'
static_configs:
- targets: ['10.10.10.9:9323']
- targets: ['172.17.0.1:9323']
+4 -4
View File
@@ -2,7 +2,7 @@ services:
# ---------- Vue 前端 ----------
vue:
container_name: ce_vue
image: s1.ronsunny.cn:13011/bbit_ai/ce_vue:latest
image: ai.ronsunny.cn:13011/bbit_ai/ce_vue:latest
networks:
- ce_network
restart: always
@@ -10,14 +10,14 @@ services:
# ---------- Python 后端 ----------
backend:
container_name: ce_pybackend
image: s1.ronsunny.cn:13011/bbit_ai/ce_pybackend:latest
image: ai.ronsunny.cn:13011/bbit_ai/ce_pybackend:latest
networks:
- ce_network
restart: unless-stopped
depends_on:
- vue
extra_hosts:
- "s1.ronsunny.cn:10.10.10.9"
volumes:
- /home/bbit/ssl/ai.ronsunny.cn.pem:/ssl/ai.ronsunny.cn.pem
# ---------- 网络 ----------
networks:
+44 -5
View File
@@ -55,6 +55,8 @@ services:
- "9001:9001"
volumes:
- minio_data:/data
- /home/bbit/ssl/ai.ronsunny.cn.pem:/root/.minio/certs/public.crt
- /home/bbit/ssl/ai.ronsunny.cn.key:/root/.minio/certs/private.key
networks:
- ce_network
command: server /data --console-address ":9001"
@@ -95,12 +97,21 @@ services:
- seccomp:unconfined
environment:
ETCD_ENDPOINTS: etcd:2379
MINIO_ADDRESS: minio:9000
MQ_TYPE: woodpecker
MINIO_ADDRESS: ai.ronsunny.cn:9000
MINIO_BUCKET_NAME: a-bucket
MINIO_USE_SSL: true
MINIO_ACCESS_KEY_ID: minioadmin
MINIO_SECRET_ACCESS_KEY: minioadmin
MINIO_REGION: Chengdu
# MINIO_CA_PATH: /ssl/certs/
networks:
- ce_network
volumes:
- milvus_data:/var/lib/milvus
- /home/bbit/ssl/ai.ronsunny.cn.pem:/ssl/public.crt
# - /home/bbit/ssl/ai.ronsunny.cn.key:/ssl/private.key
# - ./config/milvus/milvus.yaml:/milvus/configs/milvus.yaml
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"]
interval: 30s
@@ -166,10 +177,13 @@ services:
KONG_PROXY_ERROR_LOG: /dev/stderr
KONG_PREFIX: /var/run/kong
KONG_PROXY_LISTEN: "0.0.0.0:8090" # 对外暴露端口
KONG_ADMIN_LISTEN: "0.0.0.0:8001" # Admin GUI
KONG_PROXY_LISTEN: "0.0.0.0:8090 ssl" # 对外暴露端口
KONG_ADMIN_LISTEN: "0.0.0.0:8001" # Admin
KONG_ADMIN_GUI_LISTEN: "0.0.0.0:8002"
KONG_SSL_CERT: /etc/kong/certs/ai.ronsunny.cn.pem
KONG_SSL_CERT_KEY: /etc/kong/certs/ai.ronsunny.cn.key
KONG_PLUGINS: bundled,prometheus
KONG_PROMETHEUS_STATUS_CODE_METRICS: "on"
KONG_PROMETHEUS_LATENCY_METRICS: "on"
@@ -182,7 +196,7 @@ services:
volumes:
- kong_prefix_vol:${KONG_PREFIX:-/var/run/kong}
- kong_tmp_vol:/tmp
- ./config/kong:/opt/kong
- /home/bbit/ssl:/etc/kong/certs
networks:
- ce_network
restart: unless-stopped
@@ -194,6 +208,7 @@ services:
environment:
RABBITMQ_DEFAULT_USER: admin
RABBITMQ_DEFAULT_PASS: 123456
hostname: ce_rabbitmq
ports:
- "5672:5672"
- "15672:15672"
@@ -285,25 +300,49 @@ services:
- '/:/host:ro,rslave'
restart: unless-stopped
# ---------- ollama ----------
ollama:
image: ollama/ollama:0.12.6
container_name: ce_ollama
runtime: nvidia # 关键,确保容器用 NVIDIA GPU
volumes:
- ollama_data:/root/.ollama
ports:
- "11434:11434"
networks:
- ce_network
restart: unless-stopped
# ---------- 数据卷 ----------
volumes:
grafana_data:
name: ce_grafana_data
postgres_data:
name: ce_postgres_data
redis_data:
name: ce_redis_data
minio_data:
name: ce_minio_data
etcd_data:
name: ce_etcd_data
milvus_data:
name: ce_milvus_data
kong_prefix_vol:
name: ce_kong_prefix_data
driver_opts:
type: tmpfs
device: tmpfs
kong_tmp_vol:
name: ce_kong_tmp_data
driver_opts:
type: tmpfs
device: tmpfs
rabbitmq_data:
prometheus_config:
name: ce_rabbitmq_data
prometheus_data:
name: ce_prometheus_data
ollama_data: # 定义 ollama 的数据卷
name: ce_ollama_data
# ---------- 网络 ----------
networks:
+3 -3
View File
@@ -1,10 +1,10 @@
[Unit]
Description=Ktor Server
Description=BBIT AI Lab Ktor Server
After=network.target
[Service]
ExecStart=/opt/final/ktor/bin/ktor
WorkingDirectory=/opt/final/ktor
ExecStart=/home/bbit/bbit_ai_lab/ktor/bin/ktor
WorkingDirectory=/home/bbit/bbit_ai_lab/ktor
Restart=always
[Install]
+5 -5
View File
@@ -1,13 +1,13 @@
[Unit]
Description=Web Socket Scrcpy
Description=BBIT_AI_LAB_WS_SCRCPY
After=network.target
[Service]
User=qin
ExecStart=/home/qin/.nvm/versions/node/v16.20.2/bin/node index.js
WorkingDirectory=/opt/final/ws-scrcpy/dist
User=bbit
ExecStart=/usr/local/node-v16.20.2-linux-x64/bin/node index.js
WorkingDirectory=/home/bbit/bbit_ai_lab/ws-scrcpy/dist
Restart=always
Environment=PATH=/home/qin/.nvm/versions/node/v16.20.2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Environment=PATH=/usr/local/node-v16.20.2-linux-x64/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
StandardOutput=journal
StandardError=journal
+2 -2
View File
@@ -1,8 +1,8 @@
VITE_BASE=/
# 接口地址
VITE_GLOB_API_URL=http://s1.ronsunny.cn:8090/api
VITE_GLOB_API_URL_PY=http://s1.ronsunny.cn:8090/ai
VITE_GLOB_API_URL=https://ai.ronsunny.cn:8090/api
VITE_GLOB_API_URL_PY=https://ai.ronsunny.cn:8090/ai
# 是否开启压缩,可以设置为 none, brotli, gzip
VITE_COMPRESS=none
@@ -38,7 +38,7 @@ const routes: RouteRecordRaw[] = [
component: IFrameView,
meta: {
icon: 'mdi:wall-fire',
iframeSrc: 'http://s1.ronsunny.cn:13010/',
iframeSrc: 'http://ai.ronsunny.cn:13010/',
keepAlive: false,
title: 'RAG Flow',
},
@@ -22,7 +22,7 @@
// component: IFrameView,
// meta: {
// icon: 'mdi:wall-fire',
// iframeSrc: 'http://s1.ronsunny.cn:13010/',
// iframeSrc: 'http://ai.ronsunny.cn:13010/',
// keepAlive: false,
// title: 'RAG Flow',
// },
@@ -3,6 +3,8 @@ import type { RouteRecordRaw } from 'vue-router';
import { IFrameView } from '#/layouts';
import { $t } from '#/locales';
const baseAddress = '10.0.4.22';
const routes: RouteRecordRaw[] = [
{
meta: {
@@ -21,7 +23,7 @@ const routes: RouteRecordRaw[] = [
component: IFrameView,
meta: {
icon: 'mdi:monitor-dashboard',
link: 'http://10.10.10.9:8002/',
link: `http://${baseAddress}:8002/`,
title: '网关',
},
},
@@ -31,7 +33,7 @@ const routes: RouteRecordRaw[] = [
component: IFrameView,
meta: {
icon: 'mdi:monitor-dashboard',
link: 'http://10.10.10.9:9001',
link: `https://${baseAddress}:9001/`,
title: '对象存储',
},
},
@@ -41,7 +43,7 @@ const routes: RouteRecordRaw[] = [
component: IFrameView,
meta: {
icon: 'mdi:monitor-dashboard',
link: 'http://10.10.10.9:9091/webui',
link: `http://${baseAddress}:9091/webui`,
title: '向量数据库',
},
},
@@ -51,7 +53,7 @@ const routes: RouteRecordRaw[] = [
component: IFrameView,
meta: {
icon: 'mdi:monitor-dashboard',
link: 'http://10.10.10.9:3000/',
link: `http://${baseAddress}:3000/`,
title: '向量数据库Attu',
},
},
@@ -61,7 +63,7 @@ const routes: RouteRecordRaw[] = [
component: IFrameView,
meta: {
icon: 'mdi:monitor-dashboard',
link: 'http://10.10.10.9:15672',
link: `http://${baseAddress}:15672`,
title: '消息队列',
},
},
@@ -71,7 +73,7 @@ const routes: RouteRecordRaw[] = [
component: IFrameView,
meta: {
icon: 'mdi:monitor-dashboard',
link: 'http://10.10.10.9:13011',
link: `https://ai.ronsunny.cn:13011/`,
title: '容器管理',
},
},
@@ -81,7 +83,7 @@ const routes: RouteRecordRaw[] = [
component: IFrameView,
meta: {
icon: 'mdi:monitor-dashboard',
link: 'http://10.10.10.9:9090',
link: `http://${baseAddress}:9090`,
title: '日志监控',
},
},
@@ -91,7 +93,7 @@ const routes: RouteRecordRaw[] = [
component: IFrameView,
meta: {
icon: 'mdi:monitor-dashboard',
link: 'http://10.10.10.9:3001',
link: `http://${baseAddress}:3001`,
title: '数据可视化',
},
},
+1 -1
View File
@@ -127,7 +127,7 @@ const disconnectAll = async () => {
<template #default>
<Card class="ml-2 h-full">
<iframe
src="http://s1.ronsunny.cn:8090/remote"
src="https://ai.ronsunny.cn:8090/remote"
class="h-full w-full"
></iframe>
</Card>