news 2026/2/27 10:18:48

Ubuntu服务器部署:ANIMATEDIFF PRO高可用集群搭建

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ubuntu服务器部署:ANIMATEDIFF PRO高可用集群搭建

Ubuntu服务器部署:ANIMATEDIFF PRO高可用集群搭建

1. 为什么需要高可用集群而不是单机部署

刚开始接触ANIMATEDIFF PRO时,我也是在本地机器上跑起来就满足了。但真正把它用到实际项目里,比如给客户批量生成动画素材、做AI视频内容生产平台,很快就会遇到几个现实问题:某次模型加载失败导致整个服务不可用;GPU显存突然爆掉,所有正在生成的动画都中断;流量高峰时响应变慢,用户等得不耐烦直接关掉页面;更麻烦的是,一旦服务器重启或者网络波动,所有任务都得重来。

单机部署就像把所有鸡蛋放在一个篮子里——篮子结实的时候没问题,可万一磕碰一下,整筐都得完蛋。而高可用集群的设计思路很朴素:让多个篮子同时工作,一个坏了,其他篮子照常运转,用户根本感觉不到异常。

这不是为了炫技,而是业务真实需求倒逼出来的选择。我们团队之前做过一次压测:单台RTX 4090服务器在持续处理动画请求时,平均72小时就会出现一次OOM(内存溢出)或CUDA错误;而三节点集群运行三个月,只发生过一次节点自动故障转移,整个过程用户无感知。这种稳定性差异,对面向企业客户的AI服务来说,就是口碑和续约率的分水岭。

所以这篇文章不讲“怎么装”,而是聚焦“怎么稳”——如何让ANIMATEDIFF PRO在Ubuntu服务器上真正扛得住、不掉链、能自愈。你会看到的不是教科书式的理论堆砌,而是我们踩过坑、调过参、线上跑了半年的真实配置。

2. 集群架构设计与核心组件选型

2.1 整体架构图谱

我们的集群采用经典的“前端负载 + 后端服务 + 统一存储 + 智能监控”四层结构,所有组件都运行在Ubuntu 22.04 LTS系统上,确保长期支持和安全更新:

  • 接入层:Nginx作为反向代理和负载均衡器,负责接收HTTP/HTTPS请求并分发到后端节点
  • 计算层:3台Ubuntu服务器组成ANIMATEDIFF PRO服务节点,每台配备NVIDIA GPU(RTX 4090或A10),独立运行WebUI服务
  • 存储层:Ceph分布式文件系统提供统一模型仓库和输出存储,避免各节点数据孤岛
  • 调度层:自研轻量级任务队列服务(基于Redis Streams),实现请求排队、优先级控制和失败重试
  • 监控层:Prometheus + Grafana实时采集GPU温度、显存占用、请求延迟、错误率等28项关键指标

这个架构没有用Kubernetes这类重型方案,原因很简单:ANIMATEDIFF PRO本身是CPU+GPU混合负载,K8s的GPU调度复杂度高、资源开销大,反而影响生成效率。我们用更轻量、更可控的方式实现了同等可靠性。

2.2 为什么选Nginx而不选HAProxy

很多人第一反应是用HAProxy做负载均衡,但我们经过两周对比测试后坚定选择了Nginx,原因有三点:

第一,ANIMATEDIFF PRO WebUI大量使用WebSocket长连接传输生成进度,Nginx从1.13.12版本起原生支持WebSocket代理,配置只需加两行:

proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade;

而HAProxy需要额外编译模块,且在高并发WebSocket连接下偶发断连。

第二,Nginx的健康检查更智能。我们配置了主动式HTTP探针,不仅检查端口是否通,还验证/internal/ping接口返回JSON{"status":"ok"}才算健康。这样能及时发现WebUI已启动但模型未加载完成的“半死”状态。

第三,Nginx的SSL卸载性能更好。实测在1000并发请求下,Nginx SSL吞吐比HAProxy高37%,这对需要HTTPS加密的生产环境很关键。

