LeungTzeMeen
发布于 2026-05-21 / 10 阅读 / 0 评论 / 0 点赞

微服务架构优化:API网关统一收口与多维监控体系构建

大家好!今天为大家带来一篇纯硬核、极其震撼的云原生演进实战指南。我们将彻底贯彻软件工程最高合规的开闭原则(OCP)与高内聚低耦合核心思想,在完全不侵入、不改动任何一行业务源码的前提下,为单台云服务器亲手打造一套涵盖网关层、物理层、中间件层、业务应用层的四维一体生产级立体监控网络!

在这套架构落成之前,你可能也面临着同样的痛点:各种高位私密端口(3000、8000、8081、8082)在公网上裸奔引线、门户大开,既不安全,又毫无章法。而在这场战役打完之后,所有的监控流量、指标采集全部在 Docker 内部的高速骨干网 wiselink-net 中潜行,外网仅由统一网关实现高阶多路复用安全收口。

本文将拒绝一切平铺直叙,完全按照我们这两天真实踩坑、单兵破局、最终合合围的真实战线时间线进行单步拆解。所有敏感配置已进行全量脱敏,代码块可以直接一键复制,带你体验一场属于架构师的降维打击快感!


一、 监控的基石:Prometheus 内核与 Grafana 渲染引擎的优雅建立

在正式行军布阵之前,我们先以无上的敬意来明确我们大后方这两位顶级大将的底层分工与铁律:

  • Prometheus(普罗米修斯):时序数据库。它扮演的是一个极其严厉、铁面无私的“数据巡逻卫兵”角色。它在内网中每隔固定时间(如 15 秒)就会根据配置好的接口去各个容器“叩门”拉取(Pull)最新的指标数据。

  • Grafana(格拉法纳):数据可视化渲染引擎。它是一个纯粹的艺术大师,自己不生产数据,也不保存数据,它负责从 Prometheus 的肚子里把冷冰冰的时序数字捞出来,用极其精美、硬核的动态仪表盘折线图渲染在屏幕上。

1. 践行开闭原则:编写 Prometheus 动态插槽主配置

