← 中文资源

简体中文版本

Anycast 任播路由

Anycast 在全球多点宣告同一 IP,BGP 路由把每个用户送到拓扑最近的健康节点,既压缩延迟又隔离区域故障。

阅读英文原文

概念定义

任播是编址策略:同一 IP 从多个数据中心同时宣告,BGP 把每个客户端导向拓扑最近的宣告点。节点撤回路由时流量数秒内自动转移,无需逐客户端的 DNS 技巧就实现地理延迟分散与区域故障切换。

工作机制

每个站点经 BGP 宣告前缀,全局路由表按路径长度而非实测延迟解析到最近宣告者。节点必须内容一致或无状态,因为用户的新连接可能被路由到不同站点。DNS 服务正是利用单包特性在任播上跑查询。

使用场景

DNS、静态内容、DDoS 清洗与无状态 API 边缘是理想场景。攻击流量也会被摊到所有站点,稀释体积型洪泛。区域容量规划必须能承接维护或故障期间改道的流量。

常见误区

任播不是负载均衡器:路由按拓扑分流量,不含服务器负载与健康的概念。有状态服务被任播后在 BGP 改道时会丢会话;QUIC 对连接迁移的容忍度优于纯 TCP。流量分布跟随互联网地理而非业务指标,自动扩缩容必须按站点进行;路由抖动会造成全球性劣化,撤回路由要谨慎。

代码示例

package main

import (
	"context"
	"fmt"
	"net"
	"sort"
	"time"
)

func Lookup(ctx context.Context, host string) ([]string, error) {
	addresses, err := net.DefaultResolver.LookupHost(ctx, host)
	if err != nil {
		return nil, err
	}
	sort.Strings(addresses)
	return addresses, nil
}

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	defer cancel()
	addresses, err := Lookup(ctx, "localhost")
	if err != nil {
		fmt.Println("lookup failed:", err)
		return
	}
	for _, address := range addresses {
		fmt.Println(address)
	}
}
import { createClient } from '@supabase/supabase-js';

const supabase = createClient(
  process.env.SUPABASE_URL,
  process.env.SUPABASE_ANON_KEY,
  { persistSession: false },
);

const { data: active, error } = await supabase
  .from('projects')
  .select('id, name, owner_id, updated_at')
  .eq('status', 'active')
  .gte('updated_at', '2026-10-01')
  .order('updated_at', { ascending: false })
  .range(0, 19);

if (error) throw new Error(error.message);

const { data: upserted } = await supabase
  .from('projects')
  .upsert({ id: 77, name: 'pipeline', status: 'active' }, { onConflict: 'id' })
  .select();

const channel = supabase
  .channel('projects-changes')
  .on('postgres_changes', { event: '*', schema: 'public', table: 'projects' },
    (payload) => console.log('change:', payload.event))
  .subscribe();

await new Promise((r) => setTimeout(r, 1000));
supabase.removeChannel(channel);
console.log('active projects:', active.length, 'upserted:', upserted.length);