你购买了test.dev 需要跳转到 test.com,在godaddy上仅需配置转发,http(s)://test.dev 都可正常跳转。在国内云仅支持http://test.dev→https://test.com,https://test.dev不支持

购买差异

指标GoDaddy国内厂商
新顶级域支持实时开放注册(.dev/.app/.io等)暂不支持
备案要求有(法规要求),未备案部分解析功能受限

URL转发机制差异

特性GoDaddy国内云
协议支持同时支持HTTP HTTPS仅支持HTTP明文跳转
证书管理自动续签(ACME协议集成)需手动上传第三方证书

协议测试

# GoDaddy HTTPS重定向验证
curl -v https://test.dev

输出字段可以看到自动帮你加了godaddy颁发证书

  • SSL connection using TLSv1.3 / AEAD-AES128-GCM-SHA256 / [blank] / UNDEF
  • ALPN: server accepted http/1.1
  • Server certificate:
  • subject: CN=test.dev
  • start date: Mar 14 09:34:11 2025 GMT
  • expire date: Mar 14 09:34:11 2026 GMT
  • subjectAltName: host "test.dev" matched cert's "test.dev"
  • issuer: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=http://certs.godaddy.com/repository/; CN=Go Daddy Secure Certificate Authority - G2

结论

在deepseek-r1:32b较大尺寸模型下,4090单卡可提供3QPS,单问题4.4秒内完成响应。 对于个人,几十人小团队够用。

优点:

  • 本地模型问题过滤少,同样问题,官方无法回答,本地可以
  • 速度尚可,不会服务器繁忙
  • ollama动态显存占用,5分钟不问,默认不占用显卡,不影响游戏:)

缺陷:

  • 无搜索、图片识别功能,当然这也不是模型的问题,要借助flowise这种langchain编排工具实现
  • 有一定硬件要求,单卡显存越大越好,推荐3090/4090

no-answer.png

  • 低至中等并发:单卡4090在并发数从10到400时,系统表现稳定,吞吐量和响应时间均在可接受范围内。2.9QPS
  • 高并发情况:单卡在并发数为800时,吞吐量显著增加,但响应时间波动较大,且最大响应时间大幅上升,可能存在性能瓶颈。
  • 系统稳定性:系统在高并发压力下依然能保证请求的成功率,但响应时间波动可能影响整体用户体验

测试环境

  • 服务器硬件配置

    • CPU:AMD Ryzen Threadripper PRO 5975WX 32-Cores
    • GPU:1 x NVIDIA RTX 4090
    • MEM:128G
  • 网络:本机
  • 测试工具:Apache Benchmark (ab)
  • 模型:deepseek-r1:32b
  • 压测命令
ab -n 1000 -c 10 -s 30000 -T "application/json" -p payload.json -v 4 http://1.1.1.1:11434/v1/completions > ab_detailed_log01.txt 2>&1
- **请求总数**:1000

- **并发数**:逐渐升高

- **超时设置**:30秒(`-s 30000`)

- **请求类型**:POST,传送JSON格式的负载
 {
  "model": "deepseek-r1:32b",
  "prompt": "你好,你是谁?"
}

load-test-image.png

测试数据分析

并发数总请求时间(秒)成功请求数失败请求数吞吐量 (请求/秒)平均响应时间 (毫秒)最大响应时间 (毫秒)95% 响应时间 (毫秒)
10344.899100002.903448.9970734424
50341.55100002.9317077.4942027418333
100343.880100002.9134387.9773952335580
150337.687100002.9650653.0325313451942
200340.978100002.9368195.5087073369537
400351.865100002.84140746.048141672139774
800250.2617162844200208.529249642231555

背景

本地部署DeepSeek-Coder-V2-Lite-Instruct:14b。要求基础的高可用、监控、安全能力。ollama默认只能使用第一张显卡,多个模型同时调用会有bug(ollama ps显示100GPU,但使用CPU推理);无法高可用

具体方案

多GPU Ollama部署方案,通过系统服务化+负载均衡实现4块4090显卡的并行利用,边缘使用nginx负载均衡。

  • 服务器名:AIGC-01
  • 服务器硬件配置

    • CPU:AMD Ryzen Threadripper PRO 3955WX 16-Cores
    • GPU:4 x NVIDIA RTX 4090
    • MEM:128G
  • 模型:DeepSeek-Coder-V2-Lite-Instruct:14b

ollama配置

# 备份ollama
cd /etc/systemd/system/
mv ollama.service ollama.service.bak

# 创建4个独立服务文件(每个GPU对应一个端口)
for i in {0..3}; do
sudo tee /etc/systemd/system/ollama-gpu${i}.service > /dev/null <<EOF
[Unit]
Description=Ollama Service (GPU $i)

[Service]
# 关键参数配置
Environment="CUDA_VISIBLE_DEVICES=$i"
Environment="OLLAMA_HOST=0.0.0.0:$((11434+i))"
ExecStart=/usr/local/bin/ollama serve

Restart=always
User=ollama
Group=ollama

[Install]
WantedBy=multi-user.target
EOF
done


# 重载服务配置
sudo systemctl daemon-reload

