loading…
Diagnostic tests
— click a button above to run a test —
Ручной парсинг лота
Запрашивает свежие данные с Copart UK, обновляет БД и (при необходимости) докачивает картинки.
images_downloaded_at картинки не перекачиваются
(защита от лишнего расхода прокси-квоты). Сами байты в любом случае не дублируются
— Storage.Exists() проверяется перед каждым download'ом.
Сводка за 24 часа обновляется автоматически
Последние запуски crawler / sweeper
фильтр:
| start | kind | status | duration | pages | lots seen | new / upd | lost | images ok / fail | error |
|---|---|---|---|---|---|---|---|---|---|
| loading… | |||||||||
Картинки: окно
Распределение по типу события
| kind | ok | failed | success rate |
|---|
Топ ошибок
| error | count |
|---|
HTTP-статусы
Последние события
| occurred | lot | kind | outcome | http | bytes | duration | error |
|---|---|---|---|---|---|---|---|
| loading… | |||||||
Аналитика API: окно
Запросы по времени
Топ маршрутов
| method | route | requests | errors | avg, ms | p95, ms | bytes out |
|---|
Топ клиентов (за окно)
| client / api_key | requests | errors | last seen |
|---|
Распределение по статусам
Текущая конфигурация живёт в памяти процесса
Деплой в Google Cloud
Краткий план
Сервис состоит из трёх процессов: api (HTTP), crawler (обходит каталог), sweeper (рефрешит лоты в горизонте 48ч). Все три собираются из одного Dockerfile. Картинки складываются в S3-совместимое хранилище. Postgres лучше всего держать в Cloud SQL, чтобы не управлять persistence руками.
- Подготовьте GCP-проект и API.
gcloud projects create copart-uk --name "copart-uk" gcloud config set project copart-uk gcloud services enable run.googleapis.com artifactregistry.googleapis.com \ sqladmin.googleapis.com secretmanager.googleapis.com \ compute.googleapis.com storage.googleapis.com - Создайте Artifact Registry и загрузите образ.
gcloud artifacts repositories create copart-uk \ --repository-format=docker --location=europe-west2 REGION=europe-west2 IMG="$REGION-docker.pkg.dev/$(gcloud config get-value project)/copart-uk/api:$(git rev-parse --short HEAD)" docker build --platform=linux/amd64 -t "$IMG" . docker push "$IMG"
- Cloud SQL Postgres.
gcloud sql instances create copart-uk-pg --database-version=POSTGRES_16 \ --region=europe-west2 --tier=db-custom-2-7680 --storage-type=SSD --storage-size=50 gcloud sql databases create copart --instance=copart-uk-pg gcloud sql users create copart --instance=copart-uk-pg --password=... # Используйте Cloud SQL Auth Proxy или приватный VPC connector — open INET не нужен.
- Бакет для картинок. Можно AWS S3 (рекомендуется для меньшей задержки до cs.copart.com), либо GCS в S3-совместимом режиме.
# Вариант 1: GCS в S3-режиме gcloud storage buckets create gs://copart-uk-images --location=europe-west2 \ --uniform-bucket-level-access # HMAC-ключ: gsutil hmac create copart-uk-images-sa@$(gcloud config get-value project).iam.gserviceaccount.com # → выдаст S3_ACCESS_KEY и S3_SECRET_KEY # В env: # S3_ENDPOINT=storage.googleapis.com # S3_USE_SSL=true # S3_REGION=auto # S3_BUCKET=copart-uk-images # Вариант 2: AWS S3 (eu-west-2) aws s3api create-bucket --bucket copart-uk-images --region eu-west-2 \ --create-bucket-configuration LocationConstraint=eu-west-2 - Секреты в Secret Manager.
for k in JWT_SECRET DATABASE_URL S3_ACCESS_KEY S3_SECRET_KEY PROXY_LIST AUCTIONSAPI_COMPAT_KEY; do echo -n "..." | gcloud secrets create $k --data-file=- done
- Деплой
apiна Cloud Run. Stateless, авто-скейл, hooks на /healthz. Не подойдёт для crawler/sweeper — Run останавливает контейнер без активных запросов.gcloud run deploy copart-uk-api \ --image="$IMG" --region=$REGION --port=8080 \ --memory=1Gi --cpu=2 --min-instances=1 --max-instances=5 \ --add-cloudsql-instances=$(gcloud config get-value project):$REGION:copart-uk-pg \ --set-env-vars=STORAGE_BACKEND=s3,S3_BUCKET=copart-uk-images,S3_ENDPOINT=s3.eu-west-2.amazonaws.com,S3_REGION=eu-west-2,S3_USE_SSL=true,CHROMEDP_ENABLED=false,PROXY_QUOTA_GB=500 \ --set-secrets=JWT_SECRET=JWT_SECRET:latest,DATABASE_URL=DATABASE_URL:latest,S3_ACCESS_KEY=S3_ACCESS_KEY:latest,S3_SECRET_KEY=S3_SECRET_KEY:latest,AUCTIONSAPI_COMPAT_KEY=AUCTIONSAPI_COMPAT_KEY:latest \ --allow-unauthenticated
Внимание: для
apiChromedp не нужен (его использует только bootstrap-flow в crawler/sweeper). Cloud Run не позволяет монтировать/dev/shmв нужном размере — отключайте chromedp на API. - Crawler / sweeper — Compute Engine или GKE. Это долгоживущие процессы с Chrome (нужно
shm_size=1g). Простейший способ — Compute Engine VMe2-standard-2, на которой черезdocker composeподняты crawler + sweeper.gcloud compute instances create copart-uk-workers \ --zone=europe-west2-a --machine-type=e2-standard-2 \ --image-family=cos-stable --image-project=cos-cloud \ --tags=copart-workers --service-account=copart-uk-sa@... # на машине запустить docker compose --profile crawler,sweeper up -d
Если уже есть GKE — Deployment с
emptyDir { medium: Memory, sizeLimit: 1Gi }на/dev/shm. - Миграции. Один shot-job до деплоя
api.gcloud run jobs deploy copart-uk-migrate \ --image="$IMG" --command=/usr/local/bin/goose \ --args="-dir,/app/migrations,postgres,${DATABASE_URL},up" \ --set-secrets=DATABASE_URL=DATABASE_URL:latest \ --region=$REGION gcloud run jobs execute copart-uk-migrate --region=$REGION --wait - Cloud Logging / Monitoring. Запросы пишутся в stdout (chi middleware.Logger) и автоматически индексируются. Используйте лог-фильтр
resource.type="cloud_run_revision" severity>=WARNINGдля алертов.
Локальный запуск
cp .env.example .env # для локалки переопределите STORAGE_BACKEND=fs или поднимите MinIO из docker-compose docker compose up -d postgres redis minio docker compose run --rm migrate docker compose up -d api docker compose --profile crawler run --rm crawler # одноразовый прогон docker compose up -d sweeper # фон
Токены и доступы
Какие тут есть тачки авторизации?
- JWT (Bearer) — для
/v1/*(lots, search). Конфиг:JWT_SECRET. Алгоритм — HMAC (HS256/HS384/HS512). - API-ключ (
?api_key=…или заголовокX-Api-Key) — для/api/cars(auctionsapi.com-совместимый эндпоинт). Конфиг:AUCTIONSAPI_COMPAT_KEY. Если переменная пустая — middleware пропускает всех (dev-режим). - Без авторизации —
/img/{lot}/{file},/healthz, и сам админ-UI (предполагается, что он закрыт IAP/VPN на уровне сети).
Генерация JWT
Самый быстрый путь — однострочник на Python (никаких сторонних утилит ставить не нужно):
python3 - <<'PY'
import hmac, hashlib, json, base64, time, os
secret = os.environ["JWT_SECRET"].encode()
header = base64.urlsafe_b64encode(json.dumps({"alg":"HS256","typ":"JWT"}).encode()).rstrip(b'=')
payload = base64.urlsafe_b64encode(json.dumps({
"sub": "client-acme", # client identifier — попадает в request log
"iat": int(time.time()),
"exp": int(time.time()) + 365*24*3600,
}).encode()).rstrip(b'=')
signing = header + b'.' + payload
sig = base64.urlsafe_b64encode(hmac.new(secret, signing, hashlib.sha256).digest()).rstrip(b'=')
print((signing + b'.' + sig).decode())
PY
Используется так:
curl -H "Authorization: Bearer $TOKEN" \
https://api.copart-uk.example.com/v1/lots/12345678
Использование API-ключа для /api/cars
# через query
curl "https://api.copart-uk.example.com/api/cars?limit=50&api_key=$AUCTIONSAPI_COMPAT_KEY"
# или через заголовок
curl -H "X-Api-Key: $AUCTIONSAPI_COMPAT_KEY" \
https://api.copart-uk.example.com/api/cars?limit=50
Ротация
- JWT: поменяйте
JWT_SECRETв Secret Manager → перезапуститеapi. Все ранее выписанные токены инвалидируются. Перед ротацией выдайте клиентам новые токены, чтобы избежать простоя. - API-ключ: аналогично, поменяйте
AUCTIONSAPI_COMPAT_KEY. Сейчас поддерживается один активный ключ; для постепенной ротации запустите две версии сервиса с разными ключами и распределите трафик через Cloud Run revisions. - Все запросы пишутся в
api_request_logсlast4ключа иclient_idиз JWT — следите за аномалиями во вкладке Аналитика API.
Безопасность
- Админ-UI не имеет встроенной авторизации — закройте его IAP (Cloud Run → Identity-Aware Proxy) или ограничьте по IP через Cloud Load Balancer.
- Никогда не коммитьте
.envс реальными секретами. Используйте Secret Manager +--set-secrets. - Прокси-листы (
PROXY_LIST,IMAGE_PROXY_LIST) тоже секреты — там логины IPRoyal.