云原生微服务 第六章 Spring Cloud Eureka微服务的远程调用、负载均衡

系列文章目录

第一章 Java线程池技术应用
第二章 CountDownLatch和Semaphone的应用
第三章 Spring Cloud 简介
第四章 Spring Cloud Netflix 之 Eureka
第五章 Spring Cloud Netflix 之 Ribbon
第六章 Spring Cloud 之 OpenFeign


文章目录


前言

OpenFeign 全称 Spring Cloud OpenFeign,它是 Spring 官方推出的一种声明式服务调用与负载均衡组件。我们可以像调用本地方法一样来调用远程服务,而完全感觉不到这是在进行远程调用。

1、OpenFeign的实现原理和过程

OpenFeign是一个声明式的Web服务客户端,它使得编写Web服务客户端变得更加简单。通过使用OpenFeign,开发者可以更加容易地创建与远程服务进行交互的客户端代码。

OpenFeign通过自动封装HTTP请求和简化远程调用代码的过程,使得开发者可以更加专注于业务逻辑的实现,提高了开发效率和代码可读性。

1.1、OpenFeign支持Spring Cloud体系内的所有注解

例如@GetMapping、@PostMapping、@PathVariable、@RequestParam等,同时也支持自定义注解。

1.2、OpenFeign自动封装HTTP请求

包括HTTP方法、请求URL、请求参数、请求头等,开发者无需手动编写HTTP请求代码。只需要定义一个接口,并通过注解指定接口的路径和方法,OpenFeign就会自动发送HTTP请求并解析响应数据。

1.3、OpenFeign支持请求拦截器和响应拦截器

开发者可以通过实现请求拦截器和响应拦截器来对HTTP请求和响应进行处理,例如添加认证信息、重试等。

1.4、在Spring项目中的过程

在Spring项目启动中,OpenFeign会发起一个主动扫包的过程。从指定目录下加载所有被@FeignClient修饰的接口,将这些接口转换为Bean,交给Spring来管理。这些接口会经过MVC Constract解析,将方法上的注解解析出来放到MethodMetadata中。每一个FeignClient接口会生成一个动态代理对象,指向包含方法的MethodHandler的HashMap。

1.5、远程调用

当服务A发起远程调用时,它会从动态代理proxy中找到一个MethodHandler的实例,生成request,包含请求的url。经过负载均衡算法找到一个服务的IP地址,拼接请求的URL。服务B处理服务A发起的远程调用,执行逻辑后,返回响应给A。

2、常用注解

使用 OpenFegin 进行远程服务调用时,常用注解如下表。

注解 说明
@FeignClient 该注解用于通知 OpenFeign 组件对 @RequestMapping 注解下的接口进行解析,并通过动态代理的方式产生实现类,实现负载均衡和服务调用。
@EnableFeignClients 该注解用于开启 OpenFeign 功能,当 Spring Cloud 应用启动时,OpenFeign 会扫描标有 @FeignClient 注解的接口,生成代理并注册到 Spring 容器中。
@RequestMapping Spring MVC 注解,在 Spring MVC 中使用该注解映射请求,通过它来指定控制器(Controller)可以处理哪些 URL 请求,相当于 Servlet 中 web.xml 的配置。
@GetMapping Spring MVC 注解,用来映射 GET 请求,它是一个组合注解,相当于 @RequestMapping(method = RequestMethod.GET) 。
@PostMapping Spring MVC 注解,用来映射 POST 请求,它是一个组合注解,相当于 @RequestMapping(method = RequestMethod.POST) 。

3、实践

3.1、修改pom.xml配置

在上一章节[《微服务实战》 第五章 Spring Cloud Netflix 之 Ribbon ] 基础上,添加OpenFeign依赖项

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.kelvin</groupId>
        <artifactId>SpringCloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>customer-api</artifactId>
    <name>customer-api</name>
    <description>customer-api</description>

    <properties>
        <java.version>1.8</java.version>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--devtools 开发工具-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <!--Spring Boot 测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--junit 测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!-- 修改后立即生效,热部署 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>springloaded</artifactId>
            <version>1.2.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
           <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-loadbalancer -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
        <dependency>
            <groupId>com.kelvin</groupId>
            <artifactId>common-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>