# 启动所有GPU实例
sudo systemctl start ollama-gpu{0..3}.service

# 设置开机自启
sudo systemctl enable ollama-gpu{0..3}.service

nginx配置

nginx 需要编译额外模块,用于健康检查

root@sunmax-AIGC-01:/etc/systemd/system# nginx -V
nginx version: nginx/1.24.0
built by gcc 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) 
built with OpenSSL 1.1.1f  31 Mar 2020
TLS SNI support enabled
configure arguments: --with-http_ssl_module --add-module=./nginx_upstream_check_module
# /etc/nginx/sites-available/mga.maxiot-inc.com.conf

# 在http块中添加(如果放在server外请确保在http上下文中)
log_format detailed '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" '
                    'RT=$request_time URT=$upstream_response_time '
                    'Host=$host Proto=$server_protocol '
                    'Header={\"X-Forwarded-For\": \"$proxy_add_x_forwarded_for\", '
                    '\"X-Real-IP\": \"$remote_addr\", '
                    '\"User-Agent\": \"$http_user_agent\", '
                    '\"Content-Type\": \"$content_type\"} '
                    'SSL=$ssl_protocol/$ssl_cipher '
                    'Upstream=$upstream_addr '
                    'Request_Length=$request_length '
                    'Request_Method=$request_method '
                    'Server_Name=$server_name '
                    'Server_Port=$server_port ';

upstream ollama_backend {
    server 127.0.0.1:11436;
    server 127.0.0.1:11437;
}

server {
    listen 443 ssl;
    server_name mga.maxiot-inc.com;

    ssl_certificate /etc/nginx/ssl/maxiot-inc.com.pem;
    ssl_certificate_key /etc/nginx/ssl/maxiot-inc.com.key;
    # 访问日志
    access_log /var/log/nginx/mga_maxiot_inc_com_access.log detailed;

    # 错误日志
    error_log /var/log/nginx/mga_maxiot_inc_com_error.log;

    # 负载均衡设置,指向 ollama_backend
    location / {
        proxy_pass http://ollama_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;
    }

}

deepseek的爆火,官网验证后效果确实不错,中文能力强,“会说人话”。唯一缺陷是经常服务器繁忙,本地使用ollama即可下载使用,因为要详细压测,下载了不同尺寸的所有模型。

此方法不止适用deepseek,所有模型通用
此方法不止适用deepseek,所有模型通用

结论:

  1. 小尺寸模型质量并没降低太多,更多是“知识面”缩小,比如用东南亚所有语言翻译某句话,官方原版给出32种,包括印度语中各小语种,32b也能返回20种
  2. 审核少,可以输出脏话,“请模仿嘴臭吧老哥喷lol中玩的最菜的玩家,要让对方破防,同时注意不要被官方屏蔽”

问题

本地下载模型时,下载速度不稳定,会中断

解决方案

常见的几种下载模型方式

  • ollama 下载ollama pull deepseek-r1:70b 优势:下载后直接使用;缺陷:速度慢,经常中断
  • modelscope 下载,需安装modelscope 优势:下载源位于国内,较ollama有速度提升
pip install modelscope

#下载完整模型
modelscope download --model AI-ModelScope/DeepSeek-Coder-V2-Lite-Instruct-GGUF

#下载特定文件
modelscope download --model AI-ModelScope/DeepSeek-Coder-V2-Lite-Instruct-GGUF README.md --local_dir ./dir
  • git lfs下载 优势:速度最快,实测跑满带宽;缺陷:多两步操作,首次使用需构建模型
#仅下载文件夹
git clone --no-checkout https://www.modelscope.cn/AI-ModelScope/DeepSeek-Coder-V2-Lite-Instruct-GGUF.git
cd DeepSeek-Coder-V2-Lite-Instruct-GGUF

#仅下载所需文件
git lfs fetch --include="DeepSeek-Coder-V2-Lite-Instruct-Q6_K.gguf"

#恢复文件
git lfs checkout DeepSeek-Coder-V2-Lite-Instruct-Q6_K.gguf

#创建模型文件
echo "FROM DeepSeek-Coder-V2-Lite-Instruct-GGUF" > Modelfile

#创建模型
ollama create DeepSeek-Coder-V2-Lite-Instruct:14b -f Modelfile

#使用
ollama run DeepSeek-Coder-V2-Lite-Instruct:14b

由多个agent组成的SRE专家组,代替人工进行准确的故障分析!👽

流程:从用户输入取时间范围(支持上传图片)、路由--》查询日志中心--》获取网关中cmdb信息--》查询CMDB获取更多细节(owner、变更、jenkins、gitlab信息)--》分析并给出建议:

111.jpg

222.jpg

执行效果:

图中是判断某接口504故障,从依据到结论过程
333.jpg

444.jpg

555.jpg

步骤

使用flowise,配置langchain中AgentFlow

创建supervisor

- 阅读剩余部分 -

