你好,这里是codetrend专栏“SpringCloud2023实战”。
前言
feign之前是Netflix的一个子项目,由于停止了维护,spring继续维护了一个openfeign作为替代。Spring Cloud OpenFeign 具有以下优点:
- 简化微服务之间的调用,屏蔽冗余代码,基于注解开发远程调用。
- 提供负载均衡、降级等配套的微服务开发体验。
远程调用的重要性
在 Spring Cloud 2023 中,远程调用的重要性主要体现在微服务架构中。微服务架构将应用程序划分为一组小型、松耦合的服务,每个服务都运行在自己的进程中,并通过轻量级的通信机制进行通信。远程调用在微服务架构中扮演着重要的角色,主要有以下几个方面的重要性:
- 服务间通信:微服务架构中的服务通常分布在不同的主机、容器或云环境中,它们需要通过远程调用进行通信。远程调用使得各个服务可以相互协作、交换数据,并实现系统的功能。
- 服务发现与注册:远程调用需要知道其他服务的位置和接口信息,而不是直接硬编码在代码中。因此,服务发现与注册成为微服务架构中的关键组件,它使得服务能够动态地注册和发现其他服务,从而进行远程调用。
- 解耦服务:远程调用可以帮助将微服务之间的耦合度降到最低。每个微服务都可以专注于特定的业务功能,通过远程调用与其他服务交互,而无需了解对方的内部实现细节。
- 水平扩展:微服务架构支持水平扩展,即通过增加实例来处理更多的请求负载。远程调用使得新的服务实例可以被动态地添加到系统中,并与其他服务进行通信,从而实现系统的水平扩展。
- 容错与负载均衡:远程调用可以通过负载均衡和容错机制来提高系统的可用性和可靠性。负载均衡可以将请求分发到多个服务实例中,从而避免单点故障和请求过载,而容错机制则可以在服务失败时进行故障转移或重试。
生产者集成
无需特殊的集成和配置,需要注册到注册中心,这里以应用名为 client1
举例说明生产者。
生产者配置
spring.application.name: client1
spring:
cloud:
zookeeper:
connect-string: localhost:2181
server:
port: 10101
servlet:
context-path: /client1
生产者启动类
package io.rainforest.banana.client1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
生产者对外接口提供
- control层代码。
package io.rainforest.banana.client1.web.demo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
public class HelloWorld {
@GetMapping("/")
public String hello(String hello){
return hello+" world";
}
@GetMapping("/hello2")
@ResponseBody
public List<String> hello2(String hello){
List<String> res = new ArrayList<>();
res.add("test1");
res.add("test2");
res.add(hello);
return res;
}
}
消费者集成
客户端引入pom.xml
- 引入openfeign主要是引入
<artifactId>spring-cloud-starter-openfeign</artifactId>
。
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>io.rainforest</groupId>
<artifactId>banana</artifactId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>banana-client3</artifactId>
<description>spring cloud banana-client3</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!--注册中心客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency>
<!--配置中心客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!--引入openfeign主要引入 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- LB 扩展 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!-- 工具包依赖 -->
<dependency>
<groupId>io.rainforest</groupId>
<artifactId>banana-common-core</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
客户端修改配置
- 新增配置文件
application.yml
,配置中心配置主要是spring.cloud.openfeign
下面的配置。
spring:
application:
name: client3
cloud:
config:
profile: dev
name: ${spring.application.name}
# uri: http://localhost:10110
discovery:
enabled: true
service-id: config
zookeeper:
connect-string: 127.0.0.1:2181
openfeign:
httpclient:
enabled: false
okhttp:
enabled: true
通过引入 feign-okhttp
替换默认的httpurlconnection,以及修改配置 spring.cloud.openfeign.okhttp.enabled
实现。
客户端修改启动类
- 启动类不需要特殊修改。
package io.rainforest.banana.client3;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
远程调用demo
- 假设注册中心已经注册服务
clent1
。 - 编写openfeign客户端调用代码。
package io.rainforest.banana.client3.web.demo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@FeignClient(name = "client1",value = "client1",contextId = "client1",path = "/client1")
public interface Client1 {
@RequestMapping(method = RequestMethod.GET,value = "/hello2")
List<String> hello2(@RequestParam("hello") String hello);
@GetMapping(value = "/")
String hello(@RequestParam("hello") String hello);
}
- 在control层使用openfeign客户端。
package io.rainforest.banana.client3.web.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class HelloWorld {
@Autowired
private Client1 client1;
@GetMapping("/")
public String hello(String hello){
return hello+" world";
}
@GetMapping("/hello2")
public List<String> hello2(String hello){
return client1.hello2(hello);
}
@GetMapping("/hello")
public String hello1(String hello){
return client1.hello(hello);
}
}
完整源码信息查看 https://gitee.com/r0ad/spring-cloud-example
关于作者
来自一线全栈程序员nine的探索与实践,持续迭代中。
欢迎关注公众号“雨林寻北”或添加个人卫星codetrend(备注技术)。