SpringCloud:OpenFeign快速实现

前言

SpringCloud微服务框架中,我们实现了服务之间的低耦合性,将多个服务的单机系统拆分成多个独立的微服务。

在微服务中,我们将单机架构的服务拆分成多个单独的服务模块,但不可避免的,微服务之间并不是完全独立,隔离开来的,有时服务之间也需要互相进行调用,但我们如何调用呢?


远程调用的概念

以订单服务+商品服务为例,单机架构的商城服务将订单查询功能与商品信息查询功能放在一个项目中,共用一个数据库和配置文件,同时,订单服务想通过商品id查询商品信息时,可以直接调用商品服务的service层,虽然操作简单,但是两个服务间的耦合性太高,代码之间的联系千丝万缕,假若我们的某个服务出错,就会导致整个商城服务崩溃,因此我们需要将这个大服务拆分成小的服务,当订单服务需要调用商品服务时,通过远程调用,根据商品服务提供的地址查询信息。


传统远程调用缺点

  • 人工运维成本高,效率低
  • 稳定性差,代码修改频繁
  • 代码耦合性高,无法做到真正的解耦

还是以订单服务调用商品服务为例,传统的远程调用是直接在订单服务中将商品服务的服务名称和地址信息固定写死,这个前提就是我们得需要知道商品服务的信息才能进行调用,除了需要知道商品服务的地址信息之外,如果商品服务将其服务名称和地址信息修改了,那我们订单服务调用就会报错,需要重新修改代码信息,并重新打包部署,大大增加了我们的运维成本,同时,若是这时有用户需要该服务,就需要等待服务重新上线,严重影响了用户的体验。

OpenFeign简单介绍

OpenFeign是alibaba旗下的一款SpringCloud组件,基于负载均衡和服务注册的基础上,OpenFeign可以从实时Naocs配置中心上获取被调用服务注册的信息,例如服务名称,服务地址等,通过这些信息,可以取消我们的代码写死,在服务信息修改的时候,Nacos配置中心也会实时更新服务信息,从而让调用方动态调用服务。

因此,实现OpenFeign之前还需要实现配置中心功能(例如consul,nacos)和负载均衡(例如LoadBalanced)。

基于订单服务实现远程调用(快速实现)

注:案例代码可在gitee仓库获取,链接:https://gitee.com/xiaozhang-aixue-programming/example-git

  • 添加依赖

SpringBoot集成了OpenFeign的实现,我们只需要在项目中添加OpenFeign的依赖即可使用。

XML 复制代码
 <!--Openfeign的依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

注:OpenFeign只需添加在服务调用方,也就是orderService的依赖中即可

  • 修改配置

orderService作为调用方,虽然openFeign不需要添加额外配置,但是需要调用方实现服务发现(此处以注册在nacos上为例)和负载均衡,被调用方需要实现服务注册

  • orderService:

    #服务端口号
    server:
    port: 8080

    spring:
    #mysql数据库配置
    datasource:
    url: jdbc:mysql://127.0.0.1:3306/cloud_order?characterEncoding=utf8&useSSL=false
    username: root
    password: 070609
    driver-class-name: com.mysql.cj.jdbc.Driver

    服务名,对应Nacos的DataId

    复制代码
    application:
      name: order-service  
    cloud:
      nacos:
        # 全局nacos地址,【只写这里一处】,config和discovery共用
        server-addr: 121.199.35.34:10020
        # 服务注册发现
        discovery:
        # Nacos负载均衡
        loadbalancer:
          nacos:
            enabled: true

    mybatis:
    configuration: # 配置打印 MyBatis 执行的 SQL
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true #自动驼峰转换

  • productService(配置项参考上文)

    server:
    port: 9090
    spring:
    datasource:
    url: jdbc:mysql://127.0.0.1:3306/cloud_product?characterEncoding=utf8&useSSL=false
    username: root
    password: 070609
    driver-class-name: com.mysql.cj.jdbc.Driver
    application:
    name: product-service
    cloud:
    nacos:
    discovery:
    server-addr: 121.199.35.34:10020
    loadbalancer:
    nacos:
    enabled: true
    mybatis:
    configuration: # 配置打印 MyBatis 执行的 SQL
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true #自动驼峰转换

  • 添加@EnableFeignClients,启动feign服务

在服务调用方-orderService的启动类上添加注解@EnableFeignClients,启动OpenFeign

复制代码
@SpringBootApplication
@EnableFeignClients
public class OrderDemoApplication {
    public static void main(String[] args) {

        ApplicationContext context = SpringApplication.run(OrderDemoApplication.class, args);

    }

}
  • 创建接口

创建api调用接口,基于Spring MVC来声明feign客户端的信息

复制代码
@FeignClient(value = "product-service", path = "/product")
public interface ProductApi {
 @RequestMapping("/{productId}")
 ProductInfo getProductById(@PathVariable("productId") Integer productId);
}

@FeignClient(value = "product-service", path = "/product")中,value声明的是接口提供方的服务名称,和productService注册在nacos上的服务名称对应,path声明是productService的接口的路径,根据这个可映射到productService的接口上

  • 修改远程调用代码

将原本使用restTemple的代码修改成根据接口映射调用

java 复制代码
@Service
public class orderService {
    @Autowired
    orderMapper orderMapper;

//    @Autowired
//    RestTemplate restTemplate;
//注入productApi
    @Autowired
    ProductApi productApi;

    public orderInfo getOrderInfo(Integer id){
        orderInfo orderInfo = orderMapper.selectOrderInfoById(id);
//        String url="http://product-service/product/"+orderInfo.getProductId();
//        productInfo productInfo = restTemplate.getForObject(url, productInfo.class);

        productInfo productInfo = productApi.getProductInfoById(orderInfo.getProductId());
        orderInfo.setProductInfo(productInfo);

        return orderInfo;
    }
}
  • 测试

启动服务,使用浏览器或是postman访问u接口,获取productInfo信息

总结

  1. 使用OpenFeign可以从配置中心上获取服务的信息,动态获取服务的地址和其他信息,从而实现两个服务之间的调用;
  2. 使用OpenFeign服务必须注册在配置中心上,否则无法拉取服务信息,也不能进行地址的映射;
  3. 服务调用方必须在启动类上添加@EnableFeignClients注解,启动Feign功能,同时也需要绑定服务提供方的信息;
相关推荐
denlaku1 小时前
JDK 26 新特性详解
java
SL_staff1 小时前
3分钟完成业务规则调整:告别代码修改,实现拖拽式逻辑配置
java·低代码·全栈
拖孩1 小时前
AI 帮我写的小程序上线 44 天:36 个人进了收银台,8 个人付钱
前端·后端·微信小程序
Flynn Liang1 小时前
让 AI 查订单、查库存、发消息:Spring AI 自定义工具(Tool)实战与工具描述工程
java·人工智能·spring·函数调用·springai·tool·自定义工具
Rain的Java大神之路2 小时前
我,13年Java老兵,建了个免费网站,公开叫板“Java已死”:没有广告,没有付费墙,151个页面全是踩坑干货
java·后端·程序员
萧瑟余晖2 小时前
Spring Integration企业集成概览详解
java·后端·spring
小小张说故事2 小时前
Python 的赋值为什么不会复制对象?拆开引用、浅拷贝与深拷贝
后端·python
这个昵称不容易2 小时前
SpringBoot 墙绘交易平台毕设:128个文件154个接口含论文,带运行截图
java·springboot·毕设
SimonKing2 小时前
告别纸质合同,使用DocuSeal搭建私有电子签平台
java·后端·程序员