韶关市网站建设_网站建设公司_Java_seo优化
2026/1/5 10:30:09 网站建设 项目流程

一、先白话白话

昨天咱把user-serviceorder-service都登记到Nacos了,就像俩人都在社区服务中心登了记。但是光登记不中啊,得能互相找人互相帮忙

零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目

资源获取:关注公众号: 小坏说Java ,获取本文所有示例代码、配置模板及导出工具。

实际场景:

order-service(订单服务)想知道是哪个用户下单了,得问user-service(用户服务):

  • 以前:order-service得知道user-service住哪(IP:端口),自己写HTTP请求
  • 现在:order-service直接喊一声“user-service!”,Nacos负责找地址,OpenFeign负责传话

OpenFeign就是个翻译官+跑腿的

  1. 你写个接口,说想调user-service的某个方法
  2. OpenFeign帮你生成具体实现
  3. 帮你找到user-service在哪
  4. 帮你发请求、收响应
  5. 出问题了还帮你重试

二、为啥不用原生的RestTemplate?

零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目

资源获取:关注公众号: 小坏说Java ,获取本文所有示例代码、配置模板及导出工具。

RestTemplate也能调用,但是:

// RestTemplate方式(老式写法)Stringurl="http://localhost:8081/user/"+userId;Useruser=restTemplate.getForObject(url,User.class);

问题

  1. 得自己拼URL,麻烦!
  2. 得自己处理异常,麻烦!
  3. 负载均衡得自己写,麻烦!
  4. 改个地址得到处找,麻烦!

OpenFeign写法:

// Feign方式(新式写法)Useruser=userClient.getUserById(userId);

优点

  1. 跟调本地方法一样简单
  2. 自动负载均衡
  3. 自动重试
  4. 配置统一管理

三、开整!让order-service调user-service

零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目

资源获取:关注公众号: 小坏说Java ,获取本文所有示例代码、配置模板及导出工具。

准备工作

1. 先完善user-service

user-service里加个正经接口:

// User.java(先简单点,明天连数据库)publicclassUser{privateIntegerid;privateStringname;privateStringaddress;privateStringfavoriteFood;// 构造方法、getter、setter省略...}// UserController.java@RestController@RequestMapping("/user")publicclassUserController{// 模拟数据库privateMap<Integer,User>userMap=newHashMap<>();publicUserController(){// 初始化几个用户userMap.put(1,newUser(1,"张三","郑州","烩面"));userMap.put(2,newUser(2,"李四","洛阳","水席"));userMap.put(3,newUser(3,"王五","开封","灌汤包"));}@GetMapping("/{id}")publicUsergetUserById(@PathVariableIntegerid){Useruser=userMap.get(id);if(user==null){thrownewRuntimeException("用户不存在!");}returnuser;}@GetMapping("/test")publicStringtest(){return"user-service正常工作中...";}}

启动user-service,访问http://localhost:8081/user/1看看:

{"id":1,"name":"张三","address":"郑州","favoriteFood":"烩面"}

中了!

步骤1:给order-service加OpenFeign依赖

order-servicepom.xml里加:

<!-- OpenFeign --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!-- 负载均衡(必须加!) --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency>

步骤2:启动类加注解

@SpringBootApplication@EnableDiscoveryClient@EnableFeignClients// 这个注解是重点!开启FeignpublicclassOrderServiceApplication{publicstaticvoidmain(String[]args){SpringApplication.run(OrderServiceApplication.class,args);}}

步骤3:创建Feign客户端接口

零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目

资源获取:关注公众号: 小坏说Java ,获取本文所有示例代码、配置模板及导出工具。

新建feign包,里面创建UserClient.java

@FeignClient(name="user-service")// 指定要调用的服务名publicinterfaceUserClient{/** * 调用user-service的GET /user/{id}接口 * 跟写本地Controller一样,只是注解变@GetMapping */@GetMapping("/user/{id}")UsergetUserById(@PathVariable("id")Integerid);/** * 调用user-service的GET /user/test接口 */@GetMapping("/user/test")Stringtest();}

注意

  1. @FeignClient(name = "user-service")里的name必须跟Nacos里注册的服务名一致
  2. 方法上的注解(@GetMapping)要跟被调用方一致
  3. 方法签名(参数、返回值)也要一致

步骤4:写个Controller测试

order-service里:

