ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

云原生架构下AI能力集成:Chrome Skills在腾讯云的部署实践

云原生架构下AI能力集成:Chrome Skills在腾讯云的部署实践

1. 项目概述:当浏览器长出“AI大脑”

最近,我参与了一个挺有意思的项目,核心是把一个叫“Chrome Skills”的东西,部署到了腾讯云上。这名字听起来有点玄乎,简单说,它不是一个浏览器插件,而是一套能让浏览器本身变得更“聪明”的AI能力集。你可以把它想象成给Chrome浏览器装上了一颗“云原生”的AI大脑。过去,我们想在浏览器里实现一些智能功能,比如自动总结网页、实时翻译、智能填表,往往依赖于一个个独立的插件,它们各自为战,占用资源,还涉及隐私问题。而Chrome Skills的思路是,将这些通用的AI能力沉淀为浏览器底层可调用的标准化“技能”,通过云端统一的架构来提供支持。

这次实践的关键词是“云原生架构”。这意味着我们不是简单地把一个AI服务扔到云服务器上就完事了,而是充分利用了容器化、微服务、动态编排、服务网格这些云原生的核心思想和工具链,来构建一个高可用、弹性伸缩、易于维护的AI能力交付平台。选择腾讯云作为承载平台,一方面是看中其在国内完善的云产品生态和稳定的网络环境,另一方面也是想探索在公有云上实现这类前沿浏览器增强功能的最佳路径。整个过程涉及从本地原型到云端生产环境的完整链路,包括镜像构建、服务部署、网络打通、监控运维等一系列实操环节,其中踩过的坑和总结的经验,对于任何想将复杂应用云原生化落地的团队,都有不小的参考价值。

2. 核心架构设计与技术选型

2.1 为什么是云原生?传统架构的瓶颈

在项目初期,我们评估过几种方案。最直接的是单体应用部署,把所有AI模型和服务打包成一个大的应用,扔到一台云服务器上。这种方案简单粗暴,但问题很快暴露:资源利用率低(CPU/GPU负载不均衡)、难以扩展(一个功能卡住影响全部)、升级维护风险高(牵一发而动全身)。另一种是传统的虚拟机部署微服务,虽然解耦了服务,但在弹性伸缩、快速部署和统一运维上依然笨重。

云原生架构的优势在这里就凸显出来了。它的核心是以容器为交付单元,以微服务为架构模式,以动态编排为管理手段。对于Chrome Skills这种由多个独立AI技能(如OCR、NLP、语音识别)组成的系统,每个技能都可以作为一个独立的微服务进行开发、部署和伸缩。当用户大量使用翻译技能时,我们可以快速扩容翻译服务实例,而总结服务可以保持最小副本,资源按需分配,成本最优。

我们选择腾讯云,正是因为它提供了完整的云原生技术栈:容器服务TKE用于托管和编排我们的微服务;容器镜像服务TCR用于安全、高速地存储和分发Docker镜像;云监控和日志服务CLS用于洞察系统运行状态;再加上负载均衡CLB、私有网络VPC等,构成了一个生产就绪的底座。这避免了从零自建Kubernetes集群的运维复杂度,让我们能更专注于业务逻辑本身。

2.2 Chrome Skills的微服务拆分策略

Chrome Skills不是一个单一服务,而是一个技能集市。我们的拆分原则遵循“高内聚、低耦合”和“独立伸缩”。

  1. 技能网关服务:这是唯一的入口。它接收来自浏览器扩展(一个轻量级的客户端)的请求,根据请求中的技能标识(如skill:summarize),将请求路由到后面对应的具体技能微服务。它还负责统一的认证鉴权、限流熔断和请求日志记录。我们使用Go语言编写,看重其高并发性能和低资源占用。

  2. 具体技能微服务

    • 文本总结服务:基于Transformer模型(如BART、T5),接收长文本,输出摘要。该服务对CPU和内存要求较高,尤其在处理长文档时。
    • 实时翻译服务:集成腾讯云自己的机器翻译TMT API作为后端(考虑到效果和合规),自身主要做请求代理、格式转换和缓存。这个服务网络I/O密集。
    • 智能划词服务:结合NLP实体识别和知识图谱,对用户选中的文本提供解释、相关链接等。计算量相对较小,但要求低延迟。
    • OCR识别服务:处理浏览器内截图或上传图片的文字识别。需要GPU支持以获得更快的速度,我们使用了腾讯云TKE的GPU节点池。
  3. 公共支撑服务

    • 模型管理服务:负责AI模型的版本管理、热加载和A/B测试。当文本总结模型有更新时,通过此服务平滑切换到新版本,无需重启服务。
    • 用户配置与状态服务:存储用户的技能偏好设置、使用历史等。采用腾讯云数据库TDSQL(MySQL版),利用其高可用特性。
    • 异步任务队列:对于一些耗时的技能(如处理超长视频的语音转文字),请求会被放入消息队列(腾讯云CMQ),由后台工作进程异步处理,再通过WebSocket通知前端。

