diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..93bb823 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,80 @@ +# 资金服务平台 - 统一 Dockerfile +# 多阶段构建:Maven 构建 + JRE 运行 + +# ==================== 构建阶段 ==================== +FROM maven:3.9-eclipse-temurin-21-alpine AS builder + +WORKDIR /build + +# 复制 Maven 配置文件(利用缓存加速构建) +COPY pom.xml . +COPY fund-common/pom.xml fund-common/ +COPY fund-gateway/pom.xml fund-gateway/ +COPY fund-sys/pom.xml fund-sys/ +COPY fund-cust/pom.xml fund-cust/ +COPY fund-proj/pom.xml fund-proj/ +COPY fund-req/pom.xml fund-req/ +COPY fund-exp/pom.xml fund-exp/ +COPY fund-receipt/pom.xml fund-receipt/ +COPY fund-report/pom.xml fund-report/ +COPY fund-file/pom.xml fund-file/ + +# 下载依赖(利用 Docker 缓存) +RUN mvn dependency:go-offline -B || true + +# 复制源代码 +COPY fund-common/ fund-common/ +COPY fund-gateway/ fund-gateway/ +COPY fund-sys/ fund-sys/ +COPY fund-cust/ fund-cust/ +COPY fund-proj/ fund-proj/ +COPY fund-req/ fund-req/ +COPY fund-exp/ fund-exp/ +COPY fund-receipt/ fund-receipt/ +COPY fund-report/ fund-report/ +COPY fund-file/ fund-file/ + +# 构建参数:指定要构建的模块 +ARG MODULE=fund-sys +RUN mvn clean package -pl ${MODULE} -am -DskipTests -B + +# ==================== 运行阶段 ==================== +FROM eclipse-temurin:21-jre-alpine + +# 安装必要工具 +RUN apk add --no-cache curl tzdata && \ + cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \ + echo "Asia/Shanghai" > /etc/timezone && \ + apk del tzdata + +# 创建非 root 用户 +RUN addgroup -S appgroup && adduser -S appuser -G appgroup + +WORKDIR /app + +# 构建参数 +ARG MODULE=fund-sys +ARG VERSION=0.0.1-SNAPSHOT + +# 从构建阶段复制 JAR 包 +COPY --from=builder /build/${MODULE}/target/${MODULE}-${VERSION}.jar app.jar + +# 设置权限 +RUN chown -R appuser:appgroup /app + +# 切换非 root 用户 +USER appuser + +# JVM 参数 +ENV JAVA_OPTS="-Xms256m -Xmx512m -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError" +ENV SPRING_PROFILES_ACTIVE="docker" + +# 暴露端口(默认 8080,实际端口由服务决定) +EXPOSE 8080 + +# 健康检查 +HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ + CMD curl -f http://localhost:${SERVER_PORT:-8080}/actuator/health || exit 1 + +# 启动命令 +ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..fdc3531 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,436 @@ +# 资金服务平台 - Docker Compose 编排配置 +# 版本: 1.0 + +version: '3.8' + +services: + # ==================== 基础设施服务 ==================== + + # MySQL 数据库 + mysql: + image: mysql:8.0 + container_name: fund-mysql + restart: unless-stopped + environment: + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root123} + MYSQL_DATABASE: fund_platform + TZ: Asia/Shanghai + ports: + - "3306:3306" + volumes: + - mysql_data:/var/lib/mysql + - ./docker/mysql/init:/docker-entrypoint-initdb.d:ro + command: + - --character-set-server=utf8mb4 + - --collation-server=utf8mb4_unicode_ci + - --default-authentication-plugin=mysql_native_password + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + interval: 10s + timeout: 5s + retries: 5 + networks: + - fund-network + + # Redis 缓存 + redis: + image: redis:7-alpine + container_name: fund-redis + restart: unless-stopped + ports: + - "6379:6379" + volumes: + - redis_data:/data + command: redis-server --appendonly yes + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + networks: + - fund-network + + # Nacos 注册中心 & 配置中心 + nacos: + image: nacos/nacos-server:v3.0.0 + container_name: fund-nacos + restart: unless-stopped + environment: + MODE: standalone + SPRING_DATASOURCE_PLATFORM: mysql + MYSQL_SERVICE_HOST: mysql + MYSQL_SERVICE_PORT: 3306 + MYSQL_SERVICE_DB_NAME: nacos_config + MYSQL_SERVICE_USER: root + MYSQL_SERVICE_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root123} + NACOS_AUTH_TOKEN: SecretKey012345678901234567890123456789012345678901234567890123456789 + NACOS_AUTH_IDENTITY_KEY: serverIdentity + NACOS_AUTH_IDENTITY_VALUE: security + ports: + - "8848:8848" + - "9848:9848" + - "9849:9849" + volumes: + - nacos_data:/home/nacos/logs + depends_on: + mysql: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8848/nacos/v1/console/health/readiness"] + interval: 30s + timeout: 10s + retries: 10 + start_period: 60s + networks: + - fund-network + + # ==================== 监控服务 ==================== + + # Prometheus 监控 + prometheus: + image: prom/prometheus:v2.48.0 + container_name: fund-prometheus + restart: unless-stopped + ports: + - "9090:9090" + volumes: + - ./docker/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro + - ./docker/prometheus/rules:/etc/prometheus/rules:ro + - prometheus_data:/prometheus + command: + - '--config.file=/etc/prometheus/prometheus.yml' + - '--storage.tsdb.path=/prometheus' + - '--storage.tsdb.retention.time=15d' + - '--web.enable-lifecycle' + networks: + - fund-network + + # Grafana 可视化 + grafana: + image: grafana/grafana:10.2.0 + container_name: fund-grafana + restart: unless-stopped + environment: + GF_SECURITY_ADMIN_USER: admin + GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD:-admin123} + GF_USERS_ALLOW_SIGN_UP: "false" + GF_SERVER_ROOT_URL: http://localhost:3000 + ports: + - "3000:3000" + volumes: + - grafana_data:/var/lib/grafana + - ./docker/grafana/provisioning:/etc/grafana/provisioning:ro + - ./docker/grafana/dashboards:/var/lib/grafana/dashboards:ro + depends_on: + - prometheus + networks: + - fund-network + + # ==================== 业务微服务 ==================== + + # API 网关 + gateway: + build: + context: . + dockerfile: Dockerfile + args: + MODULE: fund-gateway + container_name: fund-gateway + restart: unless-stopped + environment: + SERVER_PORT: 8000 + SPRING_PROFILES_ACTIVE: docker + NACOS_SERVER_ADDR: nacos:8848 + NACOS_USERNAME: nacos + NACOS_PASSWORD: nacos + JAVA_OPTS: -Xms256m -Xmx512m + ports: + - "8000:8000" + depends_on: + nacos: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8000/actuator/health"] + interval: 30s + timeout: 10s + retries: 5 + start_period: 120s + networks: + - fund-network + + # 系统服务 + fund-sys: + build: + context: . + dockerfile: Dockerfile + args: + MODULE: fund-sys + container_name: fund-sys + restart: unless-stopped + environment: + SERVER_PORT: 8100 + SPRING_PROFILES_ACTIVE: docker + NACOS_SERVER_ADDR: nacos:8848 + NACOS_USERNAME: nacos + NACOS_PASSWORD: nacos + MYSQL_HOST: mysql + MYSQL_PORT: 3306 + MYSQL_DB: fund_platform + MYSQL_USER: root + MYSQL_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root123} + REDIS_HOST: redis + REDIS_PORT: 6379 + JAVA_OPTS: -Xms256m -Xmx512m + ports: + - "8100:8100" + depends_on: + nacos: + condition: service_healthy + mysql: + condition: service_healthy + redis: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8100/actuator/health"] + interval: 30s + timeout: 10s + retries: 5 + start_period: 120s + networks: + - fund-network + + # 客户服务 + fund-cust: + build: + context: . + dockerfile: Dockerfile + args: + MODULE: fund-cust + container_name: fund-cust + restart: unless-stopped + environment: + SERVER_PORT: 8200 + SPRING_PROFILES_ACTIVE: docker + NACOS_SERVER_ADDR: nacos:8848 + NACOS_USERNAME: nacos + NACOS_PASSWORD: nacos + MYSQL_HOST: mysql + MYSQL_PORT: 3306 + MYSQL_DB: fund_platform + MYSQL_USER: root + MYSQL_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root123} + JAVA_OPTS: -Xms256m -Xmx512m + ports: + - "8200:8200" + depends_on: + nacos: + condition: service_healthy + mysql: + condition: service_healthy + networks: + - fund-network + + # 项目服务 + fund-proj: + build: + context: . + dockerfile: Dockerfile + args: + MODULE: fund-proj + container_name: fund-proj + restart: unless-stopped + environment: + SERVER_PORT: 8300 + SPRING_PROFILES_ACTIVE: docker + NACOS_SERVER_ADDR: nacos:8848 + NACOS_USERNAME: nacos + NACOS_PASSWORD: nacos + MYSQL_HOST: mysql + MYSQL_PORT: 3306 + MYSQL_DB: fund_platform + MYSQL_USER: root + MYSQL_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root123} + JAVA_OPTS: -Xms256m -Xmx512m + ports: + - "8300:8300" + depends_on: + nacos: + condition: service_healthy + mysql: + condition: service_healthy + networks: + - fund-network + + # 需求工单服务 + fund-req: + build: + context: . + dockerfile: Dockerfile + args: + MODULE: fund-req + container_name: fund-req + restart: unless-stopped + environment: + SERVER_PORT: 8400 + SPRING_PROFILES_ACTIVE: docker + NACOS_SERVER_ADDR: nacos:8848 + NACOS_USERNAME: nacos + NACOS_PASSWORD: nacos + MYSQL_HOST: mysql + MYSQL_PORT: 3306 + MYSQL_DB: fund_platform + MYSQL_USER: root + MYSQL_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root123} + JAVA_OPTS: -Xms256m -Xmx512m + ports: + - "8400:8400" + depends_on: + nacos: + condition: service_healthy + mysql: + condition: service_healthy + networks: + - fund-network + + # 支出服务 + fund-exp: + build: + context: . + dockerfile: Dockerfile + args: + MODULE: fund-exp + container_name: fund-exp + restart: unless-stopped + environment: + SERVER_PORT: 8500 + SPRING_PROFILES_ACTIVE: docker + NACOS_SERVER_ADDR: nacos:8848 + NACOS_USERNAME: nacos + NACOS_PASSWORD: nacos + MYSQL_HOST: mysql + MYSQL_PORT: 3306 + MYSQL_DB: fund_platform + MYSQL_USER: root + MYSQL_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root123} + JAVA_OPTS: -Xms256m -Xmx512m + ports: + - "8500:8500" + depends_on: + nacos: + condition: service_healthy + mysql: + condition: service_healthy + networks: + - fund-network + + # 收款服务 + fund-receipt: + build: + context: . + dockerfile: Dockerfile + args: + MODULE: fund-receipt + container_name: fund-receipt + restart: unless-stopped + environment: + SERVER_PORT: 8600 + SPRING_PROFILES_ACTIVE: docker + NACOS_SERVER_ADDR: nacos:8848 + NACOS_USERNAME: nacos + NACOS_PASSWORD: nacos + MYSQL_HOST: mysql + MYSQL_PORT: 3306 + MYSQL_DB: fund_platform + MYSQL_USER: root + MYSQL_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root123} + JAVA_OPTS: -Xms256m -Xmx512m + ports: + - "8600:8600" + depends_on: + nacos: + condition: service_healthy + mysql: + condition: service_healthy + networks: + - fund-network + + # 报表服务 + fund-report: + build: + context: . + dockerfile: Dockerfile + args: + MODULE: fund-report + container_name: fund-report + restart: unless-stopped + environment: + SERVER_PORT: 8700 + SPRING_PROFILES_ACTIVE: docker + NACOS_SERVER_ADDR: nacos:8848 + NACOS_USERNAME: nacos + NACOS_PASSWORD: nacos + MYSQL_HOST: mysql + MYSQL_PORT: 3306 + MYSQL_DB: fund_platform + MYSQL_USER: root + MYSQL_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root123} + JAVA_OPTS: -Xms256m -Xmx512m + ports: + - "8700:8700" + depends_on: + nacos: + condition: service_healthy + mysql: + condition: service_healthy + networks: + - fund-network + + # 文件服务 + fund-file: + build: + context: . + dockerfile: Dockerfile + args: + MODULE: fund-file + container_name: fund-file + restart: unless-stopped + environment: + SERVER_PORT: 8800 + SPRING_PROFILES_ACTIVE: docker + NACOS_SERVER_ADDR: nacos:8848 + NACOS_USERNAME: nacos + NACOS_PASSWORD: nacos + MYSQL_HOST: mysql + MYSQL_PORT: 3306 + MYSQL_DB: fund_platform + MYSQL_USER: root + MYSQL_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root123} + JAVA_OPTS: -Xms256m -Xmx512m + ports: + - "8800:8800" + depends_on: + nacos: + condition: service_healthy + mysql: + condition: service_healthy + networks: + - fund-network + +# ==================== 网络配置 ==================== +networks: + fund-network: + driver: bridge + name: fund-network + +# ==================== 数据卷 ==================== +volumes: + mysql_data: + name: fund-mysql-data + redis_data: + name: fund-redis-data + nacos_data: + name: fund-nacos-data + prometheus_data: + name: fund-prometheus-data + grafana_data: + name: fund-grafana-data diff --git a/docker/.env b/docker/.env new file mode 100644 index 0000000..7a0789b --- /dev/null +++ b/docker/.env @@ -0,0 +1,18 @@ +# 资金服务平台 - Docker 环境配置 +# 复制为 .env 使用 + +# ==================== 数据库配置 ==================== +MYSQL_ROOT_PASSWORD=root123 + +# ==================== Nacos 配置 ==================== +NACOS_AUTH_TOKEN=SecretKey012345678901234567890123456789012345678901234567890123456789 + +# ==================== Grafana 配置 ==================== +GRAFANA_PASSWORD=admin123 + +# ==================== 服务配置 ==================== +# JVM 参数 +JAVA_OPTS=-Xms256m -Xmx512m -XX:+UseG1GC + +# 日志级别 +LOG_LEVEL=INFO diff --git a/docker/grafana/dashboards/fund-platform-dashboard.json b/docker/grafana/dashboards/fund-platform-dashboard.json new file mode 100644 index 0000000..0c052cd --- /dev/null +++ b/docker/grafana/dashboards/fund-platform-dashboard.json @@ -0,0 +1,662 @@ +{ + "annotations": { + "list": [] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": null, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 1, + "panels": [], + "title": "服务概览", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 0 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 0, + "y": 1 + }, + "id": 2, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.2.0", + "targets": [ + { + "expr": "count(up{job=~\"fund-.*\"})", + "refId": "A", + "legendFormat": "总服务数" + }, + { + "expr": "count(up{job=~\"fund-.*\"} == 1)", + "refId": "B", + "legendFormat": "在线服务" + }, + { + "expr": "count(up{job=~\"fund-.*\"} == 0)", + "refId": "C", + "legendFormat": "离线服务" + } + ], + "title": "服务状态", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 10, + "x": 6, + "y": 1 + }, + "id": 3, + "options": { + "legend": { + "calcs": ["mean", "max"], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "expr": "sum(rate(http_server_requests_seconds_count{application=~\"$application\"}[5m])) by (application)", + "legendFormat": "{{application}}", + "refId": "A" + } + ], + "title": "请求速率 (QPS)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 1 + }, + "id": 4, + "options": { + "legend": { + "calcs": ["mean", "max"], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "expr": "histogram_quantile(0.95, sum(rate(http_server_requests_seconds_bucket{application=~\"$application\"}[5m])) by (le, application))", + "legendFormat": "{{application}} P95", + "refId": "A" + }, + { + "expr": "histogram_quantile(0.99, sum(rate(http_server_requests_seconds_bucket{application=~\"$application\"}[5m])) by (le, application))", + "legendFormat": "{{application}} P99", + "refId": "B" + } + ], + "title": "响应时间 (P95/P99)", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 7 + }, + "id": 10, + "panels": [], + "title": "JVM 内存", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 11, + "options": { + "legend": { + "calcs": ["mean", "max"], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "expr": "jvm_memory_used_bytes{application=~\"$application\", area=\"heap\"}", + "legendFormat": "{{application}} - Used", + "refId": "A" + }, + { + "expr": "jvm_memory_max_bytes{application=~\"$application\", area=\"heap\"}", + "legendFormat": "{{application}} - Max", + "refId": "B" + } + ], + "title": "JVM 堆内存使用", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 12, + "options": { + "legend": { + "calcs": ["mean", "max"], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "expr": "rate(jvm_gc_pause_seconds_sum{application=~\"$application\"}[5m])", + "legendFormat": "{{application}} - {{action}}", + "refId": "A" + } + ], + "title": "GC 时间", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 16 + }, + "id": 20, + "panels": [], + "title": "数据库连接池", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 17 + }, + "id": 21, + "options": { + "legend": { + "calcs": ["mean", "max"], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "expr": "hikaricp_connections_active{application=~\"$application\"}", + "legendFormat": "{{application}} - Active", + "refId": "A" + }, + { + "expr": "hikaricp_connections_idle{application=~\"$application\"}", + "legendFormat": "{{application}} - Idle", + "refId": "B" + }, + { + "expr": "hikaricp_connections_max{application=~\"$application\"}", + "legendFormat": "{{application}} - Max", + "refId": "C" + } + ], + "title": "HikariCP 连接池状态", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "yellow", + "value": 70 + }, + { + "color": "red", + "value": 85 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 17 + }, + "id": 22, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.2.0", + "targets": [ + { + "expr": "(hikaricp_connections_active{application=~\"$application\"} / hikaricp_connections_max{application=~\"$application\"}) * 100", + "legendFormat": "{{application}}", + "refId": "A" + } + ], + "title": "连接池使用率", + "type": "gauge" + } + ], + "refresh": "5s", + "schemaVersion": 38, + "style": "dark", + "tags": ["fundplatform", "springboot", "jvm"], + "templating": { + "list": [ + { + "current": { + "selected": true, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "definition": "label_values(up{job=~\"fund-.*\"}, application)", + "hide": 0, + "includeAll": true, + "label": "Application", + "multi": true, + "name": "application", + "options": [], + "query": { + "query": "label_values(up{job=~\"fund-.*\"}, application)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "资金服务平台监控", + "uid": "fund-platform-dashboard", + "version": 1, + "weekStart": "" +} diff --git a/docker/grafana/provisioning/dashboards/dashboards.yml b/docker/grafana/provisioning/dashboards/dashboards.yml new file mode 100644 index 0000000..38da075 --- /dev/null +++ b/docker/grafana/provisioning/dashboards/dashboards.yml @@ -0,0 +1,14 @@ +# Grafana Dashboard 自动导入配置 +apiVersion: 1 + +providers: + - name: 'FundPlatform' + orgId: 1 + folder: 'FundPlatform' + folderUid: 'fundplatform' + type: file + disableDeletion: false + updateIntervalSeconds: 30 + allowUiUpdates: true + options: + path: /var/lib/grafana/dashboards diff --git a/docker/grafana/provisioning/datasources/prometheus.yml b/docker/grafana/provisioning/datasources/prometheus.yml new file mode 100644 index 0000000..f2d8eee --- /dev/null +++ b/docker/grafana/provisioning/datasources/prometheus.yml @@ -0,0 +1,15 @@ +# Grafana 数据源配置 +apiVersion: 1 + +datasources: + # Prometheus 数据源 + - name: Prometheus + type: prometheus + access: proxy + url: http://prometheus:9090 + isDefault: true + editable: false + jsonData: + httpMethod: POST + manageAlerts: true + prometheusType: Prometheus diff --git a/docker/mysql/init/01-init.sql b/docker/mysql/init/01-init.sql new file mode 100644 index 0000000..695f3cb --- /dev/null +++ b/docker/mysql/init/01-init.sql @@ -0,0 +1,144 @@ +-- 资金服务平台 - MySQL 初始化脚本 +-- 执行顺序: 01 + +-- 设置字符集 +SET NAMES utf8mb4; +SET CHARACTER SET utf8mb4; + +-- 创建 Nacos 配置数据库 +CREATE DATABASE IF NOT EXISTS `nacos_config` + DEFAULT CHARACTER SET utf8mb4 + COLLATE utf8mb4_unicode_ci; + +-- 创建业务数据库 +CREATE DATABASE IF NOT EXISTS `fund_platform` + DEFAULT CHARACTER SET utf8mb4 + COLLATE utf8mb4_unicode_ci; + +-- 授权(如果需要创建专用用户) +-- CREATE USER 'fund_user'@'%' IDENTIFIED BY 'fund123'; +-- GRANT ALL PRIVILEGES ON fund_platform.* TO 'fund_user'@'%'; +-- FLUSH PRIVILEGES; + +USE `fund_platform`; + +-- 用户表 +CREATE TABLE IF NOT EXISTS `sys_user` ( + `id` BIGINT NOT NULL COMMENT '用户ID', + `username` VARCHAR(50) NOT NULL COMMENT '用户名', + `password` VARCHAR(100) NOT NULL COMMENT '密码', + `real_name` VARCHAR(50) COMMENT '真实姓名', + `phone` VARCHAR(20) COMMENT '手机号', + `email` VARCHAR(100) COMMENT '邮箱', + `dept_id` BIGINT COMMENT '部门ID', + `tenant_id` BIGINT NOT NULL DEFAULT 1 COMMENT '租户ID', + `status` TINYINT DEFAULT 1 COMMENT '状态:0禁用 1启用', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP, + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `deleted` TINYINT DEFAULT 0 COMMENT '是否删除', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_username` (`username`, `tenant_id`), + KEY `idx_tenant_id` (`tenant_id`), + KEY `idx_dept_id` (`dept_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表'; + +-- 角色表 +CREATE TABLE IF NOT EXISTS `sys_role` ( + `id` BIGINT NOT NULL COMMENT '角色ID', + `role_name` VARCHAR(50) NOT NULL COMMENT '角色名称', + `role_code` VARCHAR(50) NOT NULL COMMENT '角色编码', + `tenant_id` BIGINT NOT NULL DEFAULT 1 COMMENT '租户ID', + `status` TINYINT DEFAULT 1 COMMENT '状态', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP, + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `deleted` TINYINT DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_tenant_id` (`tenant_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表'; + +-- 菜单表 +CREATE TABLE IF NOT EXISTS `sys_menu` ( + `id` BIGINT NOT NULL COMMENT '菜单ID', + `parent_id` BIGINT DEFAULT 0 COMMENT '父菜单ID', + `menu_name` VARCHAR(50) NOT NULL COMMENT '菜单名称', + `menu_type` TINYINT DEFAULT 1 COMMENT '类型:1目录 2菜单 3按钮', + `path` VARCHAR(200) COMMENT '路由路径', + `component` VARCHAR(200) COMMENT '组件路径', + `perms` VARCHAR(100) COMMENT '权限标识', + `sort` INT DEFAULT 0 COMMENT '排序', + `icon` VARCHAR(100) COMMENT '图标', + `status` TINYINT DEFAULT 1 COMMENT '状态', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP, + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `deleted` TINYINT DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_parent_id` (`parent_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='菜单表'; + +-- 用户角色关联表 +CREATE TABLE IF NOT EXISTS `sys_user_role` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `user_id` BIGINT NOT NULL, + `role_id` BIGINT NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_user_role` (`user_id`, `role_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户角色关联表'; + +-- 角色菜单关联表 +CREATE TABLE IF NOT EXISTS `sys_role_menu` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `role_id` BIGINT NOT NULL, + `menu_id` BIGINT NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_role_menu` (`role_id`, `menu_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色菜单关联表'; + +-- 部门表 +CREATE TABLE IF NOT EXISTS `sys_dept` ( + `id` BIGINT NOT NULL COMMENT '部门ID', + `parent_id` BIGINT DEFAULT 0 COMMENT '父部门ID', + `dept_name` VARCHAR(50) NOT NULL COMMENT '部门名称', + `tenant_id` BIGINT NOT NULL DEFAULT 1 COMMENT '租户ID', + `sort` INT DEFAULT 0, + `status` TINYINT DEFAULT 1, + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP, + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `deleted` TINYINT DEFAULT 0, + PRIMARY KEY (`id`), + KEY `idx_tenant_id` (`tenant_id`), + KEY `idx_parent_id` (`parent_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='部门表'; + +-- 租户表 +CREATE TABLE IF NOT EXISTS `sys_tenant` ( + `id` BIGINT NOT NULL COMMENT '租户ID', + `tenant_name` VARCHAR(100) NOT NULL COMMENT '租户名称', + `tenant_code` VARCHAR(50) NOT NULL COMMENT '租户编码', + `contact_name` VARCHAR(50) COMMENT '联系人', + `contact_phone` VARCHAR(20) COMMENT '联系电话', + `status` TINYINT DEFAULT 1 COMMENT '状态', + `expire_time` DATETIME COMMENT '过期时间', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP, + `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `deleted` TINYINT DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_tenant_code` (`tenant_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='租户表'; + +-- 插入默认租户 +INSERT INTO `sys_tenant` (`id`, `tenant_name`, `tenant_code`, `contact_name`, `status`) +VALUES (1, '默认租户', 'DEFAULT', '系统管理员', 1) ON DUPLICATE KEY UPDATE `tenant_name` = VALUES(`tenant_name`); + +-- 插入默认管理员用户 (密码: admin123,使用 BCrypt 加密) +INSERT INTO `sys_user` (`id`, `username`, `password`, `real_name`, `tenant_id`, `status`) +VALUES (1, 'admin', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt6Z5EH', '系统管理员', 1, 1) +ON DUPLICATE KEY UPDATE `real_name` = VALUES(`real_name`); + +-- 插入默认角色 +INSERT INTO `sys_role` (`id`, `role_name`, `role_code`, `tenant_id`) +VALUES (1, '管理员', 'ADMIN', 1), (2, '普通用户', 'USER', 1) +ON DUPLICATE KEY UPDATE `role_name` = VALUES(`role_name`); + +-- 分配管理员角色 +INSERT INTO `sys_user_role` (`user_id`, `role_id`) VALUES (1, 1) +ON DUPLICATE KEY UPDATE `role_id` = VALUES(`role_id`); diff --git a/docker/prometheus/prometheus.yml b/docker/prometheus/prometheus.yml new file mode 100644 index 0000000..13b897d --- /dev/null +++ b/docker/prometheus/prometheus.yml @@ -0,0 +1,159 @@ +# Prometheus 配置文件 +# 资金服务平台监控配置 + +global: + scrape_interval: 15s # 抓取间隔 + evaluation_interval: 15s # 规则评估间隔 + external_labels: + monitor: 'fund-platform' + +# 告警管理器配置(可选) +# alerting: +# alertmanagers: +# - static_configs: +# - targets: +# - alertmanager:9093 + +# 规则文件 +rule_files: + - /etc/prometheus/rules/*.yml + +# 抓取配置 +scrape_configs: + # ==================== 基础设施监控 ==================== + + # Prometheus 自身监控 + - job_name: 'prometheus' + static_configs: + - targets: ['localhost:9090'] + labels: + instance: 'prometheus' + + # MySQL 监控 (需要 mysqld_exporter) + # - job_name: 'mysql' + # static_configs: + # - targets: ['mysql-exporter:9104'] + + # Redis 监控 (需要 redis_exporter) + # - job_name: 'redis' + # static_configs: + # - targets: ['redis-exporter:9121'] + + # ==================== Spring Boot 微服务监控 ==================== + + # API 网关 + - job_name: 'fund-gateway' + metrics_path: '/actuator/prometheus' + static_configs: + - targets: ['gateway:8000'] + labels: + application: 'fund-gateway' + service: 'gateway' + relabel_configs: + - source_labels: [__address__] + target_label: instance + replacement: 'fund-gateway' + + # 系统服务 + - job_name: 'fund-sys' + metrics_path: '/actuator/prometheus' + static_configs: + - targets: ['fund-sys:8100'] + labels: + application: 'fund-sys' + service: 'business' + relabel_configs: + - source_labels: [__address__] + target_label: instance + replacement: 'fund-sys' + + # 客户服务 + - job_name: 'fund-cust' + metrics_path: '/actuator/prometheus' + static_configs: + - targets: ['fund-cust:8200'] + labels: + application: 'fund-cust' + service: 'business' + relabel_configs: + - source_labels: [__address__] + target_label: instance + replacement: 'fund-cust' + + # 项目服务 + - job_name: 'fund-proj' + metrics_path: '/actuator/prometheus' + static_configs: + - targets: ['fund-proj:8300'] + labels: + application: 'fund-proj' + service: 'business' + relabel_configs: + - source_labels: [__address__] + target_label: instance + replacement: 'fund-proj' + + # 需求工单服务 + - job_name: 'fund-req' + metrics_path: '/actuator/prometheus' + static_configs: + - targets: ['fund-req:8400'] + labels: + application: 'fund-req' + service: 'business' + relabel_configs: + - source_labels: [__address__] + target_label: instance + replacement: 'fund-req' + + # 支出服务 + - job_name: 'fund-exp' + metrics_path: '/actuator/prometheus' + static_configs: + - targets: ['fund-exp:8500'] + labels: + application: 'fund-exp' + service: 'business' + relabel_configs: + - source_labels: [__address__] + target_label: instance + replacement: 'fund-exp' + + # 收款服务 + - job_name: 'fund-receipt' + metrics_path: '/actuator/prometheus' + static_configs: + - targets: ['fund-receipt:8600'] + labels: + application: 'fund-receipt' + service: 'business' + relabel_configs: + - source_labels: [__address__] + target_label: instance + replacement: 'fund-receipt' + + # 报表服务 + - job_name: 'fund-report' + metrics_path: '/actuator/prometheus' + static_configs: + - targets: ['fund-report:8700'] + labels: + application: 'fund-report' + service: 'business' + relabel_configs: + - source_labels: [__address__] + target_label: instance + replacement: 'fund-report' + + # 文件服务 + - job_name: 'fund-file' + metrics_path: '/actuator/prometheus' + static_configs: + - targets: ['fund-file:8800'] + labels: + application: 'fund-file' + service: 'business' + relabel_configs: + - source_labels: [__address__] + target_label: instance + replacement: 'fund-file' diff --git a/docker/prometheus/rules/alerts.yml b/docker/prometheus/rules/alerts.yml new file mode 100644 index 0000000..88fd2e9 --- /dev/null +++ b/docker/prometheus/rules/alerts.yml @@ -0,0 +1,128 @@ +# Prometheus 告警规则 +# 资金服务平台 + +groups: + # ==================== 服务可用性告警 ==================== + - name: service_availability + rules: + # 服务宕机告警 + - alert: ServiceDown + expr: up == 0 + for: 1m + labels: + severity: critical + annotations: + summary: "服务 {{ $labels.job }} 宕机" + description: "服务 {{ $labels.instance }} 已经宕机超过 1 分钟" + + # 健康检查失败 + - alert: HealthCheckFailed + expr: spring_boot_health_status{status="DOWN"} == 1 + for: 30s + labels: + severity: warning + annotations: + summary: "服务健康检查失败" + description: "服务 {{ $labels.application }} 健康状态为 DOWN" + + # ==================== JVM 内存告警 ==================== + - name: jvm_memory + rules: + # 堆内存使用率过高 + - alert: HeapMemoryUsageHigh + expr: (jvm_memory_used_bytes{area="heap"} / jvm_memory_max_bytes{area="heap"}) * 100 > 85 + for: 5m + labels: + severity: warning + annotations: + summary: "JVM 堆内存使用率过高" + description: "服务 {{ $labels.application }} 堆内存使用率 {{ $value | printf \"%.2f\" }}%" + + # 堆内存即将耗尽 + - alert: HeapMemoryCritical + expr: (jvm_memory_used_bytes{area="heap"} / jvm_memory_max_bytes{area="heap"}) * 100 > 95 + for: 1m + labels: + severity: critical + annotations: + summary: "JVM 堆内存即将耗尽" + description: "服务 {{ $labels.application }} 堆内存使用率 {{ $value | printf \"%.2f\" }}%,请立即处理" + + # GC 时间过长 + - alert: GCTimeTooHigh + expr: rate(jvm_gc_pause_seconds_sum[5m]) > 0.5 + for: 5m + labels: + severity: warning + annotations: + summary: "GC 时间过长" + description: "服务 {{ $labels.application }} GC 时间占比过高,可能影响性能" + + # ==================== HTTP 请求告警 ==================== + - name: http_requests + rules: + # 高错误率 + - alert: HighErrorRate + expr: sum(rate(http_server_requests_seconds_count{status=~"5.."}[5m])) by (application) / sum(rate(http_server_requests_seconds_count[5m])) by (application) > 0.05 + for: 5m + labels: + severity: warning + annotations: + summary: "HTTP 请求错误率过高" + description: "服务 {{ $labels.application }} 5xx 错误率 {{ $value | printf \"%.2f\" }}%" + + # 响应时间过长 + - alert: HighResponseTime + expr: histogram_quantile(0.95, sum(rate(http_server_requests_seconds_bucket[5m])) by (le, application)) > 2 + for: 5m + labels: + severity: warning + annotations: + summary: "HTTP 响应时间过长" + description: "服务 {{ $labels.application }} P95 响应时间 {{ $value | printf \"%.2f\" }} 秒" + + # ==================== 数据库连接池告警 ==================== + - name: database_connections + rules: + # HikariCP 连接池使用率过高 + - alert: HikariPoolUsageHigh + expr: (hikaricp_connections_active / hikaricp_connections_max) * 100 > 80 + for: 5m + labels: + severity: warning + annotations: + summary: "数据库连接池使用率过高" + description: "服务 {{ $labels.application }} 连接池使用率 {{ $value | printf \"%.2f\" }}%" + + # 连接池等待 + - alert: HikariPoolPending + expr: hikaricp_connections_pending > 0 + for: 2m + labels: + severity: warning + annotations: + summary: "数据库连接池存在等待" + description: "服务 {{ $labels.application }} 有 {{ $value }} 个连接请求在等待" + + # ==================== 系统资源告警 ==================== + - name: system_resources + rules: + # CPU 使用率过高 + - alert: HighCPUUsage + expr: system_cpu_usage * 100 > 80 + for: 5m + labels: + severity: warning + annotations: + summary: "CPU 使用率过高" + description: "服务 {{ $labels.application }} CPU 使用率 {{ $value | printf \"%.2f\" }}%" + + # 进程打开文件描述符过多 + - alert: HighFileDescriptorUsage + expr: process_files_open_files / process_files_max_files * 100 > 80 + for: 5m + labels: + severity: warning + annotations: + summary: "文件描述符使用率过高" + description: "服务 {{ $labels.application }} 文件描述符使用率 {{ $value | printf \"%.2f\" }}%" diff --git a/fund-gateway/src/main/resources/application-docker.yml b/fund-gateway/src/main/resources/application-docker.yml new file mode 100644 index 0000000..56b4b87 --- /dev/null +++ b/fund-gateway/src/main/resources/application-docker.yml @@ -0,0 +1,113 @@ +# Docker 环境配置 - Gateway +server: + port: ${SERVER_PORT:8000} + +spring: + application: + name: fund-gateway + profiles: + active: ${SPRING_PROFILES_ACTIVE:docker} + + cloud: + nacos: + server-addr: ${NACOS_SERVER_ADDR:nacos:8848} + username: ${NACOS_USERNAME:nacos} + password: ${NACOS_PASSWORD:nacos} + discovery: + namespace: ${NACOS_NAMESPACE:} + group: DEFAULT_GROUP + enabled: true + + gateway: + discovery: + locator: + enabled: true + lower-case-service-id: true + routes: + - id: fund-sys + uri: lb://fund-sys + predicates: + - Path=/api/sys/** + filters: + - StripPrefix=1 + - id: fund-cust + uri: lb://fund-cust + predicates: + - Path=/api/cust/** + filters: + - StripPrefix=1 + - id: fund-proj + uri: lb://fund-proj + predicates: + - Path=/api/proj/** + filters: + - StripPrefix=1 + - id: fund-req + uri: lb://fund-req + predicates: + - Path=/api/req/** + filters: + - StripPrefix=1 + - id: fund-exp + uri: lb://fund-exp + predicates: + - Path=/api/exp/** + filters: + - StripPrefix=1 + - id: fund-receipt + uri: lb://fund-receipt + predicates: + - Path=/api/receipt/** + filters: + - StripPrefix=1 + - id: fund-report + uri: lb://fund-report + predicates: + - Path=/api/report/** + filters: + - StripPrefix=1 + - id: fund-file + uri: lb://fund-file + predicates: + - Path=/api/file/** + filters: + - StripPrefix=1 + +# JWT 配置 +jwt: + secret: YourSecretKeyForJWTTokenGenerationMustBeAtLeast256BitsLong + expiration: 86400000 + +# Actuator 监控端点配置 +management: + endpoints: + web: + exposure: + include: health,info,metrics,prometheus + base-path: /actuator + endpoint: + health: + show-details: always + probes: + enabled: true + health: + livenessstate: + enabled: true + readinessstate: + enabled: true + metrics: + tags: + application: ${spring.application.name} + distribution: + percentiles-histogram: + http.server.requests: true + percentiles: + http.server.requests: 0.5,0.95,0.99 + +# 日志配置 +logging: + level: + root: INFO + com.fundplatform: DEBUG + pattern: + console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] %-5level %logger{36} - %msg%n" diff --git a/fund-sys/src/main/resources/application-docker.yml b/fund-sys/src/main/resources/application-docker.yml new file mode 100644 index 0000000..642df80 --- /dev/null +++ b/fund-sys/src/main/resources/application-docker.yml @@ -0,0 +1,84 @@ +# Docker 环境配置 +server: + port: ${SERVER_PORT:8100} + +spring: + application: + name: fund-sys + profiles: + active: ${SPRING_PROFILES_ACTIVE:docker} + + # 数据源配置 + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://${MYSQL_HOST:mysql}:${MYSQL_PORT:3306}/${MYSQL_DB:fund_platform}?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true + username: ${MYSQL_USER:root} + password: ${MYSQL_PASSWORD:root123} + hikari: + pool-name: FundSysHikariPool + minimum-idle: 5 + maximum-pool-size: 20 + idle-timeout: 30000 + max-lifetime: 1800000 + connection-timeout: 30000 + + # Redis 配置 + data: + redis: + host: ${REDIS_HOST:redis} + port: ${REDIS_PORT:6379} + + # Nacos 配置 + cloud: + nacos: + server-addr: ${NACOS_SERVER_ADDR:nacos:8848} + username: ${NACOS_USERNAME:nacos} + password: ${NACOS_PASSWORD:nacos} + discovery: + namespace: ${NACOS_NAMESPACE:} + group: DEFAULT_GROUP + enabled: true + +# MyBatis Plus 配置 +mybatis-plus: + mapper-locations: classpath*:/mapper/**/*.xml + global-config: + db-config: + id-type: ASSIGN_ID + logic-delete-field: deleted + logic-delete-value: 1 + logic-not-delete-value: 0 + +# Actuator 监控端点配置 +management: + endpoints: + web: + exposure: + include: health,info,metrics,prometheus + base-path: /actuator + endpoint: + health: + show-details: always + probes: + enabled: true + health: + livenessstate: + enabled: true + readinessstate: + enabled: true + metrics: + tags: + application: ${spring.application.name} + distribution: + percentiles-histogram: + http.server.requests: true + percentiles: + http.server.requests: 0.5,0.95,0.99 + +# 日志配置 +logging: + level: + root: INFO + com.fundplatform: DEBUG + pattern: + console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] %-5level %logger{36} - %msg%n" diff --git a/pom.xml b/pom.xml index e80688c..4f11f21 100644 --- a/pom.xml +++ b/pom.xml @@ -60,6 +60,21 @@ + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + io.micrometer + micrometer-registry-prometheus + + +