IF
IndexFlowing
/ Docs
🌐 English Docs GitHub ↗

系统架构

IndexFlow 是一个高吞吐、编译型 Rust 服务。它将异步 Web 服务器、启用预写式日志(WAL)的嵌入式 SQLite 数据库、后台 worker,以及独立的技术 SEO 和 sitemap 库组合为一个可部署的二进制文件。


1. 高层架构分层

┌─────────────────────────────────────────────────────────────────────────┐
│                           1. Presentation Layer                         │
│  - Axum 0.7 HTTP Router                                                 │
│  - Interactive Web Console (Askama HTML Templates + HTMX)               │
│  - JSON REST & API Endpoints (/api/v1/*)                                │
└────────────────────────────────────┬────────────────────────────────────┘
                                     │
                                     ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                           2. Application Layer                          │
│  - PipelineManager (Arc<RwLock<HashSet<PipelineStage>>>)                │
│  - SiteService         - UrlService           - SitemapService          │
│  - HealthService       - GscService           - BingService             │
│  - SubmissionService   - ViewBoostRegistry                              │
└────────────┬───────────────────────────────────────────────┬────────────┘
             │                                               │
             ▼                                               ▼
┌──────────────────────────┐                    ┌────────────────────────┐
│  3. Background Workers   │                    │  4. Standalone Crates  │
│  - SyncWorker            │                    │  - indexflow-sitemap   │
│  - SeoAuditWorker (x30)  │                    │  - indexflow-seo       │
│  - GscInspectWorker (x3) │                    └────────────────────────┘
│  - BingInspectWorker(x2) │                                 │
│  - BingSubmitWorker      │                    ┌────────────┴───────────┐
│  - GoogleSubmitWorker    │                    │  5. External Providers │
└────────────┬─────────────┘                    │  - Google OAuth2 / GSC │
             │                                  │  - Bing IndexNow / BWT │
             ▼                                  └────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│                      6. Infrastructure & Storage                        │
│  - SQLite 3 (WAL Mode, synchronous = NORMAL, busy_timeout = 5s)         │
│  - Repositories: UrlRepo, SiteRepo, AdminRepo, HealthCheckRepo,         │
│    SubmissionLogRepo, IndexHistoryRepo                                  │
└─────────────────────────────────────────────────────────────────────────┘

2. 流水线生命周期与并发管理

IndexFlow 使用线程安全的 PipelineManager 协调后台工作流。引擎不使用分散的原子标志,而是维护正在运行阶段的活动集合:

pub enum PipelineStage {
    Sitemap,     // Stage 1: Sitemap asset discovery
    SeoGate,      // Stage 2: Technical SEO & GEO pre-flight audit
    GscInspect,   // Stage 3a: Google Search Console inspection & pool sync
    BingInspect,  // Stage 3b: Bing Webmaster Tools official inspection
    PushSubmit,   // Stage 4: Engine active push (IndexNow & Google Indexing)
}

阶段转换与并发预算

[ Trigger: UI or API ]
         │
         ▼
[ PipelineManager::start(stage) ]
         │
         ├───> SyncWorker (1 Task per Site, chunks of 500 records)
         ├───> SeoAuditWorker (Concurrency: 30 Semaphore, 5MB body cap)
         ├───> GscInspectWorker (Concurrency: 3, 250ms interval, 429 auto-stop)
         ├───> BingInspectWorker (Concurrency: 2, 500ms interval, 1.5 QPS throttle backoff)
         └───> PushWorkers (Google: Rolling 24h quota; Bing: Batch JSON)
         ▼
[ Queue Exhausted -> PipelineManager::stop(stage) ]

3. URL 优先级调度算法

URL 从 sitemap 发现或同步时,IndexFlow 会计算 1 到 999 的调度优先级整数(数值越小表示紧急程度越高)。这直接决定所有后台检查和审计 worker 使用的 ORDER BY priority ASC, id ASC 领取顺序。

分数通过 compute_url_priority 计算:

$$\text{Priority} = \text{Score}{\text{sitemap}} + \text{Score}{\text{age}} + \text{Penalty}{\text{known}} + \text{Boost}{\text{update}}$$

pub fn compute_url_priority(
    sitemap_priority: Option<f64>,
    lastmod: Option<DateTime<Utc>>,
    previous_lastmod: Option<DateTime<Utc>>,
    is_new: bool,
    now: DateTime<Utc>,
) -> i32 {
    let sp = sitemap_priority.unwrap_or(0.5).clamp(0.0, 1.0);
    let from_sitemap = ((1.0 - sp) * 400.0).round() as i32;
    let from_lastmod = match lastmod { None => 150, Some(lm) => { let age = now.signed_duration_since(lm); if age <= Duration::hours(24) { 0 } else if age <= Duration::days(7) { 40 } else if age <= Duration::days(30) { 100 } else if age <= Duration::days(90) { 180 } else { 280 } } };
    let from_new = if is_new { 0 } else { 80 };
    let from_update = match (lastmod, previous_lastmod) { (Some(cur), Some(prev)) if cur > prev => -60, (Some(_), None) if !is_new => -30, _ => 0, };
    (from_sitemap + from_lastmod + from_new + from_update).clamp(1, 999)
}

4. 查看加速机制

操作员在 Web 控制台(/indexing 或 /seo)查看 URL 的具体页面时,当前可见 URL 应优先接受检查。

IndexFlow 实现了 View Boost Registry(ViewBoostRegistry):

  1. 渲染分页表格视图时,处理器登记可见 URL ID:
    state.view_boost.record(current_site_id, items.iter().map(|u| u.id).collect());
    
  2. worker 查询以 30 秒 TTL 优先获取这些活动 ID:
    SELECT * FROM urls
    WHERE gsc_index_status = 'UNKNOWN'
    ORDER BY (CASE WHEN id IN ($1, $2, $3...) THEN 0 ELSE 1 END), priority ASC, id ASC
    LIMIT 50;
    
  3. 这样后台处理大型队列时,UI 仍能获得实时响应。

5. Token 缓存与提供商认证

Google OAuth2 架构

Google API 要求使用 RSA-SHA256 签名的 JWT assertion 交换访问 token。

  • GoogleAuthClient 解析服务账号 JSON 密钥。
  • 使用 webmasters.readonly 和 indexing scope 签署有效期 1 小时的 JWT。
  • 将交换得到的 OAuth2 Bearer token 缓存在内存 RwLock<HashMap<String, CachedToken>> 中。
  • 剩余有效期少于 5 分钟时自动刷新,避免重复网络往返。

Bing Webmaster Tools API 缓存

Bing 通过查询参数(?apikey=...)传递 API 密钥。

  • BingProvider 通过 GetUserSites 解析规范站点身份前缀。
  • 按站点在内存中缓存解析出的资源 URL,减少外部 API 调用。