Kubernetes 开发 SpringCloud (三)、使用 SpringCloud Feign 进行 SrpingCloud 服务间的通信
目录[-]
相关博文:
- Kubernetes 开发 SpringCloud (一)、使用SpringCloud Kubernetes组件进行服务发现
- Kubernetes 开发 SpringCloud (二)、使用 SpringCloud Kubernetes 组件进行动态配置
- Kubernetes 开发 SpringCloud (三)、使用 SpringCloud Feign 进行 SrpingCloud 服务间的通信
- Kubernetes 开发 SpringCloud (四)、Kubnernetes 部署 Zipkin 搭配 Kafka+ElasticSearch 实现链路追踪
系统环境:
- Kubernetes 版本:1.14.0
- SpringCloud Feign 版本:2.1.2.RELEASE
- SpringCloud Kubernetes 版本:1.0.2.RELEASE
- 示例部署文件 Github 地址:https://github.com/my-dlq/blog-example/tree/master/springcloud-kubernetes/springcloud-kubernetes-feign-demo
一、介绍
Feign 简介
Feign 是一个声明式的 Web Service 客户端,可以帮助我们更快捷、优雅地调用HTTP API。它的出现使开发 Web Service 客户端变得很简单,使用 Feign 只需要创建一个接口加上对应的注解就可以完成服务间的调用。
Spring Cloud Feign 帮助我们定义和实现依赖服务接口的定义。在Spring Cloud feign 的实现下,只需要创建一个接口并用注解方式配置它,即可完成服务提供方的接口绑定,简化了在使用Spring Cloud Ribbon时自行封装服务调用客户端的开发量。
Feign 功能:
- 可插拔的注解支持,包括Feign注解和JAX-RS注解。
- 支持可插拔的HTTP编码器和解码器(Gson,Jackson,Sax,JAXB,JAX-RS,SOAP)。
- 支持Hystrix和它的Fallback。
- 支持Ribbon的负载均衡。
- 支持HTTP请求和响应的压缩。
- 灵活的配置:基于 name 粒度进行配置
- 支持多种客户端:JDK URLConnection、apache httpclient、okhttp,ribbon)
- 支持日志
- 支持错误重试
- url支持占位符
- 可以不依赖注册中心独立运行
Hystrix 简介
在分布式环境中,许多服务依赖项中的一些必然会失败。Hystrix 是一个库,通过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互。Hystrix 通过隔离服务之间的访问点、停止级联失败和提供回退选项来实现这一点,所有这些都可以提高系统的整体弹性。
Hystrix 功能:
- 服务降级:优先核心服务,非核心服务不可用或弱可用
- 依赖隔离:依赖隔离其实就是资源隔离,把对依赖使用的资源隔离起来,统一控制和调度。
- 监控(Dashboard)状态:hystrix 提供了一套监控组件Dashboard,用于查看最近熔断器的情况。
- 服务熔断:类似现实世界中的”保险丝”,当某个异常条件被触发,直接熔断整个服务,进行服务的降级快速返回”错误”的响应信息而不是一直等到此服务超时。当检测到该节点微服务响应正常后恢复调用链路。
二、Kubernetes 中使用 Feign 进行服务间通信
在 Kubernetes 环境中使用 SpringCloud 框架开发服务跟本地开发一样,服务间调用也是可用利用
Feign完成服务间通信工作,保持和本地开发 SpringCloud 模式不变,这样也能减少学习成本。如果使用
SpringCloud Feign还能配合
SpringCloud Sleuth生成链路日志,然后配合
Zipkin配合完成服务间链路追踪工作。
在 Kubernetes 环境下使用
Feign还有一个问题是,现在已经将
Eureka等注册中心去掉了,且在 Kubernetes 中所有的
Service信息都会通过 Kubernetes 存入
Etcd中,且每个服务都会通过
CoreDNS分配一个以
服务名称命名的不会重复域名,所以我们可以在开发项目过程中,可以通过配置
Feign使用
域名+
端口号方式完成服务间的调用,如下图所示:
三、Kubernetes 中项目使用 Feign 进行服务间通信示例
这里写三个项目,分别是
提供者项目 与
消费者项目 与两个服务都引用的
接口类项目,开发模式跟在本地使用 SpringCloud 框架开发服务一样,
消费者调用
提供者,且两者都引用
接口项目,其中提供者实现
接口项目的
interface的实现,消费者调通过
Feign引入
interface接口。这两个服务创建完成后将其部署到 Kubernetes 环境下,通过
NodePort方式暴露端口供外部访问,然就外部调用
消费者服务来测试是否能成功调用
提供者服务提供的接口。
1、Feign 接口项目示例代码
(1)、Maven 引入相关依赖
<?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"> <modelVersion>4.0.0</modelVersion> <groupId>club.mydlq</groupId> <artifactId>service-feign-interface</artifactId> <version>0.0.1</version> <name>service-feign-interface</name> <description>service feign interface</description> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.1.6.RELEASE</version> </dependency> </dependencies> </project>
(2)、Interface 接口类定义
import org.springframework.web.bind.annotation.*; public interface UserInterface { /** * 获取测试信息 * @return */ @GetMapping() public String getInfo(); }
2、服务提供者示例代码
(1)、Maven 引入相关依赖
<?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"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/> </parent> <groupId>club.mydlq</groupId> <arti 3ff7 factId>service-provider</artifactId> <version>0.0.1</version> <name>service-provider</name> <description>service provider</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <!--SpringBoot Web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--SpringBoot Actuator--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!--Service Interface API--> <dependency> <groupId>club.mydlq</groupId> <artifactId>service-feign-interface</artifactId> <version>0.0.1</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
(2)、实现 UserInterface 接口
import club.mydlq.feign.TestInterface; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController implements TestInterface { @Override public String getInfo() { return "Hello World!"; } }
(3)、Application 配置文件
spring: application: name: service-provider server: port: 8080 management: server: port: 8081 endpoints: web: exposure: include: "*"
(4)、启动类
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
3、服务消费者示例代码
(1)、Maven 引入相关依赖
<?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"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/> </parent> <groupId>club.mydlq</groupId> <artifactId>service-customer</artifactId> <version>0.0.1</version> <name>service-customer</name> <description>service customer</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <!--SpringBoot Web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--SpringBoot Actuator--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!--Service Interface API--> <dependency> <groupId>club.mydlq</groupId> <artifactId>service-feign-interface</artifactId> <version>0.0.1</version> </dependency> <!--Feign--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>2.1.2.RELEASE</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
(2)、Feign Service类
import club.mydlq.feign.TestInterface; import org.springframework.cloud.openfeign.FeignClient; @FeignClient(name = "http://service-provider:8080", url = "http://service-provider:8080", fallback = TestFallback.class) public interface TestService extends TestInterface { }
(3)、Feign Fallback 类
import org.springframework.stereotype.Component; @Component public class TestFallback implements TestService { @Override public String getInfo() { return "fallback!"; } }
(4)、TestController 类
import club.mydlq.k8s.feign.TestService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @RestController public class TestController { @Autowired private TestService testService; @GetMapping("/") public String getTestInfo(){ return testService.getInfo(); } }
(5)、Application 配置文件
spring: application: name: service-customer server: port: 8080 management: server: port: 8081 endpoints: web: exposure: include: "*" #开启 Hystrix feign: hystrix: enabled: true
(6)、启动类
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication @EnableFeignClients public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
4、构建 Docker 镜像
(1)、执行 Maven 编译
#Manve 编译 service-feign-interface 项目 $ cd service-feign-interface $ mvn clean install #Manve 编译 service-provider 项目 $ cd service-provider $ mvn clean install #Manve 编译 service-customer 项目 $ cd service-customer $ mvn clean install
(2)、准备 Dockerfile
Dockerfile
FROM openjdk:8u212-b04-jre-slim VOLUME /tmp ADD target/*.jar app.jar RUN sh -c 'touch /app.jar' ENV JAVA_OPTS="-Duser.timezone=Asia/Shanghai" ENV APP_OPTS="" ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS" ]
(3)、执行 Docker 构建镜像
#构建 service-provider 镜像 $ docker build -t mydlqclub/service-provider:0.0.1 . #构建 service-customer 镜像 $ docker build -t mydlqclub/service-customer:0.0.1 .
5、准备 Kubernetes 部署文件
service-provider.yaml
apiVersion: v1 kind: Service metadata: name: service-provider spec: type: NodePort ports: - name: server nodePort: 31001 port: 8080 targetPort: 8080 - name: management nodePort: 31002 port: 8081 targetPort: 8081 selector: app: service-provider --- apiVersion: apps/v1 kind: Deployment metadata: name: service-provider labels: app: service-provider spec: replicas: 1 selector: matchLabels: app: service-provider template: metadata: name: service-provider labels: app: service-provider spec: serviceAccountName: springcloud-kubernetes restartPolicy: Always containers: - name: service-provider image: registry.cn-beijing.aliyuncs.com/mydlq/service-provider:0.0.1 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 name: server - containerPort: 8081 name: management resources: limits: memory: 1000Mi cpu: 1000m requests: memory: 500Mi cpu: 500m
service-customer.yaml
apiVersion: v1 kind: Service metadata: name: service-customer spec: type: NodePort ports: - name: server nodePort: 31003 port: 8080 targetPort: 8080 - name: management nodePort: 31004 port: 8081 targetPort: 8081 selector: app: service-customer --- apiVersion: apps/v1 kind: Deployment metadata: name: service-customer labels: app: service-customer spec: replicas: 1 selector: matchLabels: app: service-customer template: metadata: name: service-customer labels: app: service-customer spec: serviceAccountName: springcloud-kubernetes restartPolicy: Always containers: - name: service-customer image: registry.cn-beijing.aliyuncs.com/mydlq/service-customer:0.0.1 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 name: server - containerPort: 8081 name: management resources: limits: memory: 1000Mi cpu: 1000m requests: memory: 500Mi cpu: 500m
6、将项目推送到 Kubernetes
执行 Kubectl 部署命将项目部署到 Kubernetes。
#创建RBAC $ kubectl apply -f service-rbac.yaml -n mydlqcloud #创建service-customer $ kubectl apply -f service-customer.yaml -n mydlqcloud #创建service-provider $ kubectl apply -f service-provider.yaml -n mydlqcloud
7、测试接口
输入地址:http://192.168.2.11:31003 测试
service-customer服务是否能正常通过
Feign调用
service-provider服务。
结果:
Hello World!
将 Kubernetes 中 service-provider 关掉来测试 fallback,再次输入地址:http://192.168.2.11:31003
结果:
fallback!
由上面结果可知,在 Kubernetes 环境下通过 SpringCloud Feign 根据
服务名称+
端口号这种方式,完成服务间的通信是可行的。
四、可配置参数
1、Feign 配置
Feign Client 全局默认配置
feign: client: config: default: connectTimeout: 5000 #默认连接超时时间 readTimeout: 5000 #默认读取超时时间 loggerLevel: basic #默认日志级别
Feign Client 类单独配置
feign: client: config: <feignClassName>: connectTimeout: 5000 #连接超时时间 readTimeout: 5000 #读取超时时间 loggerLevel: full #日志等级
Feign 请求/响应压缩配置
# 请求开启压缩 feign.compression.request.enabled=true # 响应开启压缩 feign.compression.response.enabled=true # 什么数据类型才进行压缩操作 feign.compression.request.mine-types=text/xml,application/xml,application/json # 请求压缩的大小下线 feign.compression.request.min-request-size=2048
Feign 日志配置
在 Feign 中项目中会为每个 Feign 客户端创建一个记录器,默认情况下记录器的名称是接口的完整类名(包名+类名),并且 Feign 仅会记录 Debug 级别的日志。
(1)、Feign 记录器配置
配置 Feign 客户端记录器,且 Feign 仅仅记录 Debug 级别日志。
#配置格式:logging.level.<包路径>.<类名>:DEBUG #例如本项目设置Feign 客户端日志如下: logging: level: club.mydlq.k8s.feign.HelloService: DEBUG
(2)、Feign 日志级别配置
日志配置器有四种日志级别,分别记录不同的日志信息,需要设置一个配置类配合配置文件来完成日志设置。
@Configuration public class FeignConfig { @Bean Logger.Level feignLoggerLevel() { return Logger.Level.FULL; } }
- NONE:不记录日志(DEFAULT)。
- BASIC:仅记录请求方法和 URL 以及响应状态代码和执行时间。
- HEADERS:记录基本信息以及请求和响应 Headers 信息。
- FULL:记录请求和响应的 Headers、Body 和 Metadata 数据。
2、Hystrix 配置
开启 Hystrix
#在Feign中开启Hystrix feign: hystrix: enabled: true
—END—
- Kubernetes 开发 SpringCloud (一)、使用SpringCloud Kubernetes组件进行服务发现
- SpringCloud使用Feign进行服务调用
- 使用Spring Cloud Feign进行服务调用
- Kubernetes 开发 SpringCloud (二)、使用 SpringCloud Kubernetes 组件进行动态配置
- (Spring Cloud微服务实战-书中之坑)spring cloud feign同时使用继承特性和断路器
- 【项目搭建】使用spring-boot进行REST风格的微服务开发入门
- 使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
- spring cloud 之 Feign 使用HTTP请求远程服务
- Spring Cloud Eureka 使用 IP 地址进行服务注册
- (八)SpringBoot+SpringCloud —— 使用Feign消费服务
- spring cloud 使用Hystrix 实现断路器进行服务容错保护的方法
- 微服务笔记之Spring Cloud 中使用Feign调用接口服务(Finchley)
- 使用Spring Cloud微服务框架进行多个微服务整合时出现No converter found for return value of type:xxx异常信息
- SpringCloud 查找调用REST服务使用RestTemplate(ribbon负载)或feign模式 教程源码 火推
- 使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
- Spring boot + Spring Cloud框架下通过Feign进行跨服务传递文件
- springcloud使用feign实现服务间条用,参数数据太大,无法调用成功解决方法
- 使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务
- 微服务框架Spring Cloud介绍 Part4: 使用Eureka, Ribbon, Feign实现REST服务客户端
- 使用Spring Cloud Feign作为HTTP客户端调用远程HTTP服务