Spring Cloud构建微服务架构:服务消费者

Spring Cloud构建微服务架构:服务消费者 选型方式类型协议是否声明式负载均衡注册中心集成适用场景LoadBalancerClient底层 APIHTTP❌✅手动选实例✅需精细控制选例逻辑RestTemplateRibbon模板类HTTP❌✅自动✅简单 HTTP 调用已不推荐新项目使用FeignClient声明式客户端HTTP✅✅自动✅接口化开发、HTTP 服务间调用DubboReferenceRPC 代理TCP二进制✅✅自动✅高性能、低延迟、强一致内部调用✅一句话选型建议写 REST API → 选FeignClient写核心链路/高并发内部服务 → 选DubboReference学原理或特殊调度 → 用LoadBalancerClientRestTemplate Ribbon仅用于兼容老系统。 使用LoadBalancerClient1、服务端和客户端配置--✅**服务端application.yml**以user-service 为例spring:application:name:user-serviceserver:port:8081# 若对接 Eureka推荐eureka:client:service-url:defaultZone:http://localhost:8761/eureka/--✅**客户端application.yml**调用方spring:application:name:order-serviceserver:port:8080# 同样注册到同一注册中心如 Eureka才能发现 user-serviceeureka:client:service-url:defaultZone:http://localhost:8761/eureka/2、服务端代码RestControllerRequestMapping(/api)publicclassUserController{GetMapping(/user/{id})publicMapString,ObjectgetUser(PathVariableLongid){returnMap.of(id,id,name,Charlie,age,28,timestamp,System.currentTimeMillis());}}3、客户端代码ServicepublicclassUserService{privatefinalLoadBalancerClientloadBalancerClient;privatefinalRestTemplaterestTemplate;publicUserService(LoadBalancerClientloadBalancerClient,RestTemplaterestTemplate){this.loadBalancerClientloadBalancerClient;this.restTemplaterestTemplate;}publicMapString,ObjectfetchUser(Longid){// ① 通过服务名获取一个可用实例ServiceInstanceinstanceloadBalancerClient.choose(user-service);if(instancenull){thrownewIllegalStateException(No instances available for user-service);}// ② 拼接完整请求 URLhttp://host:port/pathStringurlString.format(http://%s:%d/api/user/%d,instance.getHost(),instance.getPort(),id);// ③ 发起同步 HTTP GET 请求returnrestTemplate.getForObject(url,Map.class);}}ConfigurationpublicclassRestTemplateConfig{BeanpublicRestTemplaterestTemplate(){returnnewRestTemplate();}}使用RestTemplateRibbon版1、服务端和客户端配置--✅**服务端application.yml**user-service注册到Eurekaspring:application:name:user-serviceserver:port:8081eureka:client:service-url:defaultZone:http://localhost:8761/eureka/instance:prefer-ip-address:true--✅**客户端application.yml**d-eureka-consumer-ribbonspring:application:name:d-eureka-consumer-ribbonserver:port:8080eureka:client:service-url:defaultZone:http://localhost:8761/eureka/2、服务端代码RestControllerRequestMapping(/api)publicclassUserController{GetMapping(/user/{id})publicMapString,ObjectgetUser(PathVariableLongid){returnMap.of(id,id,name,David,age,32,from,d-eureka-consumer-ribbon demo);}}3、客户端代码 原理说明LoadBalanced使RestTemplate被RibbonInterceptor拦截将http://user-service/...中的user-service解析为 Eureka 中注册的多个实例并按IRule如RoundRobinRule选择一个发起真实 HTTP 请求。ConfigurationpublicclassRestTemplateConfig{BeanLoadBalanced// 关键开启 Ribbon 负载均衡拦截publicRestTemplaterestTemplate(){returnnewRestTemplate();}}ServicepublicclassUserService{privatefinalRestTemplaterestTemplate;publicUserService(RestTemplaterestTemplate){this.restTemplaterestTemplate;}publicMapString,ObjectfetchUser(Longid){// ✅ 直接使用服务名 user-service非 IPRibbon 自动解析并负载均衡Stringurlhttp://user-service/api/user/{id};returnrestTemplate.getForObject(url,Map.class,id);}}RestControllerRequestMapping(/consumer)publicclassConsumerController{privatefinalUserServiceuserService;publicConsumerController(UserServiceuserService){this.userServiceuserService;}GetMapping(/user/{id})publicMapString,ObjectgetUser(PathVariableLongid){returnuserService.fetchUser(id);}}使用FeignClientFeign版1、服务端和客户端配置--✅**服务端application.yml**同前user-servicespring:application:name:user-serviceserver:port:8081eureka:client:service-url:defaultZone:http://localhost:8761/eureka/instance:prefer-ip-address:true--✅**客户端application.yml**d-eureka-consumer-feignspring:application:name:d-eureka-consumer-feignserver:port:8080eureka:client:service-url:defaultZone:http://localhost:8761/eureka/2、服务端代码RestControllerRequestMapping(/api)publicclassUserController{GetMapping(/user/{id})publicMapString,ObjectgetUser(PathVariableLongid){returnMap.of(id,id,name,Eve,age,27,from,d-eureka-consumer-feign demo);}}3、客户端代码 原理说明FeignClient接口在运行时被动态代理Feign 自动整合 Ribbon旧版或 Spring Cloud LoadBalancer新版实现服务发现 负载均衡并通过Contract解析GetMapping、PathVariable等注解生成 HTTP 请求。SpringBootApplicationEnableFeignClients// ← 必须添加扫描 FeignClient 接口EnableDiscoveryClientpublicclassDEurekaConsumerFeignApplication{publicstaticvoidmain(String[]args){SpringApplication.run(DEurekaConsumerFeignApplication.class,args);}}FeignClient(nameuser-service)// ← 服务名自动从 Eureka 查找publicinterfaceUserClient{GetMapping(/api/user/{id})MapString,ObjectgetUser(PathVariable(id)Longid);}ServicepublicclassUserService{privatefinalUserClientuserClient;publicUserService(UserClientuserClient){this.userClientuserClient;}publicMapString,ObjectfetchUser(Longid){returnuserClient.getUser(id);// ← 一行代码完成远程调用}}RestControllerRequestMapping(/consumer)publicclassConsumerController{privatefinalUserServiceuserService;publicConsumerController(UserServiceuserService){this.userServiceuserService;}GetMapping(/user/{id})publicMapString,ObjectgetUser(PathVariableLongid){returnuserService.fetchUser(id);}}使用DubboReferenceDubbo版1、服务端和客户端配置✅**服务端application.yml**user-service-dubbo-nacosspring:application:name:user-service-dubbo-nacoscloud:nacos:discovery:server-addr:localhost:8848# ← Nacos 服务地址dubbo:protocol:name:dubboport:20880registry:address:nacos://localhost:8848# ← 关键Nacos 协议注册中心scan:base-packages:com.example.demo.service.implserver:port:8081--✅**客户端application.yml**dubbo-consumer-nacosspring:application:name:dubbo-consumer-nacoscloud:nacos:discovery:server-addr:localhost:8848dubbo:registry:address:nacos://localhost:8848# ← 同样使用 nacos:// 协议server:port:8080✅ 前提本地启动 Nacos Serverhttps://nacos.io默认地址http://localhost:8848账号密码均为nacos。2、服务端代码--✅**服务接口共享**// com.example.demo.service.UserService.javapublicinterfaceUserService{MapString,ObjectgetUser(Longid);}--✅**服务实现类DubboService自动注册到Nacos**importorg.apache.dubbo.config.annotation.DubboService;importorg.springframework.stereotype.Service;DubboService// ← 自动向 Nacos 注册为 dubbo 服务含接口名、版本、分组等元数据publicclassUserServiceImplimplementsUserService{OverridepublicMapString,ObjectgetUser(Longid){returnMap.of(id,id,name,Grace,age,29,registry,nacos,timestamp,System.currentTimeMillis());}}✅ 启动后服务将注册到 Nacos 控制台【服务管理】→providers:com.example.demo.service.UserService支持健康检查与元数据展示。3、客户端代码--✅**消费方注入DubboReference自动从Nacos发现**importorg.apache.dubbo.config.annotation.DubboReference;importorg.springframework.stereotype.Service;ServicepublicclassUserService{// ← 关键Dubbo 自动从 Nacos 拉取 provider 列表创建 RPC 代理// 如果 不能直接引入需要定义完全一样的DubboReferenceprivatecom.example.demo.service.UserServiceuserService;publicMapString,ObjectfetchUser(Longid){returnuserService.getUser(id);// ← 无感知远程调用非 HTTP是高性能 RPC}}--✅**Controller示例可选**RestControllerRequestMapping(/consumer)publicclassConsumerController{privatefinalUserServiceuserService;publicConsumerController(UserServiceuserService){this.userServiceuserService;}GetMapping(/user/{id})publicMapString,ObjectgetUser(PathVariableLongid){returnuserService.fetchUser(id);}} 补充说明Dubbo 通过NacosServiceDiscovery与 Nacos 交互服务发现采用长轮询 缓存机制支持秒级故障剔除默认负载均衡策略为RandomLoadBalance。