| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- package aws
- import (
- "container/list"
- "context"
- "net"
- "net/http"
- "sync"
- "time"
- )
- var DnsCacheTransport = &http.Transport{
- Proxy: http.ProxyFromEnvironment,
- DialContext: DnsCacheTransportDialContext(&net.Dialer{
- Timeout: 30 * time.Second,
- KeepAlive: 30 * time.Second,
- }, NewDnsResolver(100)),
- ForceAttemptHTTP2: true,
- MaxIdleConns: 100,
- IdleConnTimeout: 90 * time.Second,
- TLSHandshakeTimeout: 10 * time.Second,
- ExpectContinueTimeout: 1 * time.Second,
- }
- func DnsCacheTransportDialContext(dialer *net.Dialer, resolver *DnsResolver) func(context.Context, string, string) (net.Conn, error) {
- return func(ctx context.Context, network, address string) (net.Conn, error) {
- conn, err := dialer.DialContext(ctx, network, address)
- if err != nil {
- remoteAddr, exists := resolver.cache.Get(address)
- if exists {
- return dialer.DialContext(ctx, network, remoteAddr)
- }
- return conn, err
- }
- if conn.RemoteAddr().String() != "" {
- resolver.cache.Set(address, conn.RemoteAddr().String())
- }
- return conn, err
- }
- }
- type DnsResolver struct {
- cache *FIFOCache
- }
- // NewDnsResolver 创建一个新的 DNS 解析器,使用固定长度的 FIFO 缓存
- func NewDnsResolver(maxSize int) *DnsResolver {
- return &DnsResolver{
- cache: NewFIFOCache(maxSize),
- }
- }
- // FIFOCache 实现一个固定大小的并发安全FIFO(先进先出)缓存
- // 当缓存满时,添加新条目会自动淘汰最早插入的条目
- type FIFOCache struct {
- maxSize int // 缓存的最大容量
- cache map[string]string // 存储键值对的映射
- keys *list.List // 使用链表维护键的插入顺序(FIFO)
- rwMutex sync.RWMutex // 读写锁,保证并发安全
- }
- // NewFIFOCache 创建并返回一个新的FIFOCache实例
- // 参数:
- //
- // maxSize: 缓存的最大容量,必须大于0,否则默认为100
- //
- // 返回值:
- //
- // *FIFOCache: 新创建的缓存实例
- func NewFIFOCache(maxSize int) *FIFOCache {
- if maxSize < 1 {
- maxSize = 100
- }
- return &FIFOCache{
- maxSize: maxSize,
- cache: make(map[string]string),
- keys: list.New(),
- }
- }
- // Set 添加或更新一个键值对到缓存中
- // 如果缓存已满且键不存在,会淘汰最早插入的条目
- // 参数:
- //
- // key: 要添加或更新的键
- // value: 要添加或更新的值
- //
- // 返回值:
- //
- // string: 如果键已存在,返回被替换的旧值;否则返回空字符串
- // bool: 表示是否替换了现有值(true表示替换,false表示新增)
- func (c *FIFOCache) Set(key, value string) (string, bool) {
- c.rwMutex.Lock()
- defer c.rwMutex.Unlock()
- // 检查键是否已存在
- oldValue, exists := c.cache[key]
- if exists {
- // 更新现有键的值
- c.cache[key] = value
- return oldValue, true
- }
- // 缓存已满,淘汰最旧的条目
- if c.keys.Len() >= c.maxSize {
- oldest := c.keys.Front()
- if oldest != nil {
- oldestKey := oldest.Value.(string)
- delete(c.cache, oldestKey)
- c.keys.Remove(oldest)
- }
- }
- // 添加新条目
- c.cache[key] = value
- c.keys.PushBack(key)
- return "", false
- }
- // Get 从缓存中获取指定键对应的值
- // 参数:
- //
- // key: 要查找的键
- //
- // 返回值:
- //
- // string: 找到的值(如果键不存在则返回空字符串)
- // bool: 表示键是否存在(true表示存在,false表示不存在)
- func (c *FIFOCache) Get(key string) (string, bool) {
- c.rwMutex.RLock()
- defer c.rwMutex.RUnlock()
- value, exists := c.cache[key]
- return value, exists
- }
- // Size 返回缓存中当前存储的条目数量
- // 返回值:
- //
- // int: 当前缓存中的条目数量
- func (c *FIFOCache) Size() int {
- c.rwMutex.RLock()
- defer c.rwMutex.RUnlock()
- return len(c.cache)
- }
- // GetMaxSize 返回缓存的最大容量
- // 返回值:
- //
- // int: 缓存的最大容量
- func (c *FIFOCache) GetMaxSize() int {
- return c.maxSize
- }
|