interview-blog-21-0702.png
近期借一位业内朋友推荐,面试了一家位于新加坡的互联网企业,同样记录面试过程
一面(远程):
业务线运维负责人,是一位年轻女士,在问明不需要露脸后开始。从自我介绍到了解的技术栈,擅长的方向,排错问题等。问到“擅长的方向”时,忽然一愣,眼瞅也是17年的老运维人了,但还真没觉得擅长什么。只能说阶段性的尝试过一些新技术,23年至今,甚至有点不务正业,可以不负责任的说,“运维里最了解大模型的,大模型里最了解运维”的复合型人才:) 接触越多也愈发觉得知之甚少,这也是我在简历中不敢用“精通”二字。收回来,讲了几个模型应用的实际案例

  • 微信聊天记录微调chatGLM
  • Voice2SQL
  • 智能运维机器人

23年以前,容器、网格、网关的落地、使用过程,举了几个排错。提到当前基础设施情况,使用了terraform,交流了优势和建议做法,terraform结合ansible快速拉起。在容器编排有更好的解法Cluster Autoscaler叠加Horizontal Pod Autoscaler。面试官最后礼貌的问了薪资,并贴心的补充可以不回答,基于信任,如实告知,一面结束,面试官准时,用时45分钟

二面(远程):
跨团队面试,一位男士,可能负责研发,同样的过程,自我介绍到过往经历。分享了几个经典、复杂的排错案例,也都是博客的历史文章。着重问了CDN厂商的从业经历,简历外有无其他经验,以往离开的原因等。二面结束,面试官因为凌晨处理故障到5点,迟到半小时,表示理解,实际用时49分钟

- 阅读剩余部分 -

Software_Architect.png
多年的运维感悟,什么阶段干什么事。这也是我在内部的运维规范里明确标明,“不提前优化”

我来谈谈几个阶段,

初创阶段

部分参考 原文链接:https://mp.weixin.qq.com/s/vVhLZDL6bRJL9u5GJg63tw

  • 初创阶段,更多关注业务最小模型能否跑通

    • 快速实现
    • 熟悉什么技术栈,就用什么
    • allinone
    • 引入ORM、DAO屏蔽sql复杂性
    • 早期不自研
    • 规模扩大的时候,要浅浅的封装一层,防止日后技术栈更新,控制数量。我称之为“有中台作用,但无中台负重”
    • 只有在开源社区无法满足时,再造轮子
  • 需要容量评估的场景

    • 新系统上线
    • 临时活动、大促、秒杀类
    • 系统容量有质变性增长
  • 创业初期最贵的是时间成本,这个阶段用钱堆资源的方式可以快速解决问题,不贸然重构
  • 有些明显的规则要遵守,比如

    • 不能硬编码IP,使用域名
    • 域名见名知意,区分内外,比如baidu.com / baidu-inc.com
    • 区分生产环境
    • 避免账号公用

步入正轨阶段

  • 这时候就要拆分了,上面提到的allinone可能已经有了性能、容量等压力。此时就要垂直拆分了

    • 核心是基于业务的拆分

      • 代码
      • 数据库、中间件
      • 团队垂直拆分
  • 这时候我们要引入反向代理,最常见的如nginx,我的建议是用更加贴近业务的api网关,比如kong、apisix、openrestry等等,有更多原生功能。如果nginx比作汽车引擎,后者可以比作宝马、奔驰汽车,多了很多配置外,还能开车即用,开箱即用

    • 对应反向代理层也需要高可用,好消息是都是必备能力
  • 服务也要拆分,其中关键的是,尽可能无状态,“状态”尽可能让中间件,redis、mysql、共享存储等手段解决,确保服务动态、快速伸缩

- 阅读剩余部分 -

目标

创建一个具备内部运维知识,识别自然语义,准确调用各种工具执行任务,严格控制幻觉的智能运维工程师。

v0.1 技术方案

方案介绍

使用 OpenAI 的 Assistant 功能,上传知识库,设置提示词。

  • 优势:效果不错,配置简单
  • 劣势:无审计,无法限定回答范围
  • 技术栈:JavaScript/Flowise / Prompt Engineering / OpenAI Assistant

核心内容

Prompt Engineering:

Function Call:通过 Flowise 的自定义工具

v0.1 技术架构

架构图

架构图v1.png

- 阅读剩余部分 -

先看效果

系统架构组件

  1. Streamlit 界面

    • 侧边栏和输入区域:提供用户界面,用于输入数据(如 Azure 端点)并进行配置。
    • 聊天输入和输出区域:主要区域,用户在此与聊天助手交互并查看结果。
  2. LLM(大型语言模型)配置设置

    • OpenAI 配置:配置用于使用 OpenAI 模型(如 gpt-4o-2024-08-06)。
    • 本地 LLM 配置:本地 LLM 模型(如 ollama/llama3:latest)的配置。
  3. 助手代理(AssistantAgent)和用户代理(UserProxyAgent)

    • TrackableAssistantAgent:继承自 AssistantAgent,负责与用户输入进行处理和响应,同时集成在 Streamlit 中以显示聊天消息。
    • TrackableUserProxyAgent:继承自 UserProxyAgent,用于接收用户输入,处理用户命令,并在助手代理与用户之间进行代理交互。
  4. 实用工具函数

    • get_url_info_from_kong:从 Kong API 网关中查询 URL 的路由、服务和上游配置的信息,并返回格式化结果。
    • dns_record_status:检查给定 URL 的 DNS 记录状态。
    • query_from_cmdb:从 CMDB(配置管理数据库)中检索特定云服务提供商(如阿里云、AWS 等)的服务器、数据库和中间件实例的数量。
  5. 异步聊天系统

    • 使用异步事件循环(asyncio),用户代理(User Proxy Agent)可以异步与助手代理(Assistant Agent)进行对话,提供更高效的交互体验。

