Go SDK接入指南

更新时间:
复制为 MD 格式

通过客户端接入概述您已经了解了HTTPDNS接入的基本原理,本文介绍通过Go SDK接入HTTPDNS的方法。

一、快速入门

1.1 开通服务

请参考快速入门开通HTTPDNS。

1.2 获取配置

请参考开发配置EMAS控制台开发配置中获取AccountId/SecretKey/AESSecretKey等信息,用于初始化SDK。

二、安装

通过go get安装:

go get github.com/aliyun/alicloud-httpdns-go-sdk/pkg/httpdns

接入示例:

参考 GitHub仓库中的示例代码和文档。

三、配置和使用

3.1 初始化配置

应用启动后,需要先初始化SDK,才能调用HTTPDNS能力。初始化主要是配置AccountId/SecretKey等信息及功能开关。示例代码如下:

package main

import (
    "context"
    "log"
    "os"

    "github.com/aliyun/alicloud-httpdns-go-sdk/pkg/httpdns"
)

func main() {
    config := httpdns.DefaultConfig()
    config.AccountID = "your-account-id"
    config.SecretKey = "your-secret-key"  // 可选,用于鉴权解析
    config.EnableHTTPS = true             // 是否使用HTTPS

    client, err := httpdns.NewClient(config)
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()
}
重要

EnableHTTPS参数设置为true后,计费会增加,请仔细阅读产品计费文档。

3.1.1 日志配置

应用开发过程中,如果要输出HTTPDNS的日志,可以在初始化时配置Logger,示例代码如下:

config := httpdns.DefaultConfig()
config.Logger = log.New(os.Stdout, "[HTTPDNS] ", log.LstdFlags)

3.2 域名解析

3.2.1 同步解析

同步解析方法会优先返回缓存结果,缓存未命中时发起HTTP请求,示例代码如下:

func resolve(client httpdns.Client) {
    ctx := context.Background()
    result, err := client.Resolve(ctx, "www.aliyun.com")
    if err != nil {
        log.Printf("解析失败: %v", err)
        return
    }
    
    log.Printf("域名: %s", result.Domain)
    log.Printf("IPv4: %v", result.IPv4)
    log.Printf("IPv6: %v", result.IPv6)
    log.Printf("TTL: %v", result.TTL)
}

3.2.2 异步解析

当需要非阻塞解析时,可以使用异步解析方法,该方法通过回调返回结果,示例代码如下:

func asyncResolve(client httpdns.Client) {
    ctx := context.Background()
    client.ResolveAsync(ctx, "www.aliyun.com", func(result *httpdns.ResolveResult, err error) {
        if err != nil {
            log.Printf("异步解析失败: %v", err)
            return
        }
        log.Printf("异步解析结果: %s -> %v", result.Domain, result.IPv4)
    })
}

3.2.3 批量解析

当需要同时解析多个域名时,可以使用批量解析方法,示例代码如下:

func batchResolve(client httpdns.Client) {
    ctx := context.Background()
    domains := []string{"www.aliyun.com", "www.taobao.com", "www.tmall.com"}
    
    results, err := client.ResolveBatch(ctx, domains)
    if err != nil {
        log.Printf("批量解析失败: %v", err)
        return
    }
    
    for _, result := range results {
        log.Printf("域名: %s, IPv4: %v", result.Domain, result.IPv4)
    }
}
说明

单次批量解析最多支持5个域名,超过限制将返回错误。

四、Go最佳实践

通过自定义DialContext,可以将HTTPDNS解析结果无缝集成到标准net/http客户端中,同时支持HTTPHTTPS。

步骤1:创建HTTPDNS客户端

package main

import (
    "context"
    "fmt"
    "log"
    "net"
    "net/http"
    "os"
    "time"

    "github.com/aliyun/alicloud-httpdns-go-sdk/pkg/httpdns"
)

func main() {
    // 创建HTTPDNS客户端
    config := httpdns.DefaultConfig()
    config.AccountID = "your-account-id"
    config.SecretKey = "your-secret-key"
    config.Logger = log.New(os.Stdout, "[HTTPDNS] ", log.LstdFlags)
    
    dnsClient, err := httpdns.NewClient(config)
    if err != nil {
        log.Fatal(err)
    }
    defer dnsClient.Close()
    
    // 创建集成HTTPDNS的HTTP客户端
    httpClient := createHTTPDNSClient(dnsClient)
    
    // 发起请求
    resp, err := httpClient.Get("https://www.aliyun.com")
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    
    fmt.Printf("Status: %s\n", resp.Status)
}

步骤2:创建自定义HTTP客户端

func createHTTPDNSClient(dnsClient httpdns.Client) *http.Client {
    return &http.Client{
        Timeout: 30 * time.Second,
        Transport: &http.Transport{
            DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
                // 解析域名和端口
                host, port, err := net.SplitHostPort(addr)
                if err != nil {
                    return nil, err
                }
                
                // 使用HTTPDNS解析域名
                result, err := dnsClient.Resolve(ctx, host)
                if err != nil {
                    log.Printf("[DNS Lookup] HTTPDNS解析失败,降级到系统DNS: %s, error: %v", host, err)
                    return net.Dial(network, addr)
                }
                
                // 优先使用IPv4
                var resolvedIP string
                if len(result.IPv4) > 0 {
                    resolvedIP = result.IPv4[0].String()
                    log.Printf("[DNS Lookup] HTTPDNS解析成功: %s -> %s (IPv4)", host, resolvedIP)
                } else if len(result.IPv6) > 0 {
                    resolvedIP = result.IPv6[0].String()
                    log.Printf("[DNS Lookup] HTTPDNS解析成功: %s -> %s (IPv6)", host, resolvedIP)
                } else {
                    log.Printf("[DNS Lookup] HTTPDNS无可用IP,降级到系统DNS: %s", host)
                    return net.Dial(network, addr)
                }
                
                // 使用解析的IP建立连接
                return net.Dial(network, net.JoinHostPort(resolvedIP, port))
            },
            MaxIdleConns:        100,
            IdleConnTimeout:     90 * time.Second,
            DisableCompression:  false,
        },
    }
}

