Kubernetes 开发 SpringCloud (三)、使用 SpringCloud Feign 进行 SrpingCloud 服务间的通信

Kubernetes 开发 SpringCloud (三)、使用 SpringCloud Feign 进行 SrpingCloud 服务间的通信_第1张图片

文章目录

    • 一、介绍
      • Feign 简介
      • Hystrix 简介
    • 二、Kubernetes 中使用 Feign 进行服务间通信
    • 三、Kubernetes 中项目使用 Feign 进行服务间通信示例
      • 1、Feign 接口项目示例代码
        • (1)、Maven 引入相关依赖
        • (2)、Interface 接口类定义
      • 2、服务提供者示例代码
        • (1)、Maven 引入相关依赖
        • (2)、实现 UserInterface 接口
        • (3)、Application 配置文件
        • (4)、启动类
      • 3、服务消费者示例代码
        • (1)、Maven 引入相关依赖
        • (2)、Feign Service类
        • (3)、Feign Fallback 类
        • (4)、TestController 类
        • (5)、Application 配置文件
        • (6)、启动类
      • 4、构建 Docker 镜像
        • (1)、执行 Maven 编译
        • (2)、准备 Dockerfile
        • (3)、执行 Docker 构建镜像
      • 5、准备 Kubernetes 部署文件
      • 6、将项目推送到 Kubernetes
      • 7、测试接口
    • 四、可配置参数
      • 1、Feign 配置
        • Feign Client 全局默认配置
        • Feign Client 类单独配置
        • Feign 请求/响应压缩配置
        • Feign 日志配置
      • 2、Hystrix 配置
        • 开启 Hystrix

欢迎关注我的个人博客,关注最新动态: http://www.mydlq.club

相关博文:

  • 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 开发 SpringCloud (三)、使用 SpringCloud Feign 进行 SrpingCloud 服务间的通信_第2张图片

三、Kubernetes 中项目使用 Feign 进行服务间通信示例

       这里写三个项目,分别是 提供者项目 与 消费者 项目 与两个服务都引用的 接口类项目,开发模式跟在本地使用 SpringCloud 框架开发服务一样,消费者 调用 提供者,且两者都引用 接口项目,其中提供者实现 接口项目interface 的实现,消费者调通过 Feign 引入 interface 接口。这两个服务创建完成后将其部署到 Kubernetes 环境下,通过 NodePort 方式暴露端口供外部访问,然就外部调用 消费者 服务来测试是否能成功调用 提供者 服务提供的接口。

1、Feign 接口项目示例代码

(1)、Maven 引入相关依赖


<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.0modelVersion>

    <groupId>club.mydlqgroupId>
    <artifactId>service-feign-interfaceartifactId>
    <version>0.0.1version>
    <name>service-feign-interfacename>
    <description>service feign interfacedescription>

    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
            <version>2.1.6.RELEASEversion>
        dependency>
    dependencies>

project>

(2)、Interface 接口类定义

import org.springframework.web.bind.annotation.*;

public interface UserInterface {

    /**
     * 获取测试信息
     * @return
     */
    @GetMapping()
    public String getInfo();

}

2、服务提供者示例代码

(1)、Maven 引入相关依赖


<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.0modelVersion>

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.1.6.RELEASEversion>
        <relativePath/>
    parent>

    <groupId>club.mydlqgroupId>
    <artifactId>service-providerartifactId>
    <version>0.0.1version>
    <name>service-providername>
    <description>service providerdescription>

    <properties>
        <java.version>1.8java.version>
    properties>

    <dependencies>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-actuatorartifactId>
        dependency>
        
        <dependency>
            <groupId>club.mydlqgroupId>
            <artifactId>service-feign-interfaceartifactId>
            <version>0.0.1version>
        dependency>
    dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            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 引入相关依赖


<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.0modelVersion>

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.1.6.RELEASEversion>
        <relativePath/>
    parent>

    <groupId>club.mydlqgroupId>
    <artifactId>service-customerartifactId>
    <version>0.0.1version>
    <name>service-customername>
    <description>service customerdescription>

    <properties>
        <java.version>1.8java.version>
    properties>

    <dependencies>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-actuatorartifactId>
        dependency>
        
        <dependency>
            <groupId>club.mydlqgroupId>
            <artifactId>service-feign-interfaceartifactId>
            <version>0.0.1version>
        dependency>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-openfeignartifactId>
            <version>2.1.2.RELEASEversion>
        dependency>
    dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            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:
      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:
      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:
      :
        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—

欢迎关注我的个人博客,关注最新动态: http://www.mydlq.club

你可能感兴趣的:(kubernetes)