架构图

+---------------------------------------------------------------+
|                      Streamlit Interface                      |
|---------------------------------------------------------------|
| +-----------------------------------------------------------+ |
| |  Sidebar (Azure Endpoint Config, etc.)                    | |
| +-----------------------------------------------------------+ |
|                                                               |
| +-----------------------------------------------------------+ |
| |                  Chat Input / Output Area                 | |
| |                                                           | |
| |  User Input --> UserProxyAgent --> AssistantAgent         | |
| |                                                           | |
| |  AssistantAgent --> UserProxyAgent --> Output Display     | |
| +-----------------------------------------------------------+ |
+---------------------------------------------------------------+

+--------------------+               +--------------------+
| LLM Configurations |               |   Utility Functions|
|--------------------|               |--------------------|
| - OpenAI (GPT-4)   |               | - get_url_info_from|
| - Local LLM (LLaMA)|               |   _kong()          |
+--------------------+               |   (Interacts with  |
                                     |    Kong API Gateway)|
                                     | - dns_record_status|
                                     |   (Checks DNS)     |
                                     | - query_from_cmdb  |
                                     |   (Interacts with  |
                                     |    CMDB Database)  |
                                     +--------------------+

   +-----------------+               +-------------------+
   | AssistantAgent  | <--- asyncio ->| UserProxyAgent    |
   | (Handles LLM    |               | (Manages User     |
   |  Requests)      |               |  Input/Commands)  |
   +-----------------+               +-------------------+
        ^    |                              ^    |
        |    |                              |    |
        |    v                              |    v
+----------------+                     +-------------------+
|   LLM Config   |                     |  Utility Functions|
|  Setup (OpenAI)|                     | (Kong, DNS, CMDB) |
+----------------+                     +-------------------+

                     +----------------+
                     |   Data Flow    |
                     |----------------|
                     |  - User Input  |
                     |  - Assistant   |
                     |  - ProxyAgent  |
                     |  - Utility Func|
                     +----------------+

架构图描述

  1. 用户输入(通过 Streamlit)
    用户通过 Streamlit 界面输入聊天内容或命令。
  2. 助手代理和用户代理交互
    用户代理接收用户输入,解析并处理命令,然后与助手代理交互。助手代理根据注册的工具函数或LLM配置进行响应。
  3. 工具函数交互
    当助手代理或用户代理调用工具函数时,这些函数将与 Kong API 网关、DNS 解析服务或 CMDB 模拟数据进行交互。
  4. 结果显示
    通过 Streamlit 界面将助手代理和用户代理的响应结果显示给用户。

核心优势

  1. 超越简单的 RAG 和提示词工程

    • 传统的 RAG 方法主要依赖于检索和生成的结合,通过从知识库中检索相关信息并用语言模型生成答案。然而,这种方法局限于信息查询和简单的问答系统,无法处理更复杂的任务。
    • 提示词工程则是通过精细设计提示词来引导语言模型生成特定输出,依然依赖于语言模型本身的生成能力,不能主动与外部系统进行交互或执行特定操作。
  2. 使用 Function Call 完成真实世界的任务

    • 本系统通过引入 Function Call 技术,赋予助手代理(Assistant Agent)和用户代理(User Proxy Agent)调用实际功能的能力。这些功能可以执行复杂的任务,如查询 Kong API 网关中的服务配置、检查 DNS 记录状态、从 CMDB 检索云资源信息等。
    • 通过注册和调用实际的 Python 函数,系统能够与外部 API、数据库和服务进行交互,执行逻辑操作和数据处理。这种能力使得系统不仅限于简单的对话和问答,更能够执行真实世界中的操作任务。
  3. 集成异步交互和高效任务处理

    • 使用异步框架(如 asyncio)实现用户代理和助手代理之间的异步通信,大幅提升了任务处理的效率和响应速度。这样的设计确保了系统能够并发处理多个任务,而不阻塞用户输入和系统响应。
    • 异步处理机制也增强了系统的稳定性和扩展性,使其能够处理更大规模的请求和更复杂的任务逻辑。
  4. 技术含量高,解决复杂场景问题

    • 系统架构充分考虑了实际应用场景中的复杂性,通过模块化设计,支持各种工具函数的集成和扩展,能够适应不同的企业和业务需求。
    • 例如,get_url_info_from_kong 函数能够通过调用 Kong API,获取详细的路由、服务和插件信息,并对这些数据进行格式化处理和展示;query_from_cmdb 函数能够从 CMDB 中动态检索并整合不同云服务商的资源信息。这样的功能大大提升了系统的实际应用价值。
  5. 提升企业运营效率与智能化水平

    • 通过整合各种实用功能和自动化操作,系统能够显著提升企业运维和运营效率。例如,它可以自动查询和管理 API 网关配置、检查网络 DNS 状态、整合和分析云资源数据,帮助企业做出更高效的决策和管理。

