Khi xây dựng hệ thống cần gọi AI API với lượng request lớn, tôi đã thử qua nhiều giải pháp. Từ việc dùng worker pool đơn giản đến kiến trúc pipeline phức tạp, cuối cùng tôi chọn HolySheep AI làm API gateway vì hiệu suất vượt trội và chi phí tiết kiệm đến 85%. Bài viết này chia sẻ kinh nghiệm thực chiến khi implement concurrency trong Go để gọi AI API.

Bảng So Sánh: HolySheep vs API Chính Hãng vs Relay Services

Tiêu chí HolySheep AI API Chính Hãng Relay Service Thông Thường
Tỷ giá ¥1 = $1 (85%+ tiết kiệm) Giá gốc USD Markup 20-50%
Thanh toán WeChat/Alipay/ USDT Thẻ quốc tế Hạn chế
Độ trễ trung bình <50ms 100-300ms 80-200ms
Rate limit 10,000 RPM 500-2000 RPM 1000-3000 RPM
Free credits Có khi đăng ký $5 trial Không
Retry mechanism Tích hợp sẵn Tự implement Có nhưng hạn chế

Tại Sao Go Là Lựa Chọn Tốt Nhất Cho AI API Concurrency?

Trong quá trình xây dựng hệ thống xử lý 10,000+ request/giây tới AI API, tôi đã thử Node.js, Python, và cuối cùng chọn Go vì:

Kiến Trúc Worker Pool Với Goroutine + Channel

Đây là kiến trúc tôi sử dụng trong production, xử lý batch request tới AI API với throughput cao nhất.

1. Cấu Trúc Project Cơ Bản

ai-concurrency/
├── main.go
├── config/
│   └── config.go
├── client/
│   └── holysheep.go
├── worker/
│   ├── pool.go
│   └── worker.go
├── models/
│   └── request.go
└── go.mod

2. Cài Đặt Dependencies

go mod init ai-concurrency
go get github.com/google/uuid
go get github.com/sashabaranov/go-openai

3. Implementation Chi Tiết

package main

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"sync"
	"time"

	"github.com/google/uuid"
)

// ==================== MODELS ====================

type AIRequest struct {
	ID      string
	Model   string
	Prompt  string
	MaxTokens int
}

type AIResponse struct {
	ID      string
	Content string
	Usage   TokenUsage
	Error   error
}

type TokenUsage struct {
	PromptTokens     int
	CompletionTokens int
	TotalTokens      int
}

type Config struct {
	BaseURL    string
	APIKey     string
	MaxWorkers int
	QueueSize  int
	Timeout    time.Duration
}

// ==================== HOLYSHEEP CLIENT ====================

type HolySheepClient struct {
	baseURL string
	apiKey  string
	client  *http.Client
}

func NewHolySheepClient(cfg Config) *HolySheepClient {
	return &HolySheepClient{
		baseURL: cfg.BaseURL,
		apiKey:  cfg.APIKey,
		client: &http.Client{
			Timeout: cfg.Timeout,
			Transport: &http.Transport{
				MaxIdleConns:        100,
				MaxIdleConnsPerHost: 100,
				IdleConnTimeout:     90 * time.Second,
			},
		},
	}
}

func (c *HolySheepClient) CallChatGPT(ctx context.Context, req AIRequest) (*AIResponse, error) {
	// Request body theo OpenAI format
	reqBody := map[string]interface{}{
		"model": req.Model,
		"messages": []map[string]string{
			{"role": "user", "content": req.Prompt},
		},
		"max_tokens": req.MaxTokens,
	}

	bodyBytes, err := json.Marshal(reqBody)
	if err != nil {
		return nil, fmt.Errorf("marshal error: %w", err)
	}

	httpReq, err := http.NewRequestWithContext(
		ctx,
		"POST",
		c.baseURL+"/chat/completions",
		bytes.NewBuffer(bodyBytes),
	)
	if err != nil {
		return nil, fmt.Errorf("create request error: %w", err)
	}

	httpReq.Header.Set("Content-Type", "application/json")
	httpReq.Header.Set("Authorization", "Bearer "+c.apiKey)

	resp, err := c.client.Do(httpReq)
	if err != nil {
		return nil, fmt.Errorf("http error: %w", err)
	}
	defer resp.Body.Close()

	// Parse response
	var result map[string]interface{}
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, fmt.Errorf("decode error: %w", err)
	}

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("API error: status %d, body: %v", resp.StatusCode, result)
	}

	// Extract content
	choices := result["choices"].([]interface{})
	firstChoice := choices[0].(map[string]interface{})
	message := firstChoice["message"].(map[string]interface{})
	content := message["content"].(string)

	// Extract usage
	usage := result["usage"].(map[string]interface{})

	return &AIResponse{
		ID:   req.ID,
		Content: content,
		Usage: TokenUsage{
			PromptTokens:     int(usage["prompt_tokens"].(float64)),
			CompletionTokens: int(usage["completion_tokens"].(float64)),
			TotalTokens:      int(usage["total_tokens"].(float64)),
		},
	}, nil
}

// ==================== WORKER POOL ====================