每个服务都打包成独立的Docker镜像,通过GitLab CI/CD流水线自动构建并推送至腾讯云容器镜像服务TCR。

2.3 腾讯云产品矩阵的精准选用

在腾讯云上,我们像搭积木一样选用服务,核心原则是“托管服务优先,自建次之”。

  • 计算与编排:TKE + 节点池:使用腾讯云容器服务TKE托管Kubernetes集群。我们创建了多个节点池:一个“常规CPU池”运行网关、配置等服务;一个“高CPU池”给文本总结服务;一个“GPU池”(配备NVIDIA T4卡)专供OCR和图像类AI服务。TKE的自动伸缩功能可以根据CPU/GPU利用率动态调整节点数量,完美应对流量波动。
  • 镜像与交付:TCR:将Docker镜像存放在腾讯云容器镜像服务TCR的私有命名空间内。TCR与TKE同地域内网访问,拉取镜像速度极快,且支持安全扫描和镜像同步,保障了交付链的安全与高效。
  • 网络与暴露:VPC + CLB + Ingress:所有资源部署在同一私有网络VPC内,确保内网通信安全高速。对外,我们使用腾讯云负载均衡CLB(四层)暴露TKE集群的入口。在集群内部,使用Nginx Ingress Controller(七层)作为技能网关服务的流量入口,实现基于路径(如/api/skill/summarize)的路由和SSL终止。
  • 存储与数据:TDSQL + COS:用户结构化数据(配置、元数据)存入TDSQL for MySQL。用户上传的待处理图片、音频等临时文件,则存储到腾讯云对象存储COS,并通过预签名URL让技能服务安全访问,避免大文件穿透业务服务。
  • 可观测性:CLS + 云监控:所有服务的应用日志统一采集到腾讯云日志服务CLS,便于故障排查和审计。业务指标(如请求量、延迟、错误率)通过Prometheus采集,并在腾讯云监控上配置仪表盘和告警策略。

注意:成本优化考量:GPU节点成本高昂。我们通过给OCR服务配置HPA(水平Pod自动伸缩),并设置较低的副本数下限(如1个),在夜间低峰期自动缩容,白天高峰前提前扩容,有效控制了成本。同时,对于翻译这类调用外部API的服务,我们增加了本地缓存层(使用Redis),对相同内容短时间内的重复请求直接返回缓存结果,既降低了延迟,又节省了API调用费用。

3. 核心实现细节与部署实操

3.1 Docker镜像构建的最佳实践

镜像构建是云原生应用的起点。我们的目标是构建体积小、层数少、安全的镜像。

以文本总结服务(Python)为例,最初的Dockerfile简单粗暴地COPY . /app然后pip install -r requirements.txt。这会导致镜像巨大(超过2GB),且每次代码变更都会导致整个依赖层重建,构建缓慢。

优化后的Dockerfile采用多阶段构建:

# 第一阶段:构建依赖 FROM python:3.9-slim as builder WORKDIR /app COPY requirements.txt . RUN pip install --user --no-cache-dir -r requirements.txt # 第二阶段:运行环境 FROM python:3.9-slim WORKDIR /app # 从builder阶段拷贝已安装的Python包 COPY --from=builder /root/.local /root/.local # 确保pip安装的包在路径中 ENV PATH=/root/.local/bin:$PATH # 拷贝应用代码 COPY . . # 创建非root用户运行,增强安全 RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app USER appuser EXPOSE 8080 CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:8080", "app:app"]

这样,最终的镜像只包含运行所需的Python解释器、依赖包和我们的代码,体积缩小了60%以上。requirements.txt文件被精确管理,只包含生产环境必需的包。