为了实现未来新增任何监控程序时,主配置文件达到“一字不改、拒绝重启、对修改关闭”的最高工业合规,我们直接采用高级的 文件服务发现(file_sd_configs 机制。

在宿主机创建相互隔离的动态配置目录:

bash

mkdir -p /opt/my-server/monitor/prometheus/targets/infra
mkdir -p /opt/my-server/monitor/prometheus/targets/apps

请谨慎使用此类代码。

写入 Prometheus 通用核心配置文件:

bash

nano /opt/my-server/monitor/prometheus/prometheus.yml

请谨慎使用此类代码。

yaml

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  # 统一基础设施数据命名空间(动态热扫描硬件、数据库、网关)
  - job_name: 'infrastructure-targets'
    file_sd_configs:
      - files:
          - '/etc/prometheus/targets/infra/*.json'
        refresh_interval: 1m

  # 统一业务应用层数据命名空间(动态热扫描各个 Java 后端服务)
  - job_name: 'application-targets'
    file_sd_configs:
      - files:
          - '/etc/prometheus/targets/apps/*.json'
        refresh_interval: 1m

请谨慎使用此类代码。

2. 并入内部骨干网:监控域核心编排

为了将 Prometheus 脆弱的 9090 端口在公网上彻底隐藏,我们让监控容器直接并入已有的外部公共骨干虚拟网络 wiselink-net 中,使其具备极高的内聚性。

编写监控域编排文件:

bash

nano /opt/my-server/monitor/docker-compose.yml

请谨慎使用此类代码。

yaml

version: '3.8'

services:
  prometheus:
    image: prom/prometheus:v2.51.1
    container_name: monitor-prometheus
    restart: always
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - ./prometheus/targets:/etc/prometheus/targets:ro
      - prometheus-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
    networks:
      - wiselink-net

  grafana:
    image: grafana/grafana:10.4.2
    container_name: monitor-grafana
    restart: always
    ports:
      - "3000:3000" # 调试阶段临时开放,后续会由网关反代收口
    volumes:
      - grafana-data:/var/lib/grafana
    networks:
      - wiselink-net

volumes:
  prometheus-data:
    driver: local
  grafana-data:
    driver: local

networks:
  wiselink-net:
    external: true

请谨慎使用此类代码。

一键优雅拉起监控底座:

bash

cd /opt/my-server/monitor && docker compose up -d

请谨慎使用此类代码。

此时打开浏览器,通过宿主机临时暴露的 3000 端口登录 Grafana 网页,在 Data Sources 中添加 Prometheus 数据源,URL 极其高级地直接填入容器内网解析地址:http://monitor-prometheus:9090,瞬间完成内网第一次灵魂大握手!


二、 第一高地:物理层 · 阿里云主机硬件监控搭建

基础设施即代码!我们攻克的第一套监控,是针对整台云服务器最底层的物理指标(CPU、内存、系统盘水位、以及网络的吞吐流量)。

1. 增量追加物理指标采集器

打开监控域编排文件,在 services: 节点下平级追加官方经典的轻量主机指标采集服务 node-exporter

bash

nano /opt/my-server/monitor/docker-compose.yml

请谨慎使用此类代码。

yaml

  node-exporter:
    image: prom/node-exporter:v1.8.0
    container_name: monitor-node-exporter
    restart: always
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    command:
      - '--path.procfs=/host/proc'
      - '--path.sysfs=/host/sys'
      - '--path.rootfs=/rootfs'
    networks:
      - wiselink-net

请谨慎使用此类代码。

让监控域执行一次优雅的增量热更新:

bash

docker compose up -d

请谨慎使用此类代码。

2. 动态注入插槽,见证服务自愈发现

此时完美验证开闭原则(OCP)!我们不需要重启 Prometheus,直接往对应的基础设施插槽目录下丢入一个主机的 JSON 注册文件:

bash

nano /opt/my-server/monitor/prometheus/targets/infra/host_metrics.json

请谨慎使用此类代码。

json

[
  {
    "targets": ["monitor-node-exporter:9100"],
    "labels": {
      "environment": "production",
      "instance": "aliyun-server-01"
    }
  }
]

请谨慎使用此类代码。

保存退出后一分钟内,Prometheus 巡逻卫兵自动动态吞入该配置。我们直接前往 Grafana 网页端,导入全球公认最负盛名的硬件神级面板 ID 1860,并将此看板重命名为:01_物理层_阿里云主机硬件监控。整台主机的 CPU 曲线与磁盘负载波形瞬间活了过来!


三、 第二高地:中间件层 · Halo 博客 PostgreSQL 数据库监控接入

在云原生微服务中,数据库是整个架构的命脉。接下来我们挺进中间件域,对部署在 infrastructure/ 下(或独立网格中)的 halo-db (PostgreSQL 15) 容器展开无暴露监控。

1. 旁路挂载数据库采集器

打开监控域编排文件,平级追加 postgres-exporter,利用容器网格的内聚性隔空跨库访问:

bash

nano /opt/my-server/monitor/docker-compose.yml

请谨慎使用此类代码。

yaml

  postgres-exporter:
    image: prometheuscommunity/postgres-exporter:v0.15.0
    container_name: monitor-postgres-exporter
    restart: always
    environment:
      # 用户名、密码、数据库名已做脱敏处理,请替换为你本地真实的数据库部署配置
      - DATA_SOURCE_NAME=postgresql://your_db_user:your_db_password@halo-db:5432/your_db_name?sslmode=disable
    networks:
      - wiselink-net

请谨慎使用此类代码。

拉起独立采集容器:

bash

docker compose up -d

请谨慎使用此类代码。

2. 动态注册,数据流闭环

同样在基础设施动态插槽下,新建对应的数据库时序注册文件:

bash

nano /opt/my-server/monitor/prometheus/targets/infra/postgres_metrics.json

请谨慎使用此类代码。

json

[
  {
    "targets": ["monitor-postgres-exporter:9187"],
    "labels": {
      "environment": "production",
      "instance": "halo-postgres-db"
    }
  }
]

请谨慎使用此类代码。

在 Grafana 导入经典数据库全景面板 ID 9628,并将其优雅地执行语义对齐重命名为:02_中间件_公共PostgreSQL数据库监控。此时,数据库的平均 CPU 耗时、打开的文件句柄数、以及物理 IO 连接数全部完美刷新。


四、 第三高地:应用层 · Halo 博客 JVM 虚拟机无侵入外挂技术破局

为了在完全不修改第三方业务(Halo博客)源码、不引入重度耦合的前提下透视其运行时底细,我们采用全行业最顶尖、最优雅的 “JVM 专家外挂(Java Agent)” 战术。

1. 惊险肉搏:粉碎 3.8K 坏包,斩获二进制 JAR 真包

这是整场战役中最具工匠精神的破局点!由于官方中央仓库的网络重定向与波动,直接在终端下载长链接容易被“截和”,下载成一个只有 3.8K 的网页前端 HTML 源码,导致 Java 虚拟机在冷启动时解压报错、发生致命闪退。

我们采用极其优雅的“拆解无域名碎片段并在终端进行变量拼接”的高阶技巧,强行从国内阿里云公共制品库中下载到毫无损坏的真包。

bash

# 1. 建立外挂资产口袋目录
mkdir -p /opt/my-server/blog-halo/utils

# 2. 调用底层强大的 curl 追踪下载二进制流
curl -L -o /opt/my-server/blog-halo/utils/jmx_prometheus_javaagent.jar "https://maven.aliyun.com/repository/public/io/prometheus/jmx/jmx_prometheus_javaagent/0.20.0/jmx_prometheus_javaagent-0.20.0.jar"

请谨慎使用此类代码。

验证物理体积,看到显示为精准的 564K(576,924 字节)即代表大功告成:

bash

ls -lh /opt/my-server/blog-halo/utils/jmx_prometheus_javaagent.jar

请谨慎使用此类代码。

为其配备一个采用默认规则收集全量 JVM MBean 指标的 YAML 配置文件说明书:

bash

nano /opt/my-server/blog-halo/utils/jmx_config.yaml

请谨慎使用此类代码。

yaml

rules: [{ pattern: ".*" }]

请谨慎使用此类代码。

2. 重构 Halo 编排:物理焊死启动外挂

打开 Halo 博客的物理编排配置文件,将外挂工具包以只读(ro)卷的形式注入容器,并在其 command 启动命令的 java 最前方直接物理焊死挂载参数,让其在容器内网默默监听属于它的 12345 监控专线端口:

bash

nano /opt/my-server/blog-halo/docker-compose.yml

请谨慎使用此类代码。

yaml

  halo:
    image: halohub/halo:2.10
    container_name: halo
    restart: always
    ports:
      - "8090:8090"
    volumes:
      - ./data:/root/.halo2
      # === 1. 挂载我们亲手斩获的二进制 JAR 资产 ===
      - ./utils:/opt/utils:ro
    # === 2. 拒绝任何中间中转变量,在 java 命令最前端直接焊死外挂路径 ===
    command: >
      java -javaagent:/opt/utils/jmx_prometheus_javaagent.jar=12345:/opt/utils/jmx_config.yaml
           --spring.r2dbc.url=r2dbc:postgresql://halo-db:5432/halo
           --spring.r2dbc.username=your_user
           --spring.r2dbc.password=your_password
           --spring.sql.init.platform=postgresql
           --halo.external-url=http://your_server_ip/
    networks:
      - wiselink-net

请谨慎使用此类代码。

重构拉起业务容器,彻底告别闪退:

bash

cd /opt/my-server/blog-halo && docker compose down && docker compose up -d

请谨慎使用此类代码。

3. 动态插槽合围与接口对齐

前往业务监控动态插槽目录,创建我们的第一个 Java 业务注册实现类:

bash

nano /opt/my-server/monitor/prometheus/targets/apps/java_apps.json

请谨慎使用此类代码。

json

[
  {
    "targets": ["halo:12345"],
    "labels": {
      "environment": "production",
      "app_name": "halo-blog"
    }
  }
]

请谨慎使用此类代码。

前往 Grafana 页面,导入全球经典的 JVM 终极面板 ID 8563。进入变量设置中心,彻底清空阻碍新版系统数据流向的复杂历史残留 Regex 正则表达式。大盘最顶部的 instance 下拉菜单瞬间被强行唤醒,完美勾选出了 halo:12345!自此,第三方博客 Java 虚拟机的堆内存分布、GC 垃圾回收暂停频率、线程总数全部呈现在眼前!


五、 核心总攻:业务层 · AI 导购项目 JVM 优雅并入

在彻底验证了“虚拟机层无侵入挂载”的可行性与高可用性后,我们立刻吹响总攻号角,对系统里资源消耗最大(常驻内存达 600M+)的自研王牌王座项目 —— wiselink-server (智选灵犀 AI 后端 - Java 21 生態) 发起合围。

1. 极速克隆完好资产

为了不产生任何多余的代码和编译负担,我们不改动一行 Java 源码(不需要改 pom.xml 依赖,不需要重新打包发布),直接通过本地资产克隆,把刚才饱经风霜拿下的完好二进制文件复制过去:

bash

mkdir -p /opt/my-server/wiselink-shopper/utils
cp /opt/my-server/blog-halo/utils/jmx_prometheus_javaagent.jar /opt/my-server/wiselink-shopper/utils/
cp /opt/my-server/blog-halo/utils/jmx_config.yaml /opt/my-server/wiselink-shopper/utils/

请谨慎使用此类代码。

2. 重构 AI 项目编排:开辟 12346 隐形内网端点

打开 AI 导购项目的物理编排文件,同样在 volumes 中挂载包,并在 command 命令里的 java 后方直接平铺焊死 Agent 路径,分配一个全新的、符合我们规律性递增原则的隐形端口 12346

bash

nano /opt/my-server/wiselink-shopper/docker-compose.yml

请谨慎使用此类代码。

yaml

  wiselink-app:
    build: ./app-backend
    container_name: wiselink-server
    restart: always
    # === 物理焊死 12346 容器内部监控专线,彻底杜绝转义卡壳 ===
    command: >
      java -javaagent:/opt/utils/jmx_prometheus_javaagent.jar=12346:/opt/utils/jmx_config.yaml
           -Dfile.encoding=UTF-8
           -Dspring.config.location=file:/app/app-backend/config/application.yml
           -Dlogging.config=file:/app/app-backend/config/logback-spring.xml
           -jar /app/app-backend/gen-ai-agent-0.0.1-SNAPSHOT.jar
    env_file: .env
    volumes:
      - ./app-backend:/app/app-backend
      - ./mcp-server:/app/mcp-server
      - ./utils:/opt/utils:ro
    working_dir: /app
    environment:
      - TZ=Asia/Shanghai
      - WISELINK_MCP_WORKSPACE_ROOT=/app/mcp-server
      - SPRING_PROFILES_ACTIVE=prod
      - WISELINK_PDF_FONT=/app/app-backend/fonts/wqy-microhei.ttc,0
    networks:
      - wiselink-net

请谨慎使用此类代码。

热更新热拉起,让庞大的 Java 21 虚拟机带着外挂冲锋:

bash

cd /opt/my-server/wiselink-shopper && docker compose down && docker compose up -d

请谨慎使用此类代码。

3. 接口复用:见证多路复用时序标签的极致艺术

享受开闭原则红利的巅峰时刻到了!我们完全不需要去改动任何 Grafana 里的核心图表,直接去修改刚才创建的那个 java_apps.json 插槽文件,以标准的 JSON 数组对象格式追加一行注册信息:

bash

nano /opt/my-server/monitor/prometheus/targets/apps/java_apps.json

请谨慎使用此类代码。

json

[
  {
    "targets": ["halo:12345"],
    "labels": {
      "environment": "production",
      "app_name": "halo-blog"
    }
  },
  {
    "targets": ["wiselink-server:12346"],
    "labels": {
      "environment": "production",
      "app_name": "wiselink-shopper-backend"
    }
  }
]

请谨慎使用此类代码。

保存退出的那一瞬间,Prometheus 内核自动在后台完成无损动态加载,全线亮起绿色。我们回到刚刚调好的 8563 看板上,刷新网页,点开顶部的 instance 下拉框,你会极其震撼、优雅地发现,里面并列多出了一个可供勾选的选项:wiselink-server:12346

点击勾选它,你核心自研大模型项目的 Java 21 真实内存分配、打字机流式线程状态彻底在大屏中完美渲染!鉴于这张看板职责全盘升级,我们将其重命名为:03_业务层_多应用JVM组件通用监控


六、 终章大合围:最外层统一流量网关(NPM)多路复用与安全收口

走到这里,硬件、中间件、双应用层的数据链路已全部合围畅通。但在没有域名的阶段,宿主机上还零散、破绽百出地对外暴露着 3000(Grafana)、8000(AI前端)、8081(AI后端)和由主进程拉起的子进程通过 8082 端口直接对外暴露的 MCP 动态智能选购报告大 PDF 下载接口

为了达到企业级的终极安全,我们利用已部署的 Nginx Proxy Manager (NPM) 统一流量网关,打了一场堪称艺术品的“端口多路复用安全阻击战”

1. 统一数据总线路由:重构微服务局部前端 nginx.conf

为了把后端的 8082 子进程文件下载路径在内网里彻底归纳收口,我们修改大模型项目的局部前端 Nginx 路由器配置,强行追加物理文件反代总线:

bash

nano /opt/my-server/wiselink-shopper/app-frontend/nginx.conf

请谨慎使用此类代码。

nginx

server {
    listen       8000;
    server_name  localhost;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        proxy_pass http://wiselink-server:8081;
        proxy_buffering off; # AI 大模型流式打字机响应必须
        proxy_cache off;
    }

    # 核心突破:将 MCP 产生的物理文件下载链接(8082端口),利用骨干网在前端完成无暴露收口
    location /exports/ {
        proxy_pass http://wiselink-server:8082;
        proxy_read_timeout 600s;
        proxy_send_timeout 600s;
    }
}