@RestController@RequestMapping("/order")publicclassOrderController{@AutowiredprivateUserClientuserClient;// 注入Feign客户端/** * 根据订单ID获取订单信息,顺便获取用户信息 */@GetMapping("/{orderId}")publicMap<String,Object>getOrderWithUser(@PathVariableIntegerorderId){Map<String,Object>result=newHashMap<>();// 1. 模拟订单信息result.put("orderId",orderId);result.put("orderName","河南特产大礼包");result.put("status","已发货");result.put("address","河南省郑州市金水区");// 2. 调用user-service获取用户信息(关键!)// 假设订单1对应用户1,订单2对应用户2...IntegeruserId=orderId;try{Useruser=userClient.getUserById(userId);result.put("user",user);}catch(Exceptione){result.put("user","获取用户信息失败:"+e.getMessage());}returnresult;}/** * 测试user-service是否正常 */@GetMapping("/test/user")publicStringtestUserService(){returnuserClient.test();}}

步骤5:测试一下

  1. 启动所有服务:

    • Nacos(8848端口)
    • user-service(8081端口)
    • order-service(8082端口)
  2. 访问http://localhost:8082/order/test/user
    应该返回:user-service正常工作中...

  3. 访问http://localhost:8082/order/1
    应该返回:

{"orderId":1,"orderName":"河南特产大礼包","status":"已发货","address":"河南省郑州市金水区","user":{"id":1,"name":"张三","address":"郑州","favoriteFood":"烩面"}}

得劲!order-service成功调用了user-service!

四、Feign高级配置(稍微了解一下)

1. 超时配置(默认等1秒,太短)

order-serviceapplication.yml里:

feign:client:config:default:# 全局配置connect-timeout:5000# 连接超时5秒read-timeout:5000# 读取超时5秒user-service:# 针对user-service的配置connect-timeout:3000read-timeout:3000# 或者用ribbon(Feign底层用ribbon)ribbon:ConnectTimeout:5000ReadTimeout:5000

2. 开启日志(调试时用)

零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目

资源获取:关注公众号: 小坏说Java ,获取本文所有示例代码、配置模板及导出工具。

logging:level:com.example.order.feign.UserClient:DEBUG# 你的Feign客户端包名

在配置类里:

@ConfigurationpublicclassFeignConfig{@BeanpublicLogger.LevelfeignLoggerLevel(){returnLogger.Level.FULL;// 详细日志}}

日志会显示:

[UserClient#getUserById] ---> GET http://user-service/user/1 HTTP/1.1 [UserClient#getUserById] <--- HTTP/1.1 200 OK (15ms)

3. 失败重试

spring:cloud:loadbalancer:retry:enabled:true# 开启重试

五、负载均衡(Load Balancing)

啥是负载均衡?

假设user-service有3个实例:

  • 实例1:8081端口
  • 实例2:8083端口
  • 实例3:8084端口

OpenFeign会自动把请求均匀分配给这三个实例,不会让一个实例累死。

测试负载均衡

零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目

资源获取:关注公众号: 小坏说Java ,获取本文所有示例代码、配置模板及导出工具。

  1. 启动多个user-service实例:

    • 改端口号启动就行
    • IDEA里复制配置,改server.port
    • 启动8081、8083、8084三个实例
  2. 在Nacos里能看到3个实例

  3. 多次访问http://localhost:8082/order/test/user

    • 看每个实例的控制台日志
    • 请求会被均匀分配

得劲!不用改代码,自动负载均衡!

六、实际开发中的最佳实践

1. 统一返回结果

// 通用的返回类publicclassResult<T>{privateIntegercode;privateStringmessage;privateTdata;// ...}// Feign客户端返回Result@FeignClient(name="user-service")publicinterfaceUserClient{@GetMapping("/user/{id}")Result<User>getUserById(@PathVariableIntegerid);}

2. 统一异常处理

// 创建Fallback类(服务降级)@ComponentpublicclassUserClientFallbackimplementsUserClient{@OverridepublicUsergetUserById(Integerid){// user-service挂了,返回兜底数据returnnewUser(id,"默认用户","河南","胡辣汤");}@OverridepublicStringtest(){return"user-service暂时不可用";}}// Feign客户端指定Fallback@FeignClient(name="user-service",fallback=UserClientFallback.class)publicinterfaceUserClient{// ...}

3. 放在公共模块

把Feign客户端接口放到一个公共模块,谁想用谁引用。

七、今儿个总结

零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目

资源获取:关注公众号: 小坏说Java ,获取本文所有示例代码、配置模板及导出工具。

学会了啥?

  1. ✅ OpenFeign是干啥的(翻译官+跑腿的)
  2. ✅ 创建Feign客户端接口(@FeignClient
  3. ✅ 调用远程服务(跟调本地方法一样)
  4. ✅ 配置超时、日志
  5. ✅ 负载均衡(自动的!)

关键点

  1. 服务名要对@FeignClient(name = "user-service")里的name必须跟Nacos里一样
  2. 注解要一致:方法上的注解要跟被调用方一致
  3. 依赖要全:OpenFeign + LoadBalancer
  4. 启动类要加注解@EnableFeignClients

八、常见问题

1. 报错:UnknownHostException: user-service

  • 检查Nacos里user-service注册上了没
  • 检查@FeignClient的name写对没
  • 检查order-service连上Nacos没

2. 报错:Connection refused

  • 检查user-service启动了没
  • 检查端口号对不
  • 等一会儿再试(服务刚启动可能需要时间)

3. 调用返回null

  • 检查返回值类型对不
  • 检查被调用方接口路径对不
  • 开日志看看具体请求和响应

4. 超时问题

  • 默认1秒太短,调大点
  • 网络不好也会超时

九、明儿个学啥?

零基础全栈开发Java微服务版本实战-后端-前端-运维-实战企业级三个实战项目

资源获取:关注公众号: 小坏说Java ,获取本文所有示例代码、配置模板及导出工具。

明天咱学服务熔断降级

  • user-service挂了咋办?
  • order-service一直等,等到天荒地老?
  • Sentinel做熔断降级
  • 跟电路保险丝一样,过载就跳闸!

明天咱让服务更坚强,一个挂了不影响别的!🚀

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询