
microservices-demo 系列解析Shippingservice 物流/配送微服務的 gRPC 報價與訂單履約實現【免費下載鏈接】microservices-demoSample cloud-first application with 10 microservices showcasing Kubernetes, Istio, and gRPC.項目地址: https://gitcode.com/GitHub_Trending/mi/microservices-demo導讀Shippingservice 是 microservices-demo在線精品店示例中負責物流履約的微服務它并不真正發貨而是以模擬的方式提供三項核心能力運費報價price quote、跟蹤號tracking ID生成以及訂單履約/配送流程的完整體驗。本文以倉庫中 src/shippingservice/README.md 為骨架深入其 Go 源碼、protobuf 定義、測試用例與 Kubernetes 清單幫助你掌握該服務從本地構建、鏡像打包、單元測試到部署運行的完整鏈路并理解它與 checkoutservice 之間的 gRPC 調用關系。服務定位與整體架構Shipping Service 在 10 個微服務組成的電商鏈路中處于下單后段當用戶結算時checkoutservice 會調用本服務完成兩件事——先計算運費再發貨并取得跟蹤號。整個調用鏈可概括為frontend → checkoutservice → shippingserviceGetQuote 報價 └→ shippingserviceShipOrder 發貨/跟蹤號從 protos/demo.proto 的接口定義可以看到Shippingservice 暴露了非常精簡的兩個 RPCservice ShippingService { rpc GetQuote(GetQuoteRequest) returns (GetQuoteResponse) {} rpc ShipOrder(ShipOrderRequest) returns (ShipOrderResponse) {} } message GetQuoteRequest { Address address 1; repeated CartItem items 2; } message GetQuoteResponse { Money cost_usd 1; } message ShipOrderRequest { Address address 1; repeated CartItem items 2; } message ShipOrderResponse { string tracking_id 1; } message Address { string street_address 1; string city 2; string state 3; string country 4; int32 zip_code 5; }其中Money采用整數 units 納秒 nanos的標準表示法如$-1.75 units-1, nanos-750,000,000避免浮點精度問題這個 proto 文件由倉庫根目錄的 protos/demo.proto 統一維護并通過 genproto.sh 生成 Go 代碼到 src/shippingservice/genproto 目錄generated code 由 protoc-gen-go 生成請勿手工編輯。本地依賴還原與構建依賴管理Go modulesREADME 中提到使用dep ensure --vendor-only將依賴還原到vendor/目錄這是項目早期基于 dep 工具的做法。當前倉庫已遷移到 Go modulesgo.mod 聲明了模塊路徑github.com/GoogleCloudPlatform/microservices-demo/src/shippingservice、Go 版本 1.25.0 及工具鏈 go1.26.5核心依賴包括google.golang.org/grpcv1.83.0 —— gRPC 框架google.golang.org/protobufv1.36.11 —— protobuf 運行時github.com/sirupsen/logrusv1.9.4 —— 結構化日志cloud.google.com/go/profilerv0.6.0 —— Stackdriver/Cloud Profiler因此在當前代碼庫中本地開發等價地使用標準命令即可# 進入服務目錄 cd src/shippingservice # 下載依賴go.mod / go.sum 已在倉庫中 go mod download # 如需重新生成 gRPC 代碼倉庫已內置 genproto 產物一般無需執行 ./genproto.sh說明dep ensure --vendor-only與go mod download二選一即可前者僅適用于舊版 dep 工作流后者為當前倉庫的實際形態。Docker 鏡像構建README 給出的構建命令為# 在 src/shippingservice 目錄下執行 docker build ./對應的 Dockerfile 采用兩階段構建值得逐層解讀# 階段一編譯 ARG BUILDPLATFORMlinux/amd64 FROM --platform$BUILDPLATFORM golang:1.26.5-alpine AS builder WORKDIR /src COPY go.mod go.sum ./ RUN go mod download # 利用層緩存先還原依賴 COPY . . # 支持 skaffold debug 傳入編譯參數 ARG SKAFFOLD_GO_GCFLAGS RUN GOOS${TARGETOS} GOARCH${TARGETARCH} CGO_ENABLED0 \ go build -ldflags-s -w -gcflags${SKAFFOLD_GO_GCFLAGS} -o /go/bin/shippingservice . # 階段二精簡運行鏡像 FROM gcr.io/distroless/static WORKDIR /src COPY --frombuilder /go/bin/shippingservice /src/shippingservice ENV APP_PORT50051 ENV GOTRACEBACKsingle EXPOSE 50051 ENTRYPOINT [/src/shippingservice]要點CGO_ENABLED0distroless/static產出無 glibc 依賴的靜態二進制鏡像體積小、無 shell 層契合安全基線ENV APP_PORT50051與EXPOSE 50051聲明了服務端口與 Kubernetes 清單保持一致GOTRACEBACKsingle配合 skaffold debug 定位 Go 協程故障。單元測試README 給出的測試命令go test .倉庫內 shippingservice_test.go 提供了 8 組針對核心邏輯的單元測試是理解服務行為最好的活的文檔測試函數驗證內容TestGetQuote非空購物車2 個商品、數量 13應返回$8.99units8, nanos990000000TestGetQuoteEmptyCart空購物車返回$0.00units0, nanos0TestShipOrderShipOrder返回的跟蹤號長度為 18 個字符TestTrackingIdFormat跟蹤號匹配正則^[A-Z]{2}-\d-\d$TestTrackingIdUniqueness50 次生成至少得到 2 個不同跟蹤號TestCreateQuoteFromFloat浮點金額 →{Dollars, Cents}轉換0.0→0.0、8.99→8.99、100.01→100.1 等表驅動用例TestCreateQuoteFromCount數量 0 → 零報價數量非 0 → 非零報價TestQuoteStringQuote{8, 99}的字符串化為$8.99核心業務實現解析報價邏輯按商品數量定價GetQuote 的實現 首先累加購物車中所有商品的Quantity再交給 quote.go 中的純函數計算func CreateQuoteFromCount(count int) Quote { if count 0 { return CreateQuoteFromFloat(0) } return CreateQuoteFromFloat(8.99) // 固定運費 8.99 美元 }func CreateQuoteFromFloat(value float64) Quote { units, fraction : math.Modf(value) return Quote{ uint32(units), uint32(math.Trunc(fraction * 100)), } }定價策略非常直白購物車為空報價 0否則一律 $8.99 固定運費——這正是演示項目中印象式impression of運費計算的體現。最終金額通過MoneyUSD 幣種 Units/Nanos 字段編碼進GetQuoteResponse返回由 checkoutservice 接收后再交給 currencyservice 做匯率換算見 checkoutservice 的 quoteShipping 調用。跟蹤號生成確定性 隨機性組合ShipOrder 的實現 用收貨地址拼接出 salt再調用 tracker.go 中的CreateTrackingIdfunc CreateTrackingId(salt string) string { return fmt.Sprintf(%c%c-%d%s-%d%s, getRandomLetterCode(), // 2 個大寫字母 getRandomLetterCode(), len(salt), // 地址長度 getRandomNumber(3), // 3 位隨機數字 len(salt)/2, // 地址長度的一半 getRandomNumber(7), // 7 位隨機數字 ) }生成的跟蹤號格式如XX-LL-NNN-LLLLLL-NNNNNNN其長度恒為 18 字符與測試TestShipOrder斷言一致。getRandomLetterCode()通過65 rand.Intn(25)生成大寫字母 A–Z 的碼點getRandomNumber(digits)逐位拼接指定位數的隨機數字串。由于摻入了隨機部分即使 salt 相同也能產生足夠多樣的跟蹤號TestTrackingIdUniqueness驗證了這一性質滿足notional lookup of shipment delivery status的演示需求。服務端裝配gRPC、健康檢查與可觀測性main.go 的啟動流程體現了本倉庫 Go 微服務的通用范式port : defaultPort // 50051 if value, ok : os.LookupEnv(PORT); ok { port value } lis, err : net.Listen(tcp, port) srv : grpc.NewServer() svc : server{} pb.RegisterShippingServiceServer(srv, svc) healthcheck : health.NewServer() healthpb.RegisterHealthServer(srv, healthcheck) reflection.Register(srv) srv.Serve(lis)幾個值得注意的工程點端口可配默認監聽50051可通過環境變量PORT覆蓋gRPC 健康檢查注冊了grpc_health_v1服務Kubernetes 的 readiness/liveness probe 都基于此見下文清單gRPC reflection注冊 reflection 服務便于 grpcurl 等工具在線探測服務方法可觀測性開關通過DISABLE_TRACING、DISABLE_PROFILER、DISABLE_STATS三個環境變量控制 tracingOpenTelemetry 待實現見代碼 TODO、Stackdriver profilerinitProfiling 會帶退避重試最多 3 次與 stats 的啟停JSON 結構化日志logrus 配置為 JSONFormatter輸出字段映射為timestamp/severity/message便于接入云日志系統。Kubernetes 部署形態kubernetes-manifests/shippingservice.yaml 中定義了三種資源kustomize 目錄 kustomize/base/shippingservice.yaml 與 helm-chart 模板 helm-chart/templates/shippingservice.yaml 提供等價聲明可任選一種部署方式Deployment單容器server鏡像shippingservice暴露 50051 端口通過環境變量注入PORT50051與DISABLE_PROFILER1在集群中關閉云 profilerProbesreadiness 與 liveness 均使用 gRPC 探針指向 50051 端口periodSeconds: 5資源配額requests cpu 100m / memory 64Milimits cpu 200m / memory 128Mi安全上下文runAsNonRoot: true、fsGroup: 1000容器內allowPrivilegeEscalation: false、drop: [ALL]、readOnlyRootFilesystem: trueServiceClusterIP 類型port 50051 → targetPort 50051供集群內其他服務尤其是 checkoutservice通過shippingservice:50051訪問ServiceAccount名為shippingservice對應 Deployment 中的serviceAccountName。checkoutservice 側通過環境變量SHIPPING_SERVICE_ADDR建立 gRPC 連接checkoutservice/main.go隨后依次調用GetQuoteL314與ShipOrderL387把報價與跟蹤號組裝進最終下單響應。常見問題與注意事項舊命令 vs 新依賴體系README 中的dep ensure --vendor-only屬于歷史工作流當前倉庫使用 Go modules請以go mod download為準兩者不可混用。端口沖突本機同時啟動多個 microservices-demo 服務時若 50051 被占用可通過PORT環境變量覆蓋但需同步修改依賴方checkoutservice 的SHIPPING_SERVICE_ADDR的地址。profiler 依賴 GCP非 GCP 環境會走重試退避最終放棄此時建議設置DISABLE_PROFILER1K8s 清單中已默認關閉。浮點金額報價結果一律以Money{currency_code, units, nanos}傳遞請勿直接以 float 形式跨服務傳遞金額避免精度丟失。跟蹤號僅作演示ShipOrder并不觸發真實物流動作返回的 tracking ID 僅用于前端展示與狀態查詢的印象與倉庫產品需求文檔中模擬配送流程的定位一致。小結Shippingservice 以約 200 行 Go 代碼 9 組單元測試完成了運費報價、跟蹤號生成、gRPC 裝配與健康檢查等微服務骨架的全部要素是學習如何在 microservices-demo 中編寫一個標準 Go gRPC 服務的絕佳范本。閱讀源碼時建議按此順序先看 protos/demo.proto 的接口契約再對照 quote.go 與 tracker.go 的純函數邏輯最后結合 main.go 與 shippingservice_test.go 理解裝配與驗證方式即可快速上手并類比到倉庫內其他 Go 微服務如 productcatalogservice、checkoutservice。【免費下載鏈接】microservices-demoSample cloud-first application with 10 microservices showcasing Kubernetes, Istio, and gRPC.項目地址: https://gitcode.com/GitHub_Trending/mi/microservices-demo創作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考