最近在整理CMDB信息,以Jenkins为中枢,统计、梳理代码仓库位置、发布位置。形成以应用为中心,串连资源、管理者。
首先需要统计代码中涉及的配置文件信息,比如Mysql/Redis/Elasticsearch/MongoDB/Kafka/RocketMQ/MQTT/Doris/HBase/InfLuxDB/http等
意义:

  • 排错时参考,比如该服务报504错误,马上定位到具体的中间件或者外部接口
  • 不遵守配置规范,不用配置中心硬编码在代码中的情况,能被发现
  • 资源收拢,当所有代码中都未出现的资源可作为下架依据

相较传统的正则匹配,大模型加持下有如下优点

  • 大模型能够识别到更多的配置,正则更依赖规则,对于语言多、规范复杂、执行不严有优势
  • 大模型能够用简单的提示词,格式化、筛选输出

环境介绍

  • 效果展示,使用了内部CMDB项目代码,使用了Python的Django框架,代码大小5M。项目中的配置相对分散。分析过程30秒。

效果.jpg

  • 代码、配置资产属于机密信息,故使用近期评分较高的本地模型确保安全性,Meta-Llama-3.1-8B-Instruct/Qwen2-7B-Instruct,使用vllm部署
#!/bin/bash
  
# 设置环境变量
export CUDA_VISIBLE_DEVICES=0,1

# 启动 vllm 服务器并将其转移到后台运行
nohup python3 -m vllm.entrypoints.openai.api_server \
    --model /data/vllm/Meta-Llama-3.1-8B-Instruct \
    --served-model-name llama \
    --tensor-parallel-size 2 \
    --trust-remote-code > llama.log 2>&1 &
  • 逻辑如下,通过多个模型分别判断,取并集后再利用模型整合

20240812163027.jpg

import os
import re
import requests
import time

# 定义中间件关键字的正则表达式,忽略大小写
KEYWORDS = ["mysql", "redis", "elasticsearch", "mongodb", "kafka", "rocketmq",
            "rabbitmq", "emq", "mqtt", "nacos", "postgresql", "doris",
            "hbase", "influxdb", "azkaban", "sls", "clickhouse",
            "mse", "dataworks", "neo4j", "http", "gitlab", "jenkins"]
PATTERN = re.compile(r'\b(?:' + '|'.join(KEYWORDS) + r')\b', re.IGNORECASE)


def read_files(directory):
    for root, _, files in os.walk(directory):
        # 忽略 .git 文件夹
        if '.git' in root:
            continue
        for file in files:
            file_path = os.path.join(root, file)
            with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
                content = f.readlines()
                yield file_path, content


def extract_context(content, file_path):
    results = []
    for i, line in enumerate(content):
        if PATTERN.search(line):
            start = i  # 从匹配到的行开始
            end = min(i + 11, len(content))  # 包含匹配行及其下方10行
            snippet = "".join(content[start:end]).strip()
            results.append(f"文件路径: {file_path}\n{snippet}")
    return results


def write_to_file(directory, contexts):
    output_file = os.path.join(directory, 'matched_content.txt')
    with open(output_file, 'w', encoding='utf-8') as f:
        for context in contexts:
            f.write(context + '\n' + '=' * 50 + '\n')
    return output_file


def send_to_model(url, model_name, prompt, content):
    headers = {"Content-Type": "application/json"}
    data = {
        "model": model_name,
        "temperature": 0.2,
        "messages": [
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": f"{prompt}\n\n{content}"}
        ]
    }

    try:
        response = requests.post(url, headers=headers, json=data)
        response.raise_for_status()
    except requests.RequestException as e:
        print(f"Request to model failed: {e}")
        return None

    response_json = response.json()
    if 'choices' not in response_json:
        print(f"Model response does not contain 'choices': {response_json}")
        return None

    return response_json['choices'][0]['message']['content']


def write_individual_results(directory, results, model_name):
    output_file = os.path.join(directory, f'{model_name}_results.txt')
    with open(output_file, 'w', encoding='utf-8') as f:
        for result in results:
            f.write(result + '\n' + '=' * 50 + '\n')
    return output_file


def combine_and_summarize(directory, llama_file, qwen_file, qwen_url):
    combined_content = ""

    # 读取llama和qwen的结果文件
    with open(llama_file, 'r', encoding='utf-8') as f:
        combined_content += f.read()

    with open(qwen_file, 'r', encoding='utf-8') as f:
        combined_content += f.read()

    # 使用qwen模型进行汇总处理
    summary_prompt = """
    1. 删除包含“配置信息未提供”等无用信息的部分。
    """
    result_summary = send_to_model(qwen_url, "qwen", summary_prompt, combined_content)

    if result_summary:
        summary_file = os.path.join(directory, 'final_summary_combined.txt')
        with open(summary_file, 'w', encoding='utf-8') as f:
            f.write(result_summary)
        print(f"汇总结果保存至: {summary_file}")
    else:
        print("汇总处理失败")


