Обработка ошибок и повторные попытки в Didit API на Go: Глубокое погружение (RU)
Создание надежных интеграций с Didit API на Go требует продуманной обработки ошибок и стратегий повторных попыток. Это руководство исследует лучшие практики, начиная с понимания ограничений скорости Didit и специфических кодов.

Понимание лимитов скорости DiditВнедряйте клиентское регулирование и экспоненциальную задержку для ответов 429, используя заголовки
X-RateLimit-Limit,X-RateLimit-RemainingиX-RateLimit-Resetдля предотвращения сбоев в работе сервиса.Различение типов ошибокРазличайте временные (например, проблемы с сетью, недоступность сервиса) и постоянные ошибки (например, недействительные ключи API, некорректные запросы), чтобы применять соответствующую логику повторных попыток или быстрое завершение работы.
Внедрение надежных механизмов повторных попытокИспользуйте структурированные циклы повторных попыток с экспоненциальной задержкой, джиттером и максимальным количеством попыток для корректной обработки временных сбоев, повышая надежность критически важных операций, таких как создание сессий.
Подход Didit, ориентированный на разработчиков, упрощает интеграциюDidit предоставляет четкую документацию API, специфические заголовки для ограничения скорости и модульную архитектуру, позволяя Go-разработчикам легко и уверенно создавать отказоустойчивые потоки верификации личности.
Интеграция сторонних API является краеугольным камнем современной разработки приложений, и верификация личности не является исключением. При работе с критически важными сервисами, такими как платформа идентификации Didit, крайне важно обеспечить устойчивость вашей интеграции к колебаниям сети, сбоям в работе сервисов и ограничениям скорости. Это руководство углубляется в продвинутые стратегии обработки ошибок и повторных попыток, специально разработанные для интеграций Didit API с использованием Go, помогая вам создавать надежные и отказоустойчивые системы.
Понимание ландшафта ошибок Didit API
Прежде чем внедрять какую-либо логику повторных попыток, крайне важно понять типы ошибок, с которыми вы можете столкнуться. API Didit, как и многие хорошо спроектированные сервисы, сообщает о различных состояниях через коды состояния HTTP. В то время как стандартные коды 2xx указывают на успех, вы будете в основном сосредоточены на 4xx (ошибки клиента) и 5xx (ошибки сервера), и особенно на 429 (Слишком много запросов).
Ограничение скорости Didit и что это значит для вас
Didit применяет ограничение скорости для поддержания стабильности API. Это критически важный аспект для управления в вашей интеграции. Например, конечные точки GET обычно имеют глобальный лимит в 300 запросов в минуту на приложение, при этом специфические конечные точки, такие как session-decision (100 запросов в минуту) или session-v2-create (600 запросов в минуту), имеют свои собственные, потенциально более строгие, лимиты. Когда вы достигаете лимита скорости, Didit отвечает кодом состояния 429 Too Many Requests и включает полезные заголовки:
X-RateLimit-Limit: Максимальное количество запросов, разрешенных в текущем окне.X-RateLimit-Remaining: Количество оставшихся запросов в текущем окне.X-RateLimit-Reset: Время (в секундах эпохи), когда сбрасывается текущее окно ограничения скорости.Retry-After: (Часто включается) Количество секунд, которое нужно подождать, прежде чем сделать еще один запрос.
Ваш Go-клиент должен активно отслеживать эти заголовки. Когда X-RateLimit-Remaining падает ниже определенного порога (например, 15% от X-RateLimit-Limit), вы должны активно регулировать свои запросы. Игнорирование этих заголовков может привести к постоянным ошибкам 429, что повлияет на способность вашего приложения создавать сессии верификации или получать результаты от таких продуктов, как Didit ID Verification или AML Screening.
Внедрение надежных стратегий повторных попыток с экспоненциальной задержкой в Go
Для временных ошибок (например, тайм-ауты сети, временная недоступность сервиса или 429) повторные попытки необходимы. Однако наивные повторные попытки могут усугубить проблемы. Золотым стандартом является экспоненциальная задержка с джиттером.
Экспоненциальная задержка с джиттером
Экспоненциальная задержка означает экспоненциальное увеличение времени ожидания между повторными попытками. Джиттер (добавление небольшой случайной задержки) предотвращает проблему «грохочущего стада», когда множество клиентов повторяют попытки одновременно после сбоя, снова перегружая сервис. Вот концептуальный пример на Go:
package main
import (
"fmt"
"io/ioutil"
"net/http"
"time"
"math/rand"
)
func callDiditAPIWithRetry(url string, maxRetries int) ([]byte, error) {
client := &http.Client{Timeout: 10 * time.Second}
rand.Seed(time.Now().UnixNano())
for i := 0; i <= maxRetries; i++ {
resp, err := client.Get(url)
if err != nil {
// Handle network errors (e.g., connection refused, timeout)
fmt.Printf("Attempt %d: Network error: %v\n", i+1, err)
if i == maxRetries {
return nil, fmt.Errorf("failed after %d retries: %w", maxRetries, err)
}
sleepTime := time.Duration(1<<i)*time.Second + time.Duration(rand.Intn(1000))*time.Millisecond // Exponential backoff + jitter
fmt.Printf("Retrying in %v...\n", sleepTime)
time.Sleep(sleepTime)
continue
}
defer resp.Body.Close()
switch resp.StatusCode {
case http.StatusOK:
fmt.Printf("Attempt %d: Success!\n", i+1)
return ioutil.ReadAll(resp.Body)
case http.StatusTooManyRequests:
// Respect Retry-After header if present
retryAfter := resp.Header.Get("Retry-After")
if retryAfter != "" {
if sleepSeconds, err := time.ParseDuration(retryAfter + "s"); err == nil {
fmt.Printf("Attempt %d: Rate limited. Retrying after %v.\n", i+1, sleepSeconds)
time.Sleep(sleepSeconds)
continue
}
}
// Fallback to exponential backoff if Retry-After is missing or invalid
fmt.Printf("Attempt %d: Rate limited (429).\n", i+1)
if i == maxRetries {
return nil, fmt.Errorf("rate limited after %d retries", maxRetries)
}
sleepTime := time.Duration(1<<i)*time.Second + time.Duration(rand.Intn(1000))*time.Millisecond
fmt.Printf("Retrying in %v...\n", sleepTime)
time.Sleep(sleepTime)
continue
case http.StatusInternalServerError, http.StatusBadGateway, http.StatusServiceUnavailable, http.StatusGatewayTimeout:
// Server-side errors that might be transient
fmt.Printf("Attempt %d: Server error %d. Retrying.\n", i+1, resp.StatusCode)
if i == maxRetries {
return nil, fmt.Errorf("server error %d after %d retries", resp.StatusCode, maxRetries)
}
sleepTime := time.Duration(1<<i)*time.Second + time.Duration(rand.Intn(1000))*time.Millisecond
fmt.Printf("Retrying in %v...\n", sleepTime)
time.Sleep(sleepTime)
continue
default:
// Non-retryable errors (4xx client errors, etc.)
body, _ := ioutil.ReadAll(resp.Body)
return nil, fmt.Errorf("non-retryable API error: %d %s, response: %s", resp.StatusCode, resp.Status, string(body))
}
}
return nil, fmt.Errorf("unexpected control flow") // Should not be reached
}
func main() {
// Example usage: Replace with actual Didit API endpoint
// For a real integration, you'd be POSTing to /v3/session/ or similar
// and handling the verification_url.
apiURL := "https://verification.didit.me/health"
data, err := callDiditAPIWithRetry(apiURL, 5)
if err != nil {
fmt.Println("Failed to call API:", err)
} else {
fmt.Println("API Response:", string(data))
}
}
Этот фрагмент демонстрирует, как обрабатывать сетевые ошибки, 429-е ошибки (с учетом Retry-After) и распространенные 5xx ошибки с экспоненциальной задержкой и джиттером. Он также показывает быстрое завершение для не подлежащих повторной попытке 4xx ошибок, которые обычно возникают из-за неправильного ввода и не будут решены при повторной попытке. Это крайне важно для таких операций, как создание сессии верификации с использованием модульной архитектуры Didit.
Внедрение паттерна "автомат-выключатель"
В то время как повторные попытки помогают при временных проблемах, постоянные повторные попытки обращения к сбойному сервису могут еще больше перегрузить его или потратить ресурсы впустую, если сервис действительно не работает. Именно здесь на помощь приходит паттерн "автомат-выключатель". "Автомат-выключатель" отслеживает сбои и, если они достигают определенного порога, "размыкает" цепь, предотвращая дальнейшие запросы на заданный период. По истечении этого периода он позволяет несколько тестовых запросов, чтобы проверить, восстановился ли сервис.
В Go вы можете использовать библиотеки, такие как sony/gobreaker, для реализации этого паттерна:
package main
import (
"errors"
"fmt"
"io/ioutil"
"net/http"
"time"
"github.com/sony/gobreaker"
)
var cb *gobreaker.CircuitBreaker
func init() {
st := gobreaker.Settings{
Name: "DiditAPICircuitBreaker",
MaxRequests: 3, // Allow 3 requests in half-open state
Interval: 5 * time.Second, // Period to collect data for trip decisions
Timeout: 10 * time.Second, // Open circuit for 10 seconds
ReadyToTrip: func(counts gobreaker.Counts) bool {
return counts.ConsecutiveFailures > 5 // Trip after 5 consecutive failures
},
OnStateChange: func(name string, from gobreaker.State, to gobreaker.State) {
fmt.Printf("Circuit Breaker '%s' changed from %s to %s\n", name, from, to)
},
}
cb = gobreaker.NewCircuitBreaker(st)
}
func callDiditAPIWithCircuitBreaker(url string) ([]byte, error) {
body, err := cb.Execute(func() (interface{}, error) {
resp, err := http.Get(url)
if err != nil {
return nil, err // Network error
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
// Only count 5xx and 429 as failures for circuit breaker
if resp.StatusCode == http.StatusTooManyRequests || resp.StatusCode >= http.StatusInternalServerError {
return nil, fmt.Errorf("API returned status %d", resp.StatusCode)
}
// For other 4xx errors, we might not want to trip the breaker, but still return an error
bodyBytes, _ := ioutil.ReadAll(resp.Body)
return nil, fmt.Errorf("non-retryable API error: %d %s, response: %s", resp.StatusCode, resp.Status, string(bodyBytes))
}
return ioutil.ReadAll(resp.Body)
})
if err != nil {
if errors.Is(err, gobreaker.ErrOpenState) {
return nil, fmt.Errorf("circuit breaker is open: %w", err)
}
return nil, err
}
return body.([]byte), nil
}
func main() {
// Example usage
apiURL := "https://verification.didit.me/health"
for i := 0; i < 10; i++ {
data, err := callDiditAPIWithCircuitBreaker(apiURL)
if err != nil {
fmt.Printf("Call %d failed: %v\n", i+1, err)
} else {
fmt.Printf("Call %d successful: %s\n", i+1, string(data))
}
time.Sleep(1 * time.Second)
}
}
Сочетание "автоматов-выключателей" с экспоненциальной задержкой гарантирует, что ваше приложение останется отзывчивым и не перегрузит испытывающий трудности внешний сервис. Это особенно важно при работе с большим объемом запросов на верификацию личности, таких как те, что связаны с Didit ID Verification или Passive & Active Liveness checks.
Обработка сбоев вебхуков и асинхронных результатов
API Didit часто предоставляет результаты асинхронно через вебхуки, например, после того, как пользователь завершает процесс верификации ID или когда завершается проверка AML Screening. Ваша конечная точка вебхука должна быть надежной. Если ваша конечная точка не обрабатывает вебхук (например, возвращает код состояния 5xx), Didit повторит доставку вебхука. Крайне важно:
- Немедленно подтвердить получение: Верните код состояния 2xx как можно быстрее, чтобы сигнализировать об успешном получении, даже если обработка занимает больше времени.
- Обработка асинхронно: Передайте полезную нагрузку вебхука фоновому рабочему процессу или очереди сообщений (например, Kafka, RabbitMQ) для обработки. Это предотвращает тайм-аут вашей конечной точки вебхука при повторных попытках Didit.
- Идемпотентность: Убедитесь, что ваша логика обработки вебхука идемпотентна. Если Didit повторяет попытку и доставляет один и тот же вебхук несколько раз, ваша система должна обрабатывать его только один раз, чтобы избежать дублирования действий или несогласованности данных.
- Проверка подписей: Всегда проверяйте подпись вебхука, используя ваш
Webhook Secret Keyиз Didit Console, чтобы убедиться, что запрос действительно исходит от Didit и не был подделан.
Как Didit помогает
Didit разработан с учетом опыта разработчиков и надежности, предоставляя функции, которые по своей сути упрощают расширенную обработку ошибок и стратегии повторных попыток для ваших Go-интеграций. Наш подход, ориентированный на разработчиков, означает четкую, всеобъемлющую документацию API, мгновенную песочницу и чистые API, которые делают интеграцию простой.
- Предсказуемое ограничение скорости: Didit четко определяет глобальные и специфичные для конечных точек ограничения скорости, а также стандартные заголовки HTTP (
X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Reset,Retry-After) для управления вашей клиентской логикой регулирования и задержки. Эта прозрачность позволяет вам создавать оптимизированные механизмы повторных попыток для таких сервисов, как ID Verification и AML Screening. - Модульная архитектура: Наши модульные примитивы идентификации позволяют создавать рабочие процессы, которые устойчивы по своей конструкции. Если один конкретный чек (например, Proof of Address) сталкивается с временной проблемой, ваш общий рабочий процесс может быть настроен на адаптацию или повторную попытку выполнения конкретных компонентов без влияния на несвязанные шаги верификации.
- Надежность на основе ИИ: Бэкенд Didit на основе ИИ создан для масштабирования и отказоустойчивости, минимизируя серверные ошибки, с которыми вы столкнетесь. Это позволяет вам сосредоточиться на обработке ошибок, связанных с сетью и клиентом, а не на постоянных сбоях в работе сервиса.
- Бесплатный Core KYC и гибкие тарифы: Начните работу с бесплатным уровнем Didit для Core KYC, что позволит вам тщательно протестировать стратегии обработки ошибок и повторных попыток в производственной среде без первоначальных затрат. Наша модель оплаты за успешную проверку еще больше соответствует нашим и вашим успехам.
Готовы начать?
Готовы увидеть Didit в действии? Получите бесплатную демонстрацию сегодня.
Начните бесплатно проверять личности с бесплатным уровнем Didit.