Skip to content

Day 5:gRPC服务化——让任何语言都能调你的分析能力

今天做什么

把文档分析能力封装成 gRPC 服务。Java、Python、Node.js——任何语言的服务都能通过 gRPC 调用你的分析引擎。

Proto 定义

proto/analyzer.proto

protobuf
syntax = "proto3";
package analyzer;
option go_package = "doc_analyzer/proto";

service DocAnalyzer {
  rpc Analyze(AnalyzeRequest) returns (AnalyzeResponse);
  rpc AnalyzeStream(AnalyzeRequest) returns (stream AnalyzeChunk);
}

message AnalyzeRequest {
  string document = 1;
  string format = 2; // markdown, text, pdf
}

message AnalyzeResponse {
  string summary = 1;
  repeated string key_points = 2;
}

message AnalyzeChunk {
  string content = 1;
  float progress = 2;
}

gRPC Server

go
package main

import (
    "context"
    "fmt"
    "log"
    "net"

    pb "doc_analyzer/proto"
    "google.golang.org/grpc"
)

type AnalyzerServer struct {
    pb.UnimplementedDocAnalyzerServer
    analyzer *CachedAnalyzer
}

func (s *AnalyzerServer) Analyze(ctx context.Context, 
    req *pb.AnalyzeRequest) (*pb.AnalyzeResponse, error) {

    result, _, err := s.analyzer.AnalyzeWithCache(ctx, req.Document)
    if err != nil {
        return nil, err
    }

    return &pb.AnalyzeResponse{
        Summary:   result.Summary,
        KeyPoints: result.KeyPoints,
    }, nil
}

// 流式接口:边分析边返回
func (s *AnalyzerServer) AnalyzeStream(req *pb.AnalyzeRequest, 
    stream pb.DocAnalyzer_AnalyzeStreamServer) error {

    steps := []string{"解析文档", "提取要点", "分析趋势", "生成总结"}
    
    for i, step := range steps {
        select {
        case <-stream.Context().Done():
            return nil
        default:
        }
        
        // 分步返回进度
        stream.Send(&pb.AnalyzeChunk{
            Content:  fmt.Sprintf("[%s] 处理中...", step),
            Progress: float32(i+1) / float32(len(steps)),
        })
    }

    return nil
}

func main() {
    lis, _ := net.Listen("tcp", ":50051")
    s := grpc.NewServer()
    pb.RegisterDocAnalyzerServer(s, &AnalyzerServer{
        analyzer: NewCachedAnalyzer(5),
    })

    fmt.Println("🚀 gRPC 分析服务启动在 :50051")
    log.Fatal(s.Serve(lis))
}

运行

bash
# 生成 proto stub
protoc --go_out=. --go-grpc_out=. proto/analyzer.proto

# 启动服务
go run server.go

# 其他语言调用(Python 示例)
python -c "
import grpc, analyzer_pb2, analyzer_pb2_grpc
channel = grpc.insecure_channel('localhost:50051')
stub = analyzer_pb2_grpc.DocAnalyzerStub(channel)
resp = stub.Analyze(analyzer_pb2.AnalyzeRequest(document='Q1财报...'))
print(resp.summary)
"

Day 5 完成。任何语言都能调你的分析引擎了。