def main(directory):
    start_time = time.time()

    all_contexts = []

    for file_path, content in read_files(directory):
        contexts = extract_context(content, file_path)
        all_contexts.extend(contexts)

    # 将匹配到的内容写入文件
    matched_file = write_to_file(directory, all_contexts)

    results_llama = []
    results_qwen = []

    with open(matched_file, 'r', encoding='utf-8') as f:
        content = f.read()

    analysis_prompt = """
    1. Ignore lines starting with #, //, /**, or <!--.
    2. Exclude commented lines.
    3. Extract configuration info for: MySQL, Redis, Elasticsearch, MongoDB, Kafka, RocketMQ, RabbitMQ, EMQ, MQTT, Nacos, PostgreSQL, Doris, HBase, InfluxDB, Azkaban, SLS, ClickHouse, MSE, DataWorks, Neo4j, HTTP, HTTPS, GitLab, Jenkins.
    4. Focus on URLs, usernames, passwords, hosts, ports, and database names.
    5. Extract the following attributes:
       - Username
       - Password
       - Host
       - Port
       - Database Name
       - URL or Connection String
    6. Look for configuration patterns like key-value pairs and environment variables.
    7. Ensure extracted values are not in commented sections.
    8. Extract all distinct configurations.
    9. Handle different configuration formats (JSON, YAML, dictionaries, env variables).
    10. Delete sections containing “**配置信息未直接提供**” or similar useless content.
    """

    # 分别调用llama和qwen模型
    result_llama = send_to_model("http://1.1.1.1:8000/v1/chat/completions", "llama", analysis_prompt, content)
    result_qwen = send_to_model("http://1.1.1.1:8001/v1/chat/completions", "qwen", analysis_prompt, content)

    if result_llama:
        results_llama.append(result_llama)
    if result_qwen:
        results_qwen.append(result_qwen)

    # 分别保存llama和qwen的结果到不同文件
    llama_file = write_individual_results(directory, results_llama, "llama")
    qwen_file = write_individual_results(directory, results_qwen, "qwen")

    # 汇总llama和qwen的结果
    combine_and_summarize(directory, llama_file, qwen_file, "http://1.1.1.1:8001/v1/chat/completions")

    end_time = time.time()
    total_duration = end_time - start_time
    print(f"总耗时: {total_duration:.2f} 秒")


if __name__ == "__main__":
    main("/Users/jixing/PycharmProjects/AIOps-utils/Athena_Legacy")

7月7日,收到来自CDN群的告警,当天带宽峰值较往日上涨600倍,进一步发现是某一宣传视频被反复下载,下载用户的IP集中,都是来自山西联通ADSL的一个C段。20240807163117.jpg
通过带宽比较,6日开始就有下载,时间晚上八点开始,一直持续到夜间十一点。至此,初步的用户画像如下

  • 恶意用户IP集中,都是来自山西联通adsl用户。221.205.169段
  • 时间点固定20:00-23:00
  • 下载大文件,我们是一段100MB的宣传视频。每3-5秒下载一次
  • 屏蔽IP后,会更换IP,不断变化UA进行下载

两天账单被刷了

2万!😓