type WorkerPool struct {
	client    *HolySheepClient
	workers   int
	taskQueue chan AIRequest
	resultQueue chan AIResponse
	wg        sync.WaitGroup
	ctx       context.Context
	cancel    context.CancelFunc
}

func NewWorkerPool(client *HolySheepClient, workers, queueSize int) *WorkerPool {
	ctx, cancel := context.WithCancel(context.Background())
	return &WorkerPool{
		client:     client,
		workers:    workers,
		taskQueue:  make(chan AIRequest, queueSize),
		resultQueue: make(chan AIResponse, queueSize),
		ctx:        ctx,
		cancel:     cancel,
	}
}

func (wp *WorkerPool) Start() {
	for i := 0; i < wp.workers; i++ {
		wp.wg.Add(1)
		go wp.worker(i)
	}
}

func (wp *WorkerPool) worker(id int) {
	defer wp.wg.Done()

	for {
		select {
		case <-wp.ctx.Done():
			return
		case req, ok := <-wp.taskQueue:
			if !ok {
				return
			}
			// Xử lý request với timeout riêng
			workerCtx, cancel := context.WithTimeout(wp.ctx, 30*time.Second)
			resp, err := wp.client.CallChatGPT(workerCtx, req)
			cancel()

			if err != nil {
				wp.resultQueue <- AIResponse{
					ID:    req.ID,
					Error: err,
				}
			} else {
				wp.resultQueue <- *resp
			}
		}
	}
}

func (wp *WorkerPool) Submit(req AIRequest) bool {
	select {
	case wp.taskQueue <- req:
		return true
	default:
		return false
	}
}

func (wp *WorkerPool) SubmitAndWait(req AIRequest) (*AIResponse, error) {
	// Submit và đợi kết quả
	resultChan := make(chan AIResponse, 1)
	errorChan := make(chan error, 1)

	// Goroutine để xử lý
	go func() {
		resp, err := wp.client.CallChatGPT(wp.ctx, req)
		if err != nil {
			errorChan <- err
		} else {
			resultChan <- *resp
		}
	}()

	select {
	case resp := <-resultChan:
		return &resp, nil
	case err := <-errorChan:
		return nil, err
	case <-wp.ctx.Done():
		return nil, wp.ctx.Err()
	}
}

func (wp *WorkerPool) Stop() {
	wp.cancel()
	close(wp.taskQueue)
	wp.wg.Wait()
	close(wp.resultQueue)
}

func (wp *WorkerPool) Results() <-chan AIResponse {
	return wp.resultQueue
}

// ==================== MAIN ====================

func main() {
	// Khởi tạo client với HolySheep API
	// Đăng ký tại: https://www.holysheep.ai/register
	client := NewHolySheepClient(Config{
		BaseURL:    "https://api.holysheep.ai/v1",
		APIKey:     "YOUR_HOLYSHEEP_API_KEY",
		MaxWorkers: 50,
		QueueSize:  10000,
		Timeout:    60 * time.Second,
	})

	// Tạo worker pool với 50 workers
	pool := NewWorkerPool(client, 50, 10000)
	pool.Start()

	// Benchmark
	totalRequests := 1000
	successCount := 0
	errorCount := 0

	start := time.Now()

	// Submit tasks
	for i := 0; i < totalRequests; i++ {
		req := AIRequest{
			ID:        uuid.New().String(),
			Model:     "gpt-4.1",
			Prompt:    fmt.Sprintf("Translate to Vietnamese: Hello world %d", i),
			MaxTokens: 100,
		}

		if !pool.Submit(req) {
			errorCount++
		}
	}

	// Collect results
	for i := 0; i < totalRequests; i++ {
		resp := <-pool.Results()
		if resp.Error != nil {
			errorCount++
		} else {
			successCount++
		}
	}

	duration := time.Since(start)

	pool.Stop()

	// Stats
	fmt.Printf("=== PERFORMANCE RESULTS ===\n")
	fmt.Printf("Total requests: %d\n", totalRequests)
	fmt.Printf("Success: %d\n", successCount)
	fmt.Printf("Errors: %d\n", errorCount)
	fmt.Printf("Duration: %v\n", duration)
	fmt.Printf("Throughput: %.2f req/sec\n", float64(totalRequests)/duration.Seconds())
}

Pipeline Concurrency Với Multiple Stages

Kiến trúc pipeline cho phép xử lý request theo nhiều stages, ví dụ: pre-process → AI call → post-process.

package main

import (
	"context"
	"fmt"
	"sync"
	"time"
)

// Pipeline Stages
type PipelineRequest struct {
	ID      string
	Content string
	Result  string
	Stage   string
}

func preprocessor(id string, data string, out chan<- PipelineRequest) {
	// Preprocess: validate, transform
	processed := fmt.Sprintf("[PREPROCESSED] %s", data)
	out <- PipelineRequest{
		ID:      id,
		Content: processed,
		Stage:   "preprocessed",
	}
}

