尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

microservices-demo Ad Service 深度解析:Java/gRPC 广告服务的构建、镜像化与部署实践

microservices-demo Ad Service 深度解析:Java/gRPC 广告服务的构建、镜像化与部署实践 microservices-demo Ad Service 深度解析Java/gRPC 广告服务的构建、镜像化与部署实践【免费下载链接】microservices-demoSample cloud-first application with 10 microservices showcasing Kubernetes, Istio, and gRPC.项目地址: https://gitcode.com/GitHub_Trending/mi/microservices-demo导读Ad Service广告服务是 GoogleCloudPlatform/microservices-demo本项目仓库根目录即该示例项目中负责广告分发的核心微服务它根据前端页面传入的上下文关键词context keys返回匹配的广告若没有提供上下文则返回随机广告。本文以 src/adservice/README.md 为主线结合 AdService.java、build.gradle、Dockerfile 与 kubernetes-manifests/adservice.yaml 等仓库资源完整讲解该服务的功能逻辑、本地构建、Docker 镜像制作以及 Kubernetes 部署验证读完即可独立完成该服务的编译、运行与调试。一、服务定位与核心功能根据 README.md 的定义Ad Service 基于上下文关键词context keys提供广告如果请求中没有提供任何上下文关键词则返回随机广告。这一行为在 protos/demo.proto 中定义了对应的 gRPC 契约service AdService { rpc GetAds(AdRequest) returns (AdResponse) {} } message AdRequest { // List of important key words from the current page describing the context. repeated string context_keys 1; } message AdResponse { repeated Ad ads 1; } message Ad { // url to redirect to when an ad is clicked. string redirect_url 1; // short advertisement text to display. string text 2; }接口语义非常清晰GetAds接收一个AdRequest其中context_keys是描述当前页面语义的关键词列表返回AdResponse内含若干条Ad每条Ad由redirect_url点击广告后跳转的商品页和text展示给用户的广告文案组成。从 AdService.java 的AdServiceImpl.getAds实现可以看出完整的决策流程若req.getContextKeysCount() 0则遍历每个上下文关键词调用getAdsByCategory(category)从内存中的广告映射表取对应分类的广告若请求没有上下文关键词直接走getRandomAds()返回随机广告兜底逻辑即使提供了关键词但该分类下没有广告allAds.isEmpty()也会回退为随机广告保证调用方始终能拿到可展示的广告内容。这种上下文优先、随机兜底的设计保证了在商品目录缺失、分类命名变化等场景下广告位永远不会空置是演示微服务中典型的容错式降级实现。二、广告数据模型分类到商品的映射广告素材并非从外部数据库读取而是在服务启动时以静态方式构建在内存中。AdService.java 中的createAdsMap()使用 Guava 的ImmutableListMultimap将分类 → 广告列表固化上下文分类广告商品redirect_url广告文案clothing服饰Tank top背心/product/66VCHSJNUPTank top for sale. 20% off.accessories配饰Watch手表/product/1YMWWN1N4OWatch for sale. Buy one, get second kit for freefootwear鞋履Loafers乐福鞋/product/L9ECAV7KIMLoafers for sale. Buy one, get second one for freehair美发Hairdryer吹风机/product/2ZYFJ3GM2NHairdryer for sale. 50% off.decor家居装饰Candle holder烛台/product/0PUK6V6EV0Candle holder for sale. 30% off.kitchen厨房Bamboo glass jar竹盖玻璃罐/product/9SIQT8TOJOBamboo glass jar for sale. 10% off.kitchen厨房Mug马克杯/product/6E92ZMYYFZMug for sale. Buy two, get third one for free其中redirect_url指向的是 src/frontend 渲染的商品详情页路径商品 ID如66VCHSJNUP与 productcatalogservice 的 products.json 中的商品 ID 一一对应构成了广告点击到商品落地页的完整链路。随机广告逻辑见 getRandomAds()单次最多返回MAX_ADS_TO_SERVE 2条广告从全量广告池中通过java.util.Random随机抽取这也是 README 中返回随机广告一句的实现细节所在。三、本地构建基于 Gradle Wrapper3.1 一键构建./gradlew installDistREADME 明确指出Ad Service 使用 gradlewGradle Wrapper进行 compile / install / distributeWrapper 已随源码一起分发因此本地无需预装 Gradle。执行./gradlew installDist该命令执行后会在src/adservice/build/install/hipstershop/bin/下生成可执行脚本AdService以及配套的AdServiceClient即为该服务的可运行产物。从 build.gradle 可以看到支撑该命令的关键配置项目名由 settings.gradle 定义为hipstershop因此分发目录为build/install/hipstershopapplication插件配合adService、adServiceClient两个CreateStartScripts任务分别将主类hipstershop.AdService与hipstershop.AdServiceClient打包为可执行启动脚本见 build.gradle生成的脚本会装载build/install/hipstershop/lib下的全部依赖 JAR直接运行./build/install/hipstershop/bin/AdService即可启动 gRPC 服务默认监听PORT环境变量缺省为9555见 AdService.java。构建产物目录结构可预期为build/install/hipstershop/ ├── bin/ │ ├── AdService # 服务端启动脚本 │ └── AdServiceClient # 测试用客户端脚本 └── lib/ # 依赖 JAR 包集合3.2 Wrapper 版本信息与升级方式Wrapper 自身由gradle/wrapper/目录下的gradle-wrapper.jar、gradle-wrapper.properties组成。当前仓库使用的 Gradle 发行版定义在 gradle/wrapper/gradle-wrapper.propertiesdistributionBaseGRADLE_USER_HOME distributionPathwrapper/dists distributionUrlhttps\://services.gradle.org/distributions/gradle-8.14.5-bin.zip networkTimeout10000 validateDistributionUrltrue zipStoreBaseGRADLE_USER_HOME zipStorePathwrapper/dists关键点distributionUrl指向gradle-8.14.5-bin.zip首次执行 gradlew 时会自动下载该发行版networkTimeout10000毫秒控制下载超时网络较慢的环境可按需调大不需要手动安装 Gradle这也是 Wrapper 的核心价值——团队成员与 CI 构建环境使用完全一致的构建版本。如需升级 Gradle 版本README 给出的官方命令为./gradlew wrapper --gradle-version new-version例如升级到 8.15 可执行./gradlew wrapper --gradle-version 8.15。该命令会重写gradle-wrapper.properties中的distributionUrl并同步更新gradle-wrapper.jar之后所有开发者再运行./gradlew就会使用新版本。注意升级前建议确认 build.gradle 中声明的 Java 21 兼容性sourceCompatibility/targetCompatibility均为JavaVersion.VERSION_21与所用 Gradle 插件版本protobuf 0.10.0、google-java-format 0.9是否被目标 Gradle 版本支持。3.3 构建依赖与编译要点build.gradle 中值得注意的实现细节gRPC / Protobuf 依赖io.grpc:grpc-protobuf、grpc-stub、grpc-netty、grpc-services、grpc-census均锁定版本1.83.1protoc与protobuf-java锁定4.35.1protoc-gen-grpc-java与 grpc 同版本保证生成代码与运行时完全兼容protobuf 插件通过com.google.protobuf插件在编译期从 src/main/proto/demo.proto 生成 Java 与 gRPC 桩代码生成目录build/generated/source/proto/main/java/hipstershop与.../grpc/hipstershop被显式加入sourceSets见 build.gradle所以仓库不提交生成的桩代码而是构建时动态生成downloadRepos任务将compileClasspath拷贝到build/output/lib配合-Pspeed属性可实现离线编译implementation fileTree(dir: offlineCompile, ...)该机制被 Dockerfile 用来分层缓存依赖显著加快镜像重复构建速度proto 同步脚本genproto.sh 会把仓库根目录的 protos/demo.proto 复制到src/main/proto确保 Ad Service 编译使用的 proto 与整个项目保持单源一致——Docker 构建前会执行该脚本。四、构建 Docker 镜像4.1 基本命令README 给出的镜像构建方式是在src/adservice/目录下执行docker build ./最终镜像默认 tag 为空实际使用时建议显式打 tag例如docker build -t adservice:latest ./注意docker build的构建上下文为src/adservice/目录本身因此 Dockerfile 中引用的相对路径如build.gradle、gradlew、gradle/均相对于该目录。4.2 Dockerfile 多阶段构建解析Dockerfile 采用标准的多阶段构建multi-stage build兼顾构建速度与运行镜像体积阶段一builder构建镜像FROM --platform$BUILDPLATFORM eclipse-temurin:24.0.2_12-jdk-noblesha256:... AS builder WORKDIR /app COPY [build.gradle, gradlew, ./] COPY gradle gradle RUN chmod x gradlew RUN ./gradlew downloadRepos COPY . . RUN chmod x gradlew RUN ./gradlew installDist先只复制build.gradle、gradlew与gradle/执行./gradlew downloadRepos提前缓存依赖层——只要build.gradle未变化该层即可复用 Docker 缓存再复制全部源码并执行./gradlew installDist产出可分发的应用目录基础镜像固定到 digestsha256:...级别保证可复现构建。阶段二运行镜像FROM eclipse-temurin:25.0.3_9-jre-alpinesha256:... WORKDIR /app COPY --frombuilder /app . EXPOSE 9555 ENTRYPOINT [/app/build/install/hipstershop/bin/AdService]仅使用精简的 JREAlpine镜像体积远小于 JDKEXPOSE 9555声明服务端口与 AdService.java 读取的默认端口一致ENTRYPOINT直接执行上一步installDist生成的AdService启动脚本。此外Dockerfile 中被注释掉的 Stackdriver Profiler Java agent 下载步骤# TODO: ...说明该项目曾计划集成 Java Profiler当前仓库中该能力处于 TODO 状态不作为现网功能宣传。五、在 Kubernetes 中部署manifest 视角构建出镜像后即可按仓库提供的 kubernetes-manifests/adservice.yaml 部署到集群。该文件一次声明了三种资源Deploymentdeployment 关键字段容器端口9555并通过环境变量PORT9555显式传给服务与代码默认值保持一致探针使用 gRPC 健康检查readinessProbe与livenessProbe均为initialDelaySeconds: 20、periodSeconds: 15的 gRPC 探测对应 AdService.java 中注册的HealthStatusManager健康服务——服务启动并注册为SERVING后探针才能通过资源配额requestscpu: 200m / memory: 180Milimitscpu: 300m / memory: 300Mi安全加固runAsNonRoot: true、runAsUser/Group: 1000、readOnlyRootFilesystem: true、drop ALL capabilities禁止提权体现生产级最小权限原则。Service类型ClusterIP端口9555仅集群内部可访问广告服务由前端frontend通过 gRPC 调用无需对外暴露。ServiceAccount名为adservice供 Deployment 使用配合网络策略或 RBAC 实现最小权限。此外仓库的 helm-chart/templates/adservice.yaml、kustomize/base/adservice.yaml 与 kustomize/components/network-policies/network-policy-adservice.yaml 还提供了 Helm、Kustomize 与网络策略等不同交付方式下的等价编排可在实际部署时按需选择。六、本地验证用 AdServiceClient 请求广告仓库同时提供了测试用 gRPC 客户端 AdServiceClient.java便于在本地验证服务行为。先启动服务端./gradlew installDist ./build/install/hipstershop/bin/AdService启动日志会输出Ad Service started, listening on 9555。随后另开终端运行客户端./build/install/hipstershop/bin/AdServiceClient客户端默认行为见 AdServiceClient.java 的main第 1 个参数上下文关键词默认camera第 2 个参数服务端 host默认localhost第 3 个参数端口默认9555。因此以下命令等价于默认调用./build/install/hipstershop/bin/AdServiceClient camera localhost 9555客户端会构建AdRequest并调用阻塞式 stubgetAds然后把每条广告的text打印到日志Ads: ...。由于广告映射表中没有camera分类此时可以直观验证 README 描述的兜底逻辑服务端因getAdsByCategory(camera)返回空集合而回退到getRandomAds()客户端仍然能收到 2 条随机广告。若换成clothing、kitchen等已存在的分类则会返回该分类下的定向广告。七、总结Ad Service 虽然业务简单却完整展现了本项目微服务的典型工程模式契约先行gRPC/Protobuf 契约统一维护在根目录 protos/demo.proto通过 genproto.sh 与 Gradle protobuf 插件在各服务内生成代码零依赖构建Gradle Wrapper 固化构建版本./gradlew installDist一键产出可执行脚本升级只需./gradlew wrapper --gradle-version new-version镜像可复现多阶段 Docker 构建 digest 固定基础镜像 downloadRepos分层缓存既快又稳生产可部署Kubernetes manifest 提供 gRPC 健康探针、资源配额与最小权限安全上下文上下文优先、随机兜底即使关键词无法命中广告分类也不会让广告位空置。对照 README.md 的三组核心命令——./gradlew installDist、./gradlew wrapper --gradle-version new-version、docker build ./——读者现在可以顺藤摸瓜从源码、构建脚本到部署清单完整复现该服务的全生命周期。【免费下载链接】microservices-demoSample cloud-first application with 10 microservices showcasing Kubernetes, Istio, and gRPC.项目地址: https://gitcode.com/GitHub_Trending/mi/microservices-demo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表