五、API

5.1 初始化

初始化配置,在应用启动时调用。

config := httpdns.DefaultConfig()
config.AccountID = "your-account-id"
config.SecretKey = "your-secret-key"

client, err := httpdns.NewClient(config)
if err != nil {
    log.Fatal(err)
}
defer client.Close()

参数:

参数名

类型

是否必须

功能

AccountID

string

必选参数

Account ID

SecretKey

string

可选参数

加签密钥

BootstrapIPs

[]string

可选参数

启动IP列表

Timeout

time.Duration

可选参数

解析超时时间,默认5

MaxRetries

int

可选参数

最大重试次数,默认0

EnableHTTPS

bool

可选参数

是否使用HTTPS,默认false

EnableMetrics

bool

可选参数

是否启用指标统计,默认false

EnableMemoryCache

bool

可选参数

是否启用内存缓存,默认true

EnablePersistentCache

bool

可选参数

是否启用持久化缓存,默认false

AllowExpiredCache

bool

可选参数

是否允许使用过期缓存,默认false

CacheExpireThreshold

time.Duration

可选参数

持久化缓存过期阈值,默认0

Logger

Logger

可选参数

日志记录器

5.2 域名解析

解析指定域名。

ctx := context.Background()
result, err := client.Resolve(ctx, "www.aliyun.com")
if err != nil {
    log.Printf("解析失败: %v", err)
    return
}

fmt.Printf("IPv4: %v\n", result.IPv4)
fmt.Printf("IPv6: %v\n", result.IPv6)

参数:

参数名

类型

是否必须

功能

ctx

context.Context

必选参数

上下文

domain

string

必选参数

域名

opts

...ResolveOption

可选参数

解析选项

解析选项:

选项函数

功能

WithIPv4Only()

仅解析IPv4

WithIPv6Only()

仅解析IPv6

WithBothIP()

同时解析IPv4IPv6

WithTimeout(duration)

设置超时时间

WithClientIP(ip)

设置客户端IP,用于就近接入

返回字段说明:

字段名

类型

功能

Domain

string

域名

ClientIP

string

客户端IP

IPv4

[]net.IP

IPv4地址列表

IPv6

[]net.IP

IPv6地址列表

TTL

time.Duration

TTL时间

Source

ResolveSource

解析来源

Timestamp

time.Time

解析时间戳

5.3 批量解析

批量解析多个域名。

ctx := context.Background()
domains := []string{"www.aliyun.com", "www.taobao.com"}
results, err := client.ResolveBatch(ctx, domains)
if err != nil {
    log.Printf("批量解析失败: %v", err)
    return
}

for _, result := range results {
    fmt.Printf("域名: %s, IPv4: %v\n", result.Domain, result.IPv4)
}

参数:

参数名

类型

是否必须

功能

ctx

context.Context

必选参数

上下文

domains

[]string

必选参数

域名列表,最多5

opts

...ResolveOption

可选参数

解析选项

5.4 异步解析

异步解析域名,通过回调返回结果。

ctx := context.Background()
client.ResolveAsync(ctx, "www.aliyun.com", func(result *httpdns.ResolveResult, err error) {
    if err != nil {
        log.Printf("异步解析失败: %v", err)
        return
    }
    fmt.Printf("解析结果: %v\n", result.IPv4)
})

参数:

参数名

类型

是否必须

功能

ctx

context.Context

必选参数

上下文

domain

string

必选参数

域名

callback

func(*ResolveResult, error)

必选参数

回调函数

opts

...ResolveOption

可选参数

解析选项

5.5 客户端管理

获取客户端状态和管理客户端生命周期。

// 检查客户端健康状态
isHealthy := client.IsHealthy()

// 获取当前服务IP列表
serviceIPs := client.GetServiceIPs()

// 手动更新服务IP
err := client.UpdateServiceIPs(ctx)

// 获取指标统计
stats := client.GetMetrics()
fmt.Printf("总解析次数: %d\n", stats.TotalResolves)
fmt.Printf("成功率: %.2f%%\n", stats.SuccessRate*100)
fmt.Printf("平均延迟: %v\n", stats.AvgLatency)

// 重置指标统计
client.ResetMetrics()

// 关闭客户端
err := client.Close()

六、总结

本文介绍了Go环境下HTTPDNS SDK的使用方法和最佳实践。通过自定义DialContext方式集成HTTP客户端,可以实现高性能、高可用的域名解析服务。主要特点包括:

  1. 简单易用:提供同步、异步和批量解析接口

  2. 高可用性:内置缓存机制和降级策略

  3. 安全可靠:支持鉴权解析和HTTPS通信

通过遵循本文的最佳实践建议,开发者可以在Go应用中高效地集成HTTPDNS服务。