实操心得:.dockerignore文件至关重要。一定要创建.dockerignore文件,排除.git,__pycache__,*.log,Dockerfile,README.md等无关文件。这能加速构建过程,并避免敏感信息(如本地配置文件)意外打入镜像。

3.2 Kubernetes资源配置清单详解

将服务部署到TKE,需要编写Kubernetes的YAML清单。我们以技能网关服务为例,展示一个生产可用的Deployment和Service配置。

deployment.yaml:

apiVersion: apps/v1 kind: Deployment metadata: name: skills-gateway namespace: production labels: app: skills-gateway spec: replicas: 3 # 初始副本数,结合HPA动态调整 selector: matchLabels: app: skills-gateway template: metadata: labels: app: skills-gateway spec: containers: - name: gateway image: ccr.ccs.tencentyun.com/my-namespace/skills-gateway:v1.2.0 # TCR镜像地址 ports: - containerPort: 8080 resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" cpu: "500m" livenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /readyz port: 8080 initialDelaySeconds: 5 periodSeconds: 5 env: - name: REDIS_ADDR valueFrom: configMapKeyRef: name: app-config key: redis.address - name: LOG_LEVEL value: "info" volumeMounts: - name: config-volume mountPath: /app/config volumes: - name: config-volume configMap: name: gateway-config

service.yaml:

apiVersion: v1 kind: Service metadata: name: skills-gateway-svc namespace: production spec: selector: app: skills-gateway ports: - port: 80 # Service对外端口 targetPort: 8080 # 容器端口 protocol: TCP type: ClusterIP # 内部服务发现,由Ingress对外暴露

关键点解析

  1. 资源请求与限制requests是调度依据,limits是硬性上限。合理设置能提高集群资源利用率,防止单个Pod“饿死”邻居或“撑爆”节点。
  2. 健康检查livenessProbe失败会重启Pod;readinessProbe失败会将Pod从Service的负载均衡端点中移除。这是实现服务自愈和零停机部署的关键。
  3. 配置分离:将Redis地址等配置通过ConfigMap注入,而非写死在代码或镜像中,便于不同环境(开发、测试、生产)的切换。
  4. 镜像标签:使用明确的版本号(v1.2.0),而非latest,确保每次部署版本可控,便于回滚。

3.3 Ingress与域名配置实战

为了让外部用户能通过域名访问我们的服务,我们在TKE集群中部署了Nginx Ingress Controller,并配置了Ingress规则。

首先,在腾讯云TKE控制台的应用市场中,一键部署“Nginx Ingress Controller”。它会自动创建一个公网CLB,并将CLB的VIP(虚拟IP)作为入口。

然后,创建Ingress资源定义ingress.yaml

apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: skills-ingress namespace: production annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/rewrite-target: /$2 nginx.ingress.kubernetes.io/proxy-body-size: "20m" # 允许上传大文件 spec: tls: - hosts: - skills-api.mycompany.com secretName: skills-tls-secret # 存放SSL证书的Secret rules: - host: skills-api.mycompany.com http: paths: - path: /api/skills(/|$)(.*) pathType: Prefix backend: service: name: skills-gateway-svc port: number: 80

这个配置意味着,所有发送到https://skills-api.mycompany.com/api/skills/...的请求,都会被转发到集群内的skills-gateway-svc服务。我们在腾讯云SSL证书控制台申请了免费证书,下载后通过kubectl create secret tls命令创建了skills-tls-secret

最后,将域名skills-api.mycompany.com的CNAME记录解析到Ingress Controller对应的CLB的VIP地址。至此,公网用户就可以通过HTTPS安全地访问我们的Chrome Skills API了。

4. 持续集成与持续部署流水线

自动化是云原生实践的灵魂。我们基于GitLab CI/CD构建了从代码提交到生产环境部署的全自动流水线。

.gitlab-ci.yml核心阶段如下:

stages: - test - build - push - deploy-staging - deploy-production variables: IMAGE_TAG: $CI_COMMIT_SHORT_SHA # 使用提交哈希作为镜像标签 # 1. 测试阶段 unit-test: stage: test image: python:3.9-slim script: - pip install -r requirements.txt - pytest tests/ --cov=app --cov-report=xml artifacts: reports: coverage_report: coverage_format: cobertura path: coverage.xml # 2. 构建Docker镜像 build-image: stage: build image: docker:20.10 services: - docker:20.10-dind script: - docker build -t $CI_REGISTRY_IMAGE:$IMAGE_TAG . - docker build -t $CI_REGISTRY_IMAGE:latest . # 同时打latest标签,用于开发环境 only: - main - develop # 3. 推送镜像到腾讯云TCR push-image: stage: push image: docker:20.10 services: - docker:20.10-dind script: - echo $TENCENT_REGISTRY_PASSWORD | docker login ccr.ccs.tencentyun.com --username $TENCENT_REGISTRY_USERNAME --password-stdin - docker push $CI_REGISTRY_IMAGE:$IMAGE_TAG - docker push $CI_REGISTRY_IMAGE:latest only: - main - develop # 4. 部署到预发布环境 deploy-staging: stage: deploy-staging image: bitnami/kubectl:latest script: - kubectl config use-context tke-staging-cluster - kubectl set image deployment/skills-gateway gateway=$CI_REGISTRY_IMAGE:$IMAGE_TAG -n staging - kubectl rollout status deployment/skills-gateway -n staging --timeout=120s environment: name: staging only: - develop # develop分支合并后自动部署到staging # 5. 手动触发部署生产环境 deploy-production: stage: deploy-production image: bitnami/kubectl:latest script: - kubectl config use-context tke-production-cluster - kubectl set image deployment/skills-gateway gateway=$CI_REGISTRY_IMAGE:$IMAGE_TAG -n production - kubectl rollout status deployment/skills-gateway -n production --timeout=180s environment: name: production when: manual # 生产环境部署需要手动点击触发 only: - main # 仅对main分支生效

流水线亮点与避坑点

  • 安全凭证管理:腾讯云TCR的登录密码、Kubernetes集群的kubeconfig文件,都以“变量”的形式存储在GitLab的CI/CD设置中,而非代码里。
  • 金丝雀发布:生产环境部署并非简单的set image。我们后来升级为更高级的策略,通过修改Deployment的YAML,采用RollingUpdate策略,并配置maxSurgemaxUnavailable来控制滚动更新的节奏,实现无缝升级。
  • 环境隔离:我们为 staging 和 production 环境配置了不同的Kubernetes上下文(context),在流水线中切换,确保操作隔离。

5. 监控、日志与问题排查实录

系统上线后,可观测性就成了生命线。我们主要从三个维度进行监控:基础设施、应用性能、业务指标。

5.1 基础设施监控

利用腾讯云监控,我们为TKE集群和节点配置了基础告警:

  • 节点CPU/内存使用率> 80% 持续5分钟。
  • 节点磁盘使用率> 85%。
  • Pod异常重启(频繁重启可能意味着应用有bug或内存不足)。

5.2 应用性能监控

我们在每个技能服务的代码中集成了Prometheus客户端库(如Python的prometheus_client),暴露了如下关键指标:

  • http_request_duration_seconds:请求耗时直方图,用于计算P50, P95, P99延迟。
  • http_requests_total:请求总数,按状态码分类。
  • skill_processing_duration_seconds:具体AI技能的处理耗时。
  • external_api_call_duration:调用腾讯云TMT等外部API的耗时。

这些指标被集群内部署的Prometheus Server抓取,并通过Grafana展示。我们设置了一个核心告警:P95延迟超过500ms持续2分钟,这往往意味着服务可能正在排队或遇到性能瓶颈。

5.3 集中式日志收集

所有服务都将日志输出到标准输出(stdout)和标准错误(stderr)。TKE的日志采集组件会自动收集这些日志,并发送到腾讯云日志服务CLS。

在CLS中,我们为不同服务创建了不同的日志主题,并设置了索引。当用户反馈“翻译失败”时,我们可以:

  1. 在CLS控制台选择“翻译服务”日志主题。
  2. 搜索关键词ERROR或失败请求的request_id
  3. 通过上下文查看完整的错误堆栈和当时的请求参数,快速定位是网络超时、API密钥失效还是输入内容异常。

5.4 典型问题排查案例