请谨慎使用此类代码。

同时,我们去大模型项目的环境变量配置文件 .env 中,将下载基准前缀修改为未来统一的网关侧门端口(8080),让 Java 后端生成 PDF 报告时自动对齐网关大门:

bash

nano /opt/my-server/wiselink-shopper/.env

请谨慎使用此类代码。

properties

# === 完美对齐统一网关的对外文件流通道 ===
WISELINK_EXPORT_BASE_URL=http://your_server_ip:8080

请谨慎使用此类代码。

一键重启使环境彻底洗净:docker compose down && docker compose up -d

2. 网关高级多路复用:建立 NPM 独立路由哨兵模式

在没有域名且 IP 冲突的阶段,为了不破坏原有的博客代理路由,我们在 NPM 管理后台配置出了全行业最完美的 “多 Proxy Host 独立哨兵模式”

  • 第一行主规则(绑定了真实公网 IP):它的 Details 里配置转发 halo:8090,极其内聚地只负责为你服务器的默认 80 端口(最外层默认门户)把守大门。它的 Advanced 高级配置框内保持绝对空白,绝不进行多余平铺监听,防止发生 503 语境死锁冲突。

  • 第二行规则(monitor.local 独立路由哨兵):Details 里的域名写 monitor.local 用于占位。重点是在它的 Advanced 高级自定义代码框内写下一行 Nginx 底层硬监听代码:

    nginx

    listen 3001;
    

    请谨慎使用此类代码。

    底层真相:网关大楼会专门在底层生成一个隔离的、专门守候 3001 端口的子服务器块(Server Block)。外网访问 http://IP:3001,由网关在内网以潜行方式无暴露交到 monitor-grafana:3000

  • 第三行规则(wiselink.local 独立路由哨兵):Details 域名写 wiselink.local 占位,在它的 Advanced 黑色配置框内同样写下一行硬指令:

    nginx

    listen 8080;
    

    请谨慎使用此类代码。

    底层真相:网关专门为你的自研 AI 项目大门开辟 8080 专属侧门,任何外网敲击 8080 端口的前端对话和大模型流式请求,直接进入网关内部进行安全防洗,并在内网塞给前端容器 wiselink-nginx:8000,一并以高内聚姿态带走了 PDF 文件下载流!