3.2、增加用户服务接口,添加FeignClient配置

java 复制代码
import com.kelvin.common.model.UserInfo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.List;

/***
 * @title 用户服务接口
 * @desctption 用户服务接口
 * @author kelvin
 * @create 2023/5/11 16:44
 **/
@Component
@FeignClient(value = "USER-SERVICE")
public interface UserService {
    @RequestMapping(value = "/user/userInfoList",method = RequestMethod.GET)
    public List<UserInfo> userInfoList();
}

3.3、修改控制层UserConsumerController

java 复制代码
import com.kelvin.common.model.UserInfo;
import com.kelvin.customerapi.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;

/***
 * @title UserConsumerController
 * @desctption 用户控制层
 * @author kelvin
 * @create 2023/5/11 14:22
 **/
@RestController
@RequestMapping("/user")
public class UserConsumerController {

/*    @Autowired
    private UserConsumerService userConsumerService;*/

    @Autowired
    private UserService userService;

    @GetMapping("/userInfoList")
    public List<UserInfo> userInfoList(){
        return userService.userInfoList();
    }
}

3.4、启动类增加OpenFeign配置

java 复制代码
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

/***
 * @title SpringBoot 启动类
 * @desctption SpringBoot 启动类
 * @author kelvin
 * @create 2023/5/11 12:22
 **/
@SpringBootApplication
@EnableFeignClients
public class CustomerApiApplication {

    public static void main(String[] args) {
        SpringApplication.run(CustomerApiApplication.class, args);
    }

}

3.5、远程调用超时设置

openFeign其实是有默认的超时时间的,默认分别是连接超时时间10秒、读超时时间60秒

可添加配置,自定义超时时间

yml 复制代码
server:
  port: 80

eureka:
  client:
    register-with-eureka: false #本微服务为服务消费者,不需要将自己注册到服务注册中心
    fetch-registry: true  #本微服务为服务消费者,需要到服务注册中心搜索服务
    service-url:
      defaultZone: http://localhost:7001/eureka
feign:
  client:
    config:
      default:
        #建立连接所用的时间,适用于网络状况正常的情况下,两端连接所需要的时间
        connect-timeout: 5000
        #指建立连接后从服务端读取到可用资源所用的时间
        read-timeout: 10000

4、总结

OpenFeign通过自动封装HTTP请求和简化远程调用代码的过程,使得开发者可以更加专注于业务逻辑的实现,提高了开发效率和代码可读性。

相关推荐
虚伪的空想家30 分钟前
rook-ceph配置dashboard代理无法访问
ceph·云原生·k8s·存储·rook
Connie14516 小时前
k8s多集群管理中的联邦和舰队如何理解?
云原生·容器·kubernetes
一眼万年046 小时前
Redis Cluster模式
redis·微服务
伤不起bb10 小时前
Kubernetes 服务发布基础
云原生·容器·kubernetes
国际云,接待12 小时前
微软服务器安全问题
运维·服务器·云原生·云计算·azure
默默coding的程序猿12 小时前
3.前端和后端参数不一致,后端接不到数据的解决方案
java·前端·spring·ssm·springboot·idea·springcloud
别骂我h13 小时前
Kubernetes服务发布基础
云原生·容器·kubernetes
要开心吖ZSH14 小时前
微服务架构的演进:迈向云原生
java·微服务·云原生
dyj09514 小时前
Rancher Server + Kubernets搭建云原生集群平台
云原生·rancher
weixin_3993806915 小时前
k8s一键部署tongweb企业版7049m6(by why+lqw)
java·linux·运维·服务器·云原生·容器·kubernetes