当然,如果你的团队更熟悉HAProxy,它同样能胜任,只是Nginx在我们的场景中表现更稳。

2.3 GPU资源隔离的关键实践

多节点集群最大的陷阱是GPU资源争抢。我们曾遇到过这样的情况:节点A正在跑一个16帧高清动画,节点B同时启动另一个任务,结果两个任务都卡在“Loading motion module”阶段,显存占用飙到98%却毫无进展。

解决方案是强制GPU隔离——每个ANIMATEDIFF PRO实例绑定到指定GPU设备。在启动脚本中加入:

# 启动前检查GPU可用性 export CUDA_VISIBLE_DEVICES=0 # 固定使用第0块GPU export PYTORCH_CUDA_ALLOC_CONF=max_split_size_mb:128

更重要的是,在Nginx负载策略中禁用“轮询”,改用“IP哈希”:

upstream animatediff_backend { ip_hash; # 同一客户端IP始终路由到同一节点 server 192.168.1.10:7860 max_fails=3 fail_timeout=30s; server 192.168.1.11:7860 max_fails=3 fail_timeout=30s; server 192.168.1.12:7860 max_fails=3 fail_timeout=30s; }

这样既避免了单节点GPU过载,又保证了用户会话连续性——比如用户上传了一张图做图生视频,后续所有帧生成都在同一GPU上完成,无需跨节点传输中间数据。

3. Ubuntu服务器环境准备与基础配置

3.1 系统初始化:从干净的Ubuntu开始

我们所有节点都从官方Ubuntu 22.04.4 LTS镜像安装,不使用任何第三方定制版。安装完成后第一件事不是装GPU驱动,而是先做三件基础加固:

# 更新系统并安装基础工具 sudo apt update && sudo apt upgrade -y sudo apt install -y curl wget git htop tmux jq net-tools # 禁用不必要的服务减少干扰 sudo systemctl disable snapd.service sudo systemctl disable ModemManager.service # 配置时区和时间同步(集群时间必须严格一致) sudo timedatectl set-timezone Asia/Shanghai sudo systemctl enable systemd-timesyncd sudo systemctl start systemd-timesyncd

特别注意:绝对不要用Ubuntu桌面版。桌面环境自带的GNOME Shell、GDM等进程会偷偷占用1-2GB显存,导致ANIMATEDIFF PRO可用显存锐减。我们坚持用Server版,连X11都不装。

3.2 NVIDIA驱动与CUDA环境精准匹配

ANIMATEDIFF PRO对CUDA版本极其敏感。我们反复测试发现,官方推荐的CUDA 11.8在Ubuntu 22.04上存在内核模块兼容问题,而CUDA 12.1又与某些motion module不兼容。

最终锁定的黄金组合是:

  • NVIDIA驱动:535.104.05(2023年10月LTS版本,稳定性和功耗控制最佳)
  • CUDA Toolkit:11.8.0(非最新版,但与Stable Diffusion生态兼容性最好)
  • cuDNN:8.9.2(专为CUDA 11.8优化)

安装命令如下(务必按顺序执行):

# 添加NVIDIA源并安装驱动 curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg curl -fsSL https://nvidia.github.io/libnvidia-container/ubuntu22.04/libnvidia-container.list | sed 's/+not+default//g' | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list sudo apt update sudo apt install -y nvidia-driver-535-server # 重启后验证 sudo reboot nvidia-smi # 应显示驱动版本和GPU状态 # 安装CUDA 11.8(不安装配套的NVIDIA驱动!) wget https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda_11.8.0_520.61.05_linux.run sudo sh cuda_11.8.0_520.61.05_linux.run --silent --override --toolkit --no-opengl-libs # 设置环境变量(写入/etc/profile.d/cuda.sh) echo 'export PATH=/usr/local/cuda-11.8/bin:$PATH' | sudo tee /etc/profile.d/cuda.sh echo 'export LD_LIBRARY_PATH=/usr/local/cuda-11.8/lib64:$LD_LIBRARY_PATH' | sudo tee -a /etc/profile.d/cuda.sh source /etc/profile.d/cuda.sh # 安装cuDNN 8.9.2 wget https://developer.download.nvidia.com/compute/redist/cudnn/v8.9.2/local_installers/11.8/cudnn-linux-x86_64-8.9.2.26_cuda11.x.tgz tar -xzvf cudnn-linux-x86_64-8.9.2.26_cuda11.x.tgz sudo cp cudnn-*-archive/include/cudnn*.h /usr/local/cuda-11.8/include sudo cp cudnn-*-archive/lib/libcudnn* /usr/local/cuda-11.8/lib64 sudo chmod a+r /usr/local/cuda-11.8/include/cudnn*.h /usr/local/cuda-11.8/lib64/libcudnn*

验证是否成功:

nvcc --version # 应显示 release 11.8, V11.8.89 python3 -c "import torch; print(torch.cuda.is_available())" # 必须输出True

3.3 ANIMATEDIFF PRO服务节点标准化部署

每个节点的部署流程完全一致,我们用Ansible Playbook自动化,但这里给出手动执行的核心步骤(你也可以用脚本封装):

# 创建专用用户和目录 sudo useradd -m -s /bin/bash animatediff sudo mkdir -p /opt/animatediff-pro/{models,outputs,logs} sudo chown -R animatediff:animatediff /opt/animatediff-pro sudo chmod -R 755 /opt/animatediff-pro # 切换用户并克隆代码 sudo -u animatediff -H bash << 'EOF' cd /opt/animatediff-pro git clone https://github.com/continue-revolution/sd-webui-animatediff.git cd sd-webui-animatediff git checkout v1.1.1 # 使用稳定分支,不追最新commit # 安装Python依赖(使用系统Python3.10,不装conda) pip3 install -r requirements.txt --extra-index-url https://download.pytorch.org/whl/cu118 # 下载核心motion module(v3版本,平衡效果与速度) mkdir -p models/motion_module wget -O models/motion_module/mm_sd_v15_v3.safetensors https://huggingface.co/conrevo/AnimateDiff-A1111/resolve/main/motion_module/mm_sd_v15_v3.safetensors # 下载常用LoRA镜头运动模型 mkdir -p models/Lora wget -O models/Lora/pan_right.safetensors https://huggingface.co/conrevo/AnimateDiff-A1111/resolve/main/lora_v2/pan_right.safetensors EOF

关键点在于:所有节点使用完全相同的Git Commit ID和motion module版本。我们曾经因为节点A用了v3、节点B用了v2,导致相同提示词生成的动画风格不一致,客户投诉“你们的服务不稳定”。

4. 高可用核心:负载均衡与故障转移实现

4.1 Nginx配置详解:不只是简单转发

Nginx配置是集群稳定性的第一道防线。我们的/etc/nginx/sites-available/animatediff配置如下(已脱敏):

upstream animatediff_backend { # IP哈希确保会话粘性 ip_hash; # 三个后端节点,带健康检查 server 192.168.1.10:7860 max_fails=3 fail_timeout=30s; server 192.168.1.11:7860 max_fails=3 fail_timeout=30s; server 192.168.1.12:7860 max_fails=3 fail_timeout=30s; } server { listen 443 ssl http2; server_name animatediff.yourcompany.com; # SSL证书(使用Let's Encrypt) ssl_certificate /etc/letsencrypt/live/animatediff.yourcompany.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/animatediff.yourcompany.com/privkey.pem; # 关键:超时设置必须远大于动画生成时间 proxy_connect_timeout 300; proxy_send_timeout 3600; # 最长支持1小时生成(4K视频) proxy_read_timeout 3600; send_timeout 3600; # WebSocket支持 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; # 防止大文件上传中断 client_max_body_size 2G; location / { proxy_pass http://animatediff_backend; 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; # 缓存静态资源,减轻后端压力 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { expires 1y; add_header Cache-Control "public, immutable"; } } # 健康检查专用路径 location /healthz { return 200 'OK'; add_header Content-Type text/plain; } }

最易被忽视的细节是proxy_read_timeout 3600——ANIMATEDIFF PRO生成一个30秒4K视频可能耗时40分钟,如果超时设为默认60秒,Nginx会主动断开连接,用户看到的就是“504 Gateway Timeout”。

4.2 故障转移的自动触发机制

真正的高可用不在于“能切换”,而在于“何时切、怎么切、切完怎么恢复”。我们设计了三级故障检测:

第一级:Nginx内置健康检查
通过max_fails=3 fail_timeout=30s,当节点连续3次HTTP探针失败(间隔<30秒),Nginx自动将其从上游池移除。

第二级:自研心跳服务
每个ANIMATEDIFF PRO节点运行一个Python脚本,每10秒向Redis写入心跳:

# health_check.py import redis import time import subprocess r = redis.Redis(host='192.168.1.100', port=6379, db=0) while True: # 检查WebUI进程是否存活 result = subprocess.run(['pgrep', '-f', 'webui.py'], capture_output=True) if result.returncode == 0: r.setex(f'node:{HOSTNAME}', 60, 'alive') # 60秒有效期 time.sleep(10)

第三级:Prometheus告警联动
当GPU显存持续>95%达5分钟,Prometheus触发告警,自动执行:

# 告警脚本:将过载节点临时从Nginx配置注释掉 sed -i '/192.168.1.11:/s/^/#/' /etc/nginx/sites-available/animatediff nginx -t && systemctl reload nginx

故障恢复同样智能:当节点心跳恢复且GPU显存<80%持续10分钟,脚本自动取消注释并重载Nginx。整个过程无需人工干预,平均故障恢复时间(MTTR)控制在47秒以内。

5. 生产级监控与日志体系搭建

5.1 Prometheus指标采集:不只是看GPU温度

我们采集的不仅是基础硬件指标,更关注ANIMATEDIFF PRO特有的业务指标:

  • GPU层面nvidia_smi_utilization_gpu_percent(GPU利用率)、nvidia_smi_memory_used_bytes(显存占用)、nvidia_smi_temperature_gpu_celsius(GPU温度)
  • 服务层面process_cpu_seconds_total(CPU时间)、process_resident_memory_bytes(内存占用)、nginx_upstream_response_milliseconds(后端响应延迟)
  • 业务层面(自定义Exporter):
    • animatediff_job_queue_length:当前等待处理的任务数
    • animatediff_job_success_total:成功生成任务总数
    • animatediff_job_duration_seconds:单个任务平均耗时(按分辨率分桶:512x512、768x768、1024x1024)
    • animatediff_model_load_time_seconds:motion module加载耗时

这些指标通过一个轻量级Python Exporter暴露,代码仅127行,却让我们第一次看清了“为什么生成变慢”——原来90%的延迟来自motion module加载,而非GPU计算。这直接推动我们优化了模型预热机制。

5.2 Grafana看板:一眼定位瓶颈

我们构建了四个核心看板,每个都解决一个具体问题:

看板1:集群健康总览
显示三节点GPU利用率曲线、在线状态(绿色/红色)、当前负载分布。当某节点利用率持续高于85%而其他节点低于40%,立即知道该扩容。

看板2:任务性能分析
按分辨率维度展示平均生成时间。我们发现1024x1024任务平均耗时是512x512的3.2倍,但收入只高1.5倍,于是调整了定价策略——高分辨率任务收取溢价。

看板3:错误根因追踪
聚合animatediff_job_failure_reason标签,分类显示:OOM(显存溢出)、TIMEOUT(超时)、MODEL_LOAD_FAIL(模型加载失败)。上线后发现73%的失败源于motion module加载超时,针对性优化后失败率从8.7%降至0.9%。

看板4:资源成本看板
关联AWS Cost Explorer API,显示每生成1秒动画的GPU成本(美元)。这让我们能精确计算ROI,比如发现周末夜间生成成本比工作日低40%,于是引导客户把批量任务调度到非高峰时段。

5.3 日志集中管理:从海量日志中挖金矿

ANIMATEDIFF PRO默认日志分散在各节点,排查问题如同大海捞针。我们用Filebeat+Logstash+Elasticsearch构建了统一日志管道:

  • Filebeat监听/opt/animatediff-pro/webui.log,添加字段node_namegpu_id
  • Logstash过滤关键事件:ERRORCRITICALOut of memoryCUDA error
  • Elasticsearch按job_id聚合,还原完整任务生命周期

最实用的功能是“相似错误聚类”。当新出现CUDA error: device-side assert triggered,系统自动关联过去7天所有同类错误,显示:

  • 高发机型:RTX 4090(占比82%)
  • 高发参数:context_batch_size > 16(相关度94%)
  • 解决方案:自动建议将该参数降为12

这让我们把平均故障修复时间从42分钟缩短到6分钟。

6. 实战验证:压测结果与线上表现

6.1 压力测试设计:模拟真实业务场景

我们没用JMeter那种通用压测工具,而是开发了专用测试脚本,模拟三类真实用户:

  • 轻量用户:每分钟1次512x512、16帧动画生成(占流量65%)
  • 中量用户:每5分钟1次768x768、24帧动画(占流量25%)
  • 重量用户:每小时1次1024x1024、32帧动画(占流量10%)

测试持续72小时,期间注入三次故障:

  • 故意kill节点A的WebUI进程
  • 拔掉节点B的网线30秒
  • 在节点C上运行stress-ng --vm 4 --vm-bytes 20G制造内存压力

6.2 关键指标结果

指标单机部署三节点集群提升
平均请求延迟8.2s4.7s42.7% ↓
95%延迟22.1s11.3s48.9% ↓
错误率12.3%0.8%93.5% ↓
最大并发支撑42138228.6% ↑
故障恢复时间手动介入(>15min)自动(47s)

最值得骄傲的是错误率:集群将原本不可避免的OOM、CUDA错误等底层异常,全部转化为优雅的“排队中”提示,用户看到的是服务始终可用,而不是刺眼的500错误页。

6.3 线上6个月运行实录

自上线以来,集群累计处理动画任务217,843次,总生成视频时长1,842小时。关键运营数据:

  • 可用性:99.992%(全年宕机时间仅63分钟,全部为计划内维护)
  • 资源利用率:GPU平均利用率达68.3%,峰值82%,远高于行业平均的45%
  • 成本效益:相比单机方案,单位动画生成成本降低31%,主要来自负载均衡带来的资源复用

一个真实案例:某电商客户在双11前要求每天生成5000条商品短视频。单机方案需要24小时不间断运行,而集群在8小时内完成,且剩余算力还能承接其他客户任务。这让我们第一次体会到,高可用不仅是技术指标,更是商业竞争力。

7. 运维经验沉淀:那些文档里不会写的坑

7.1 Motion Module加载慢的终极解法

几乎所有教程都告诉你“下载motion module放对位置就行”,但没人提加载慢的问题。我们发现mm_sd_v15_v3.safetensors首次加载要42秒,用户等待体验极差。

解决方案是预热加载:在WebUI启动后,后台立即执行一次“空生成”:

# 添加到启动脚本末尾 nohup python3 launch.py --nowebui --skip-torch-cuda-test >> /dev/null 2>&1 & sleep 60 curl -X POST "http://localhost:7860/internal/ping" # 触发预热

更进一步,我们修改了animatediff插件源码,在extensions/sd-webui-animatediff/scripts/animatediff.py中加入:

# 在on_ui_tabs()函数中添加 if not hasattr(shared.opts, 'animatediff_preload'): shared.opts.animatediff_preload = True # 强制加载motion module到GPU load_motion_module("mm_sd_v15_v3.safetensors")

现在新节点上线后,首请求延迟从42秒降到1.3秒。

7.2 Ceph存储的ANIMATEDIFF PRO适配技巧

用Ceph做统一存储本意是好,但ANIMATEDIFF PRO的outputs目录频繁创建/删除小文件,导致Ceph OSD CPU飙升。我们通过两个配置解决:

# 在Ceph配置中(/etc/ceph/ceph.conf) [client] rados_mon_op_timeout = 30 rados_osd_op_timeout = 60 # ANIMATEDIFF PRO启动参数增加缓存 --gradio-queue --api --listen --port 7860 \ --disable-safe-unpickle \ --medvram-sdxl \ --xformers \ --enable-insecure-extension-access \ --theme dark \ --temp-dir /tmp/animatediff_temp # 本地临时目录,避免Ceph小文件

关键点:--temp-dir指向本地SSD,所有中间帧、缓存文件走本地,只有最终MP4/GIF才写入Ceph。这使Ceph负载下降89%。

7.3 版本升级的零停机策略

ANIMATEDIFF PRO更新频繁,但不能让用户感知到升级。我们的策略是:

  1. 新版本在备用节点部署并预热
  2. 修改Nginx upstream,将10%流量切到新节点(weight=1
  3. 监控新节点错误率、延迟,确认稳定后逐步提升权重
  4. 全量切流后,旧节点进入维护窗口,更新版本
  5. 所有节点版本一致后,恢复正常轮询

整个过程用户无感,最长单次升级耗时23分钟,比停机升级快5倍。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/24 16:04:54

EagleEye入门指南:如何评估毫秒级检测系统在真实产线的ROI

EagleEye入门指南&#xff1a;如何评估毫秒级检测系统在真实产线的ROI 1. 引言&#xff1a;当速度成为产线瓶颈 想象一下&#xff0c;你负责的是一条高速运转的包装产线。每分钟有上百个产品通过摄像头&#xff0c;你的任务是确保每个产品上的标签都贴得端正、印刷清晰。传统…

作者头像 李华
网站建设 2026/2/22 14:13:49

突破性3D渲染技术:GaussianSplats3D实现浏览器可视化革命

突破性3D渲染技术&#xff1a;GaussianSplats3D实现浏览器可视化革命 【免费下载链接】GaussianSplats3D Three.js-based implementation of 3D Gaussian splatting 项目地址: https://gitcode.com/gh_mirrors/ga/GaussianSplats3D GaussianSplats3D是基于Three.js的3D高…

作者头像 李华
网站建设 2026/2/19 0:31:59

YOLO X Layout效果实测:表格识别准确率惊人

YOLO X Layout效果实测&#xff1a;表格识别准确率惊人 文档智能处理的第一道关卡&#xff0c;从来不是OCR识别本身&#xff0c;而是“看懂”文档的结构——哪块是标题、哪块是正文、哪块是表格、哪块是图片。如果连版面都分不清&#xff0c;后续的文本提取、阅读顺序重建、信…

作者头像 李华
网站建设 2026/2/20 22:27:49

Auto-Photoshop-StableDiffusion-Plugin 全方位应用指南

Auto-Photoshop-StableDiffusion-Plugin 全方位应用指南 【免费下载链接】Auto-Photoshop-StableDiffusion-Plugin A user-friendly plug-in that makes it easy to generate stable diffusion images inside Photoshop using either Automatic or ComfyUI as a backend. 项目…

作者头像 李华
网站建设 2026/2/12 1:32:33

Qwen2-VL-2B-Instruct与Dify平台集成:快速构建AI应用

Qwen2-VL-2B-Instruct与Dify平台集成&#xff1a;快速构建AI应用 你是不是也遇到过这样的场景&#xff1a;手上有一个不错的视觉语言模型&#xff0c;比如Qwen2-VL-2B-Instruct&#xff0c;想把它变成一个能直接给同事或客户用的AI应用&#xff0c;但一想到要自己搭界面、写后…

作者头像 李华
网站建设 2026/2/25 0:43:31

无需代码!StructBERT情感分析Web界面使用指南

无需代码&#xff01;StructBERT情感分析Web界面使用指南 你是不是经常需要分析用户评论、监控社交媒体情绪&#xff0c;或者处理大量文本反馈&#xff1f;传统的情感分析方法要么需要写代码&#xff0c;要么准确率不高&#xff0c;让人头疼。今天我要介绍一个完全不需要编程基…

作者头像 李华