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 完成。任何语言都能调你的分析引擎了。