func aiProcessor(client *HolySheepClient, input <-chan PipelineRequest, out chan<- PipelineRequest) {
	for req := range input {
		// Gọi HolySheep AI
		resp, err := client.CallChatGPT(
			context.Background(),
			AIRequest{
				ID:        req.ID,
				Model:     "gpt-4.1",
				Prompt:    req.Content,
				MaxTokens: 200,
			},
		)
		if err != nil {
			req.Result = fmt.Sprintf("ERROR: %v", err)
		} else {
			req.Result = resp.Content
		}
		req.Stage = "ai_completed"
		out <- req
	}
}

func postprocessor(input <-chan PipelineRequest, out chan<- PipelineRequest) {
	for req := range input {
		// Postprocess: format, validate
		req.Result = fmt.Sprintf("[FORMATTED] %s", req.Result)
		req.Stage = "completed"
		out <- req
	}
}

func runPipeline() {
	// Tạo HolySheep client
	// Đăng ký tại: https://www.holysheep.ai/register
	client := NewHolySheepClient(Config{
		BaseURL: "https://api.holysheep.ai/v1",
		APIKey:  "YOUR_HOLYSHEEP_API_KEY",
	})

	// Buffer sizes cho channels
	preOut := make(chan PipelineRequest, 100)
	aiOut := make(chan PipelineRequest, 100)
	postOut := make(chan PipelineRequest, 100)

	var wg sync.WaitGroup

	// Start 3 preprocessors
	for i := 0; i < 3; i++ {
		wg.Add(1)
		go func(id int) {
			defer wg.Done()
			// Simulate preprocess work
			for j := 0; j < 100; j++ {
				preprocessor(fmt.Sprintf("req-%d-%d", id, j), fmt.Sprintf("data %d", j), preOut)
			}
			close(preOut)
		}(i)
	}

	// Start 5 AI processors
	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func(id int) {
			defer wg.Done()
			aiProcessor(client, preOut, aiOut)
			if id == 0 {
				close(aiOut)
			}
		}(i)
	}

	// Start 2 postprocessors
	for i := 0; i < 2; i++ {
		wg.Add(1)
		go func(id int) {
			defer wg.Done()
			postprocessor(aiOut, postOut)
			if id == 0 {
				close(postOut)
			}
		}(i)
	}

	// Collect results
	go func() {
		wg.Wait()
		close(postOut)
	}()

	// Process results
	resultCount := 0
	start := time.Now()
	for result := range postOut {
		resultCount++
		if resultCount%100 == 0 {
			fmt.Printf("Processed %d results\n", resultCount)
		}
	}

	fmt.Printf("Pipeline completed: %d results in %v\n", resultCount, time.Since(start))
}

Rate Limiter Với Token Bucket

Để tránh bị limit khi gọi API, tôi implement rate limiter với token bucket algorithm.

package main

import (
	"context"
	"fmt"
	"sync"
	"time"
)

// TokenBucket Rate Limiter
type RateLimiter struct {
	mu       sync.Mutex
	tokens   float64
	maxTokens float64
	rate      float64 // tokens per second
	lastTime time.Time
}

func NewRateLimiter(rpm int) *RateLimiter {
	return &RateLimiter{
		tokens:    float64(rpm) / 60.0 * 2, // initial burst
		maxTokens: float64(rpm) / 60.0 * 2,
		rate:      float64(rpm) / 60.0,
		lastTime:  time.Now(),
	}
}

func (rl *RateLimiter) Allow() bool {
	rl.mu.Lock()
	defer rl.mu.Unlock()

	now := time.Now()
	elapsed := now.Sub(rl.lastTime).Seconds()
	rl.lastTime = now

	// Add tokens based on elapsed time
	rl.tokens += elapsed * rl.rate
	if rl.tokens > rl.maxTokens {
		rl.tokens = rl.maxTokens
	}

	if rl.tokens >= 1.0 {
		rl.tokens -= 1.0
		return true
	}
	return false
}

func (rl *RateLimiter) Wait(ctx context.Context) error {
	for {
		if rl.Allow() {
			return nil
		}

		select {
		case <-ctx.Done():
			return ctx.Err()
		case <-time.After(10 * time.Millisecond):
			// retry
		}
	}
}

// BurstRateLimiter: kết hợp burst limit và rate limit
type BurstRateLimiter struct {
	*RateLimiter
	semaphore chan struct{}
}

func NewBurstRateLimiter(rpm, burst int) *BurstRateLimiter {
	return &BurstRateLimiter{
		RateLimiter: NewRateLimiter(rpm),
		semaphore:   make(chan struct{}, burst),
	}
}

func (brl *BurstRateLimiter) Acquire(ctx context.Context) error {
	select {
	case brl.semaphore <- struct{}{}:
		return brl.Wait(ctx)
	default:
		return fmt.Errorf("burst limit exceeded")
	}
}

func (brl *BurstRateLimiter) Release() {
	<-brl.semaphore
}

// Retry mechanism với exponential backoff
func withRetry(ctx context.Context, fn func() error, maxRetries int) error {
	var err error
	for i := 0; i < maxRetries; i++ {
		err = fn()
		if err == nil {
			return nil
		}

		select {
		case <-ctx.Done():
			return ctx.Err()
		case <-time.After(time.Duration(1<

Tài nguyên liên quan

Bài viết liên quan