案例一:深夜CPU使用率飙升告警

  • 现象:凌晨2点,收到“文本总结服务CPU使用率超过90%”的告警。
  • 排查
    1. 登录Grafana,查看该服务的QPS(每秒查询率)图表,发现请求量并未增加。
    2. 查看该服务Pod的日志(CLS),发现大量Out of Memory错误前的GC(垃圾回收)日志。
    3. 检查部署配置,发现该服务Pod的内存limit设置为1GB,但request只有256MB。Kubernetes调度时只保证request,该节点可能内存已紧张。
    4. 进一步检查,发现同一个节点上被调度了一个新部署的、内存消耗大的批处理任务Pod。
  • 根因与解决:根本原因是节点内存资源竞争,导致我们的服务因内存不足而被系统频繁终止和重启(OOMKilled),重启过程消耗大量CPU。解决方案有两个:一是调整该服务的memory request到512MB,使其调度到更宽松的节点;二是为不同优先级的服务配置不同的节点池或使用Kubernetes的priorityClass
  • 经验固化:此后我们规定,所有服务的requestlimit必须经过压测后谨慎设置,且两者比值不宜过大(通常limit不超过request的2倍)。

案例二:特定用户翻译请求超时

  • 现象:个别用户反馈翻译功能经常超时,但其他用户正常。
  • 排查
    1. 在CLS中,用该用户的ID过滤翻译服务日志,发现其请求的目标语言多为“藏语”等小语种。
    2. 检查翻译服务的代码和配置,发现我们调用的腾讯云TMT API,对于小语种是异步处理的,默认超时时间设置较短(5秒),而异步处理可能超过这个时间。
    3. 查看服务监控,发现调用TMT小语种接口的P99延迟高达8秒。
  • 解决:调整翻译服务中调用TMT异步接口的超时时间至15秒,并在客户端(浏览器扩展)侧对这类可能耗时的操作增加“处理中”的友好提示,避免用户误认为失败。
  • 更深层优化:我们为小语种翻译增加了本地缓存,并将用户频繁翻译的句子(即使语种不同)也纳入缓存策略,进一步降低对API的依赖和延迟。

6. 安全与成本治理实践

6.1 安全加固措施

  1. 镜像安全:在CI流水线中集成镜像安全扫描工具(如Trivy),扫描Docker镜像中的已知漏洞,只有扫描通过的镜像才能被推送到TCR。
  2. 网络策略:在Kubernetes中启用并配置NetworkPolicy,实现微服务间的网络隔离。例如,只允许技能网关服务访问具体的技能服务,技能服务之间默认不能互相访问。
  3. 密钥管理:腾讯云TMT API的密钥等敏感信息,使用腾讯云“密钥管理系统SSM”来存储和管理,在Pod启动时通过环境变量注入,而非写在配置文件中。
  4. API安全:技能网关对所有入站请求进行JWT令牌验证,并实施基于令牌的速率限制,防止API滥用。

6.2 成本控制与优化

云原生虽好,但成本可能失控。我们建立了以下机制:

  1. 资源配额与限制:在Kubernetes命名空间级别设置ResourceQuota,限制整个Chrome Skills项目可使用的总CPU、内存量,防止资源无限扩张。
  2. HPA与弹性伸缩:为所有无状态服务配置了基于CPU/内存利用率的HPA。但需要谨慎设置阈值,避免因瞬间流量毛刺导致集群过度扩容。我们通常将扩容阈值设在70%,缩容阈值设在30%,并设置稳定窗口时间。
  3. GPU资源池化与共享:GPU节点成本极高。我们探索了使用NVIDIA MIG技术将一块物理GPU切分给多个Pod使用,或者使用基于时间的GPU调度策略,让非关键任务在夜间低谷期运行。
  4. 定期资源审计:每月使用腾讯云的成本分析工具,查看TKE集群、COS存储、公网流量等各项费用的明细。我们发现日志存储(CLS)费用增长较快,于是调整了日志的保存周期(从永久改为30天),并对不重要的DEBUG级别日志进行采样收集,费用立减40%。

将Chrome Skills这套浏览器AI能力以云原生架构部署在腾讯云上,是一次从技术理念到工程实践的完整闭环。它不仅仅是“上云”,更是通过容器化、微服务、动态编排和丰富的云服务,构建了一个弹性、可靠、可观测、可持续进化的现代化应用平台。过程中最大的体会是,云原生带来的不仅是部署方式的改变,更是团队协作、运维理念和成本意识的全面升级。每一个YAML文件、每一条监控告警、每一次流水线执行,都是这个系统稳健运行的基石。对于后来者,我的建议是:从小处着手,定义一个清晰的服务边界,重视可观测性建设,并始终将安全和成本纳入设计和运维的每一个环节。这条路没有银弹,但每一步扎实的实践,都会让系统更强大,也让团队更从容。

返回列表