至此,没想明白这种损人不利己的行为。直到看到v2的一篇类似帖子(https://www.v2ex.com/t/1055510#reply27),pcdn用户手动制造下行流量,伪装成正常用户,妄图躲过运营商审查。
20240807160710.jpg

鉴于对公司利益造成实际损失,联合安全同事决定报警,起码提醒对方不要再有此行为。提供资料后警方不予立案,理由如下

  • 宣传视频本属于公开资源
  • 源站当时未宕机

对我们提出的经济损失不予认可。不理解但尊重!!最终因为这一两例“老鼠屎”用户,全局限制了下载速度

背景:
位于阿里云的kubernetes集群,通过ingress svc暴露,类型为ClusterIP。某天在对集群内大量缩容节点时,马上出现了大量的502、504报警
500告警.jpg

以为外部密集请求导致后端服务受影响,从监控观察并无异常,联想到最近的变更,怕不是缩容导致?正在排查的过程中,服务恢复。事后通过工单确认
ClusterIP类型的SLB后端的rs被移除时,SLB的操作就是静默丢包,也就是该SLB对任何发过来的tcp包都会默认丢弃,DROP并不会响应

  • 如果此时此链接是空闲链接,就会等待SLB设置的空闲链接超时时间,超过这个时间后,SLB断开链接
  • 如果此时此链接还有请求,由于SLB不会回ack包,客户端就会超时重传,重传的时间就取决于客户端或者内核的超时设置,比如内核ack默认会进行15次重传(net.ipv4.tcp_retries2=15),累加起来大概是924秒,JDBC URL支持设置SocketTimeout、ConnectTimeout,会在这个超时时间后断开重连

文档描述
https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/user-guide/add-annotations-to-the-yaml-file-of-a-service-to-configure-clb-instances
注解.jpg

最终解法

  • 代码中判断,失败重新建立连接
  • 在ingress中开启上述注解,缩短时间。并在谷值时缩容

早上看到一个粗看起来很简单的问题,“如何在crontab中增加每7分钟循环执行的任务”,下意识想不就是 */7。这么简单的问题怎么一堆回答。
先上结论,比如每7分钟,我10:40分添加的,

  • 第一次执行是在10:42,而不是下意识的10:47
  • 10:56最后一次执行,下一次执行是在11:00,而不是想象中的11:03

cron.jpg
也就破坏了需求中“每7分钟”,解决办法是每分钟执行,在脚本中判断当前时间

# 获取当前时间的分钟数
current_minute=$(date +"%M")

# 判断分钟数是否是7的倍数
if (( current_minute % 7 == 0 )); then
  # 如果是7的倍数,执行任务
  echo $(date +"%Y-%m-%d %H:%M:%S") >> /tmp/timestamp.txt
fi

背景:

我们有一款私有化部署系统,服务于用户购买的智能终端(简单理解为顺丰小哥手持的扫码枪)。周六接到端开发工程师反馈,此批设备续航异常,理论数据两周,但实际只有三至四天。
经过监测电量、抓包手段,电流的峰谷交替约为20秒电量消耗.jpg
端上抓包也显示每20秒收到来自服务器的keepalive报文,此原因导致设备无法休眠!

排查过程:

  1. 首先去服务端抓包,很清晰也能看到每20秒。当我看到抓包结果时,马上自信的答复,这是端上发来的keepalive包呀,肯定端上问题,不查端查服务器干嘛- -!keepalive包.jpg
  2. battle,端开发工程师回怼,“我抓包是从服务器端返回的”,仔细一看还真是。这时候懵圈,证据显示都是对方发来的,且正确响应
  3. 没头绪时,在想经历的中间环节。智能终端---aws NLB---mqtt服务器,NLB配置了标准的tls,卸载证书后转发到mqtt,功能测试都正常,且NLB用了这么久,不应该有问题
  4. 难道是运营商或者网络设备发送?想想不可能,tcp无法伪造IP,持续没头绪
  5. 中间环节只有NLB,进一步排查发现aws的NLB有区别于其他云的独特“机制”aws机制.jpg
  6. 接下来就是验证EIP直接暴露,问题消失。问题确认

总结:

aws NLB产品如果配置了tls监听,会主动20秒为周期发送keepalive!!!

客户端发送Keep-Alive包
AWS NLB行为时间线

时间点行为描述
第0秒客户端发送Keep-Alive包,NLB接收到并立即返回。
第20秒NLB发送Keep-Alive包到前端和后端。
第40秒NLB再次发送Keep-Alive包到前端和后端。
第60秒客户端再次发送Keep-Alive包,NLB接收到并重置计时。
第80秒NLB发送Keep-Alive包到前端和后端。
...重复每20秒发送Keep-Alive包的过程,直到客户端停止发送。

阿里云NLB行为时间线

时间点行为描述
第0秒客户端发送Keep-Alive包,NLB接收到并保持连接。
第60秒客户端再次发送Keep-Alive包,NLB接收到并保持连接。
第120秒客户端再次发送Keep-Alive包,NLB接收到并保持连接。
...重复每60秒发送Keep-Alive包的过程,直到客户端停止发送。

客户端不发送Keep-Alive包
AWS NLB行为时间线

时间点行为描述
第0秒客户端与NLB建立连接。
第350秒没有数据包发送,NLB关闭连接并发送TCP RST包。
第351秒连接关闭,客户端无法继续发送数据。

阿里云NLB行为时间线

时间点行为描述
第0秒客户端与NLB建立连接。
第900秒没有数据包发送,NLB关闭连接。
第901秒连接关闭,客户端无法继续发送数据。

在上一篇文档中实现了检查单台服务器故障的典型排错场景。此次我们加大难度
一、排查链路中故障,识别南北向流量走向并给出排查结果

  • 难点

    • 模型无法理解私有环境
    • 给出的建议具备安全风险
  • 思路

    • 结合提示词,使用function call功能来准确获取配置
    • 新增the_supervisor角色,对planer的建议安全过滤

二、与真实用户交流,给出域名申请建议并检测是否可用

  • 难点

    • 引导用户使用合规的子域名
  • 思路

    • 提示词约定规范,使用socket库来判断可用性

整体难点,多agent执行顺序,“技能绑定”,来看效果。图1为用户与gatekeeper探讨需求pic1.jpg
图2为agent建议用户使用的解析记录pic2.jpg
图3为正确路由南北向流量问题,并使用对应function判断pic3.jpg

关键代码片段
pic4.jpg

探索大模型在运维工作中的方向,此篇主要讲故障排查。是“Autogen 运维排错实践-复杂案例”的进一步整合,改进如下

  • 通过跳板机,不需要在目标机器安装agent,零侵入
  • 入口统一,集成在运维系统
  • 模型自由切换,GPT-4/Claude/tongyi等等

效果

用户在资产中选择目标机器
host_management.png
描述故障,选择策略(自动执行、逐步询问),点击执行
start_tr.png
输出结果
end_tr.png

方案设计

利用堡垒机与所有目标机器互通,将aiagent部署在此。通过提示词确认专精方向、连接方式。后端使用Django开启websocket,前端使用xterm.js模拟终端
topology.png

重点

  • Xterm.js学习曲线陡峭,捕获中文、英文、空格、回退,快捷键等均需要自定义。在即将完成时看到有封装更简单的项目webssh
  • Autogen中与openai通信使用了api.openai.com,改对应库中的域名至代理域名
  • websocket模式需要配置asgi使用,加载静态文件有差别。consumers.py和routing.py需自定义
  • AIagent中提示词需要明确,注意模型的上下文限制,通过提示词截取部分结果

- 阅读剩余部分 -

模型仅具备各领域的通用知识,对于垂类仍有进步空间,这也是医疗、政务类模型出现的原因。我们在尝试AIagent时发现模型并不够聪明,对于安装性能分析工具,vim前后台等问题无法进展到下一步,详见 Autogen 运维排错实践-复杂案例。此次尝试使用偏运维领域的ServerFault,爬取经过人工审核的有效答案来微调模型,观察效果。简言之,教模型所不擅长

步骤

  1. 爬取ServerFault,筛选有效问答
  2. 微调模型
  3. AutoGen配置微调后模型

先看效果,根据采集到的数据,统计出ServerFault热门词云
ciyun-new.jpg

爬虫

筛选逻辑,根据Active状态&前500页&作者vote过的问题,分别记录问题链接、标题、内容、发布时间、更新时间、被查看总数、投票总数;答案内容、得分9个字段,两张表通过外键关联

CREATETABLE Posts (
    PostID INTEGERPRIMARYKEY,
    PostLink TEXTNOTNULL,
    Title TEXTNOTNULL,
    PostContent TEXTNOTNULL,
    PostTime TEXTNOTNULL,-- ISO8601 strings ("YYYY-MM-DD HH:MM:SS.SSS")
    ModifyTime TEXTNOTNULL,
    ViewCount INTEGERNOTNULL,
    VoteCount INTEGERNOTNULL
);
CREATETABLE Answers (
    AnswerID INTEGERPRIMARYKEY,
    PostID INTEGER,
    AnswerContent TEXTNOTNULL,
    VoteCount INTEGERNOTNULL,
FOREIGNKEY(PostID)REFERENCES Posts(PostID)

);NO;

经过控制爬虫速率,切换代理地址,共采集问题、答案数

数量
Posts6681
Answers16253

VoteCount分布

0-100101-200201-300301-400401-500>500
Posts627885321315
Answers15643150311678

- 阅读剩余部分 -

让查数据这件事,不再是高高在上、遥不可及的技能,而是人人都能玩得转,妙趣横生的小技巧。比如“我的店上周赚了多少钱?哪个商品即将售罄?这个月卖的最多的商品是啥?”,下一秒,答案就像变魔术一样蹦出来。直接看效果

流程如下,

  • 前端使用gradio,采集麦克风声音
  • 后端收到声音,使用openai的speech-to-text
  • 文字通过dbgpt(链接各种自定义模型),转换为sql进行数据库查询
  • 返回对应数据

关键代码

- 阅读剩余部分 -

需求如下,产品团队高频要求翻译团队给出符合标准的翻译件,比如翻译产品文档,其中又有大量的术语,比如3D结构光、扫码头、主屏、客显屏、立式等(在公司内有统一的标准叫法),使用市面通用的翻译产品需要自己修改。看效果
翻译效果.jpg

原理如图
Retrieval.png

openai负责文档Retrieval,flowise负责功能补充,同时做了一次封装,gradio负责提供展示页面,方便用户交互

gradio_run.py

import gradio as gr
import requests
import json

def call_api(question):
    url = "https://xxxx.com/api/v1/prediction/asdasce1-5a7b-4d9e-9ed6-21a9aaaab2"
    headers = {"Content-Type": "application/json"}
    data = {"question": question}
    response = requests.post(url, headers=headers, data=json.dumps(data))
    return response.json().get("text", "No response text found.")

iface = gr.Interface(
    fn=call_api,
    inputs="text",
    outputs="text",
)

iface.launch()

一直有个需求,企业内私有知识库RAG,“陪产假怎么申请?”,“公司发票抬头是啥?”等问题,解放行政、人事的部分人力。偶然发现钉钉“智能员工”非常契合。零代码开发、配置简单。看效果,支持单聊群聊。目前免费!
RAG-01.jpg
RAG-02.jpg

配置方式,登录钉钉开发者-数字员工,类似flowise编辑langchain的每个环节,别担心,有模板只需要简单修改!在知识库贴钉文档的链接。文档准备需要注意以下几点

  1. 主题、内容紧密相关
  2. 段落清晰,一段文字不超过500字,长文本可以拆成多段
  3. QA优先级最高
  4. 用标准中文,反对“互联网黑话”
  5. 单文件不超10mb
  6. 通义模型基于中文,中文提示词效果更好
  7. 温度尽可能低,0.1

钉钉AI.jpg