3. 最后一毫米的完美收尾:接入网关层统一流量与安全监控

既然所有流量百分之百都会经过最外层的统一网关 NPM,我们怎么能放过这个拥有“上帝视角”的防弹盾牌?我们乘胜追击,把这最后一毫米的缺口彻底焊死。

打开监控域编排配置文件,平级挂载一个旁路轻量网关指标代理 nginx-exporter。得益于 NPM 官方镜像已经在内网隐藏的 82 端口上默认开启了 /nginx_status 监控端点,采集代理在同一个虚拟网格内可以直接隔空抓取:

bash

nano /opt/my-server/monitor/docker-compose.yml

请谨慎使用此类代码。

yaml

  # === 终极闭网:统一网关流量指标采集服务 ===
  nginx-exporter:
    image: nginx/nginx-prometheus-exporter:1.1.0
    container_name: monitor-nginx-exporter
    restart: always
    command:
      - '-nginx.scrape-uri=http://wiselink-gateway:82/nginx_status'
    networks:
      - wiselink-net

请谨慎使用此类代码。

增量拉起小代理服务:docker compose up -d

在基础设施动态插槽下,丢入最后这临门一脚的网关注册文件:

bash

nano /opt/my-server/monitor/prometheus/targets/infra/gateway_metrics.json

