docs: 联网搜索服务架构方案全套(plan-final/design-arch/选型决策/整合导览/MCP文档/部署预设/联调手册) bench: 5 方案 + 代理 + 站点矩阵本机实测工程(无密钥) 部署目标:primary mgr1 先行测试(待批准后执行)
135 lines
4.2 KiB
Bash
Executable file
135 lines
4.2 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# T3 / T5 request helper for searxng-global. No secrets.
|
|
set -euo pipefail
|
|
ROOT="$(cd "$(dirname "$0")" && pwd)"
|
|
BASE="${BASE:-http://127.0.0.1:18882}"
|
|
Q="${Q:-best bluetooth earbuds 2026 reddit}"
|
|
MAX_TIME="${MAX_TIME:-45}"
|
|
|
|
one() {
|
|
local engines="${1:-}"
|
|
local label="${2:-t3}"
|
|
local body code_file metrics http_code t_nl t_conn ttfb t_total bytes
|
|
body="$(mktemp)"
|
|
local extra=()
|
|
if [[ -n "$engines" ]]; then
|
|
extra+=(--data-urlencode "engines=${engines}")
|
|
fi
|
|
metrics="$(curl -sS -G "${BASE}/search" \
|
|
--data-urlencode "q=${Q}" \
|
|
--data-urlencode "format=json" \
|
|
--data-urlencode "language=en-US" \
|
|
--data-urlencode "categories=general" \
|
|
${extra[@]+"${extra[@]}"} \
|
|
-o "$body" \
|
|
-w '%{http_code} %{time_namelookup} %{time_connect} %{time_starttransfer} %{time_total} %{size_download}' \
|
|
--connect-timeout 10 --max-time "$MAX_TIME" \
|
|
-A 'onesvm-bench/s3c' || true)"
|
|
read -r http_code t_nl t_conn ttfb t_total bytes <<<"$metrics"
|
|
python3 - "$body" "$http_code" "$t_nl" "$t_conn" "$ttfb" "$t_total" "$bytes" "$label" "$engines" <<'PY'
|
|
import json, sys, os, datetime
|
|
body_path, http_code, t_nl, t_conn, ttfb, t_total, bytes_, label, engines = sys.argv[1:10]
|
|
raw = open(body_path, "rb").read()
|
|
os.unlink(body_path)
|
|
text = raw.decode("utf-8", "replace")
|
|
obj = None
|
|
err = ""
|
|
try:
|
|
obj = json.loads(text) if text.strip() else None
|
|
except Exception as e:
|
|
err = str(e)
|
|
results = (obj or {}).get("results") or []
|
|
engines_hit = []
|
|
hosts = []
|
|
reddit = False
|
|
for r in results:
|
|
eng = r.get("engine") or ""
|
|
if eng and eng not in engines_hit:
|
|
engines_hit.append(eng)
|
|
url = r.get("url") or ""
|
|
host = ""
|
|
if "://" in url:
|
|
host = url.split("/")[2].lower()
|
|
if host not in hosts:
|
|
hosts.append(host)
|
|
blob = ((r.get("title") or "") + " " + (r.get("content") or "") + " " + url).lower()
|
|
if "reddit.com" in host or host.endswith("redd.it") or "reddit" in blob:
|
|
reddit = True
|
|
unresp = (obj or {}).get("unresponsive_engines") or []
|
|
# searxng: list of [name, error] or dicts
|
|
un_names = []
|
|
for u in unresp:
|
|
if isinstance(u, (list, tuple)) and u:
|
|
un_names.append(str(u[0]))
|
|
elif isinstance(u, dict):
|
|
un_names.append(str(u.get("engine") or u.get("name") or u))
|
|
else:
|
|
un_names.append(str(u))
|
|
good = 0
|
|
for r in results[:10]:
|
|
title = (r.get("title") or "").strip()
|
|
url = (r.get("url") or "").strip()
|
|
content = (r.get("content") or "").strip()
|
|
if title and url.startswith("http") and len(content) >= 8:
|
|
good += 1
|
|
assert_ok = (
|
|
str(http_code) == "200"
|
|
and len(results) >= 5
|
|
and len(engines_hit) >= 2
|
|
and len(hosts) >= 3
|
|
and reddit
|
|
)
|
|
note = ""
|
|
if "google" in [x.lower() for x in un_names]:
|
|
note = "google_captcha_or_unresponsive"
|
|
out = {
|
|
"ts": datetime.datetime.now().astimezone().isoformat(timespec="seconds"),
|
|
"scheme": "searxng-global",
|
|
"template": label,
|
|
"engines_param": engines,
|
|
"http_code": int(http_code or 0) if str(http_code).isdigit() else 0,
|
|
"t_namelookup": float(t_nl or 0),
|
|
"t_connect": float(t_conn or 0),
|
|
"ttfb": float(ttfb or 0),
|
|
"t_total": float(t_total or 0),
|
|
"bytes": int(float(bytes_ or 0)),
|
|
"n_results": len(results),
|
|
"engines": engines_hit,
|
|
"hosts": hosts[:20],
|
|
"host_n": len(hosts),
|
|
"reddit_ref": reddit,
|
|
"unresponsive_engines": un_names,
|
|
"good_snippets_top10": good,
|
|
"assert_ok": assert_ok,
|
|
"parse_error": err,
|
|
"note": note,
|
|
}
|
|
print(json.dumps(out, ensure_ascii=False))
|
|
# keep a compact results excerpt for samples
|
|
excerpt = {
|
|
"http_code": out["http_code"],
|
|
"n_results": out["n_results"],
|
|
"engines": engines_hit,
|
|
"unresponsive_engines": un_names,
|
|
"results_head": [
|
|
{"title": (r.get("title") or "")[:180], "url": r.get("url"), "engine": r.get("engine"),
|
|
"content": (r.get("content") or "")[:240]}
|
|
for r in results[:8]
|
|
],
|
|
}
|
|
sys.stderr.write(json.dumps(excerpt, ensure_ascii=False) + "\n")
|
|
PY
|
|
}
|
|
|
|
cmd="${1:-t3}"
|
|
case "$cmd" in
|
|
t3) one "" t3 ;;
|
|
t5) one "" t5 ;;
|
|
engine)
|
|
one "${2:?engine name}" "t3-engine-${2}"
|
|
;;
|
|
*)
|
|
echo "usage: $0 t3|t5|engine <name>" >&2
|
|
exit 2
|
|
;;
|
|
esac
|