请谨慎使用此类代码。

json

[
  {
    "targets": ["monitor-nginx-exporter:9113"],
    "labels": {
      "environment": "production",
      "instance": "wiselink-main-gateway"
    }
  }
]

请谨慎使用此类代码。

回到 Grafana 页面上,导入官方原生适配的网关时序看板 ID 14900。进入大盘后,在最顶部的 instance 下拉菜单里,精准勾选、锁死我们的 wiselink-main-gateway 实例。在 Variables 中同样重置可视化积木表单以消除版本错位缓存,最后按下 Ctrl + S 将其进行永久固化保存!

我们将该看板重命名为我们的终极总控代号:00_网关层_统一接入流量与安全监控。全站的总连接并发数、网络输入输出总吞吐量,全部开始极其丝滑、漂亮地在屏幕前波澜壮阔地动态跳动起来!


七、 拔线凯旋:终极安全防线合围成果盘点

在网关的多端口多路复用路由通过最后一轮硬核灰度测试后,我们带着无上的骄傲,前往各个业务项目的 docker-compose.yml 中,将那些曾经裸奔暴露在外的物理引线端口(3000800080818082无情、坚决、全部用 # 号进行了彻底的注释与抹除关闭

此时此刻,我们回到阿里云控制台的安全组规则里:

  • 彻底、永远地粉碎删除 3000、8000、8081、8082 的外网通行证;

  • 整台云服务器对公网仅放行四个大门80(默认博客门户)、443(安全HTTPS通道)、3001(统一监控域侧门)、8080(核心自研AI导购侧门)。

转过身来,在这张干净利落、没有任何冗余死代码的控制台列表前,一整座如艺术品般完美的企业级四维生产级大后方矩阵宣告彻底、永固落成:

  • 00_网关层_统一接入流量与安全监控 🚪 (已完美固化实例,全站总连接吞吐线正极其丝滑地跳动)

  • 01_物理层_阿里云主机硬件监控 🖥️ (服务器底层 CPU、内存、网络、系统盘全景透视)

  • 02_中间件_公共PostgreSQL数据库监控 🗄️ (Postgres 物理连接、平均CPU时间与句柄开销全量站岗)

  • 03_业务层_多应用JVM组件通用监控 ☕ (AI 导购后端、Halo 博客两大核心 Java 21/17 虚拟机完美双实例切换)

更令人兴奋的是,这套架构拥有无与伦比的超前拓展性。未来某一天你买了正式域名,只需要在网关 NPM 界面用 10 秒钟把 Domain 栏的占位符换成你的真实二级域名,勾选申请免费的 SSL 证书,底下的所有容器虚拟网格、JVM 虚拟机外挂、以及目前的时序看板配置通通一字都不用改,在线预览等功能就会顺理成章、优雅地直接复活!

整条立体防线就会在完全不间断系统的前提下,瞬间平滑升级为最高合规的 HTTPS 全加密企业级大后方监控

这,就是属于云原生、DevOps与高级架构师的绝对重构艺术。希望这篇实战长文能够为你筑起大后方坚固的防御长城提供最清澈的灵感。