spring-cloud-kubenetes 与 feign调用

5 篇文章 0 订阅
2 篇文章 0 订阅

1、所需环境:

  • windows 安装 Ubuntu-18.04
  • docker
  • minikube

2、安装docker

  1. 安装yum-utils包(提供yum-config-manager 实用程序)并设置稳定的存储库。

    sudo yum install -y yum-utils
    sudo yum-config-manager \
        --add-repo \
        https://download.docker.com/linux/centos/docker-ce.repo
    
  2. 安装 Docker 引擎

    sudo yum install docker-ce docker-ce-cli containerd.io
    
  3. 启动 Docker

    sudo /etc/init.d/docker start # wsl2 启动
    
  4. 测试安装

    docker --version
    
  5. 通过运行hello-world 映像来验证 Docker 引擎是否已正确安装。

    sudo docker run hello-world
    

以上docker安装完成

3、安装minikube

  1. 更新包

    sudo apt-get update
    sudo apt-get install apt-transport-https
    sudo apt-get upgrade
    
  2. 安装Virtual Box(用来跑minikube)

    sudo apt install virtualbox virtualbox-ext-pack
    
  3. 下载minikube

    wget https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
    chmod +x minikube-linux-amd64
    sudo mv minikube-linux-amd64 /usr/local/bin/minikube
    
  4. 验证minikube的版本

    minikube version
    
    root@localhost:~$ minikube version
    minikube version: v1.25.2
    commit: 362d5fdc0a3dbee389b3d3f1034e8023e72bd3a7
    root@localhost:~$
    
  5. 在Ubuntu上安装 kubectl

    1. 使用命令行下载安装包
      curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
      
    2. 安装kubectl
      sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
      
    3. 测试安装 kubectl version --client 或使用 kubectl version -o json 验证安装是否正确
      kubectl version --client
      
      root@localhost:~$ kubectl version --client
      WARNING: This version information is deprecated and will be replaced with the output from kubectl version --short.  Use --output=yaml|json to get the full version.
      Client Version: version.Info{Major:"1", Minor:"24", GitVersion:"v1.24.0", GitCommit:"4ce5a8954017644c5420bae81d72b09b735c21f0", GitTreeState:"clean", BuildDate:"2022-05-03T13:46:05Z", GoVersion:"go1.18.1", Compiler:"gc", Platform:"linux/amd64"}
      Kustomize Version: v4.5.4
      root@localhost:~$
      
      root@localhost:~$ kubectl version -o json
      {
        "clientVersion": {
          "major": "1",
          "minor": "24",
          "gitVersion": "v1.24.0",
          "gitCommit": "4ce5a8954017644c5420bae81d72b09b735c21f0",
          "gitTreeState": "clean",
          "buildDate": "2022-05-03T13:46:05Z",
          "goVersion": "go1.18.1",
          "compiler": "gc",
          "platform": "linux/amd64"
        },
        "kustomizeVersion": "v4.5.4",
        "serverVersion": {
          "major": "1",
          "minor": "23",
          "gitVersion": "v1.23.3",
          "gitCommit": "816c97ab8cff8a1c72eccca1026f7820e93e0d25",
          "gitTreeState": "clean",
          "buildDate": "2022-01-25T21:19:12Z",
          "goVersion": "go1.17.6",
          "compiler": "gc",
          "platform": "linux/amd64"
        }
      }
      root@localhost:~$
      

以上minikube安装完成

4、新建服务发现工程

  • 环境信息:
    1、minikube
    2、java 1.8
    3、maven 3.6
    4、spring-cloud-kubernetes:1.0.1RELEASE

  • 开发应用
    基于maven创建一个springboot应用,名为spring-cloud-k8s-discovery-demo;

  1. pom文件中依赖了spring-cloud-kubernetes的以下两个库,后面才能使用spring-cloud-kubernetes的服务;

    <dependency>
    	<groupId>org.springframework.cloud</groupId>
    	<artifactId>spring-cloud-kubernetes-core</artifactId>
    	<version>1.0.1.RELEASE</version>
    </dependency>
    
    <dependency>
    	<groupId>org.springframework.cloud</groupId>
    	<artifactId>spring-cloud-kubernetes-discovery</artifactId>
    	<version>1.0.1.RELEASE</version>
    </dependency>
    
  2. 创建DiscoveryController.java类:

    package com.example.springcloudk8sdiscoverydemo.controller;
    
    import com.alibaba.fastjson.JSON;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.client.discovery.DiscoveryClient;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    @RestController
    public class DiscoveryController {
    
        @Autowired
        private DiscoveryClient discoveryClient;
    
        /**
         * 探针检查响应类
         *
         * @return
         */
        @RequestMapping("/health")
        public String health() {
            return "health";
        }
    
        /**
         * 返回远程调用的结果
         *
         * @return
         */
        @RequestMapping("/getservicedetail")
        public String getservicedetail(
                @RequestParam(value = "servicename", defaultValue = "") String servicename) {
            return "Service [" + servicename + "]'s instance list : " + JSON.toJSONString(discoveryClient.getInstances(servicename));
        }
    
        /**
         * 返回发现的所有服务
         *
         * @return
         */
        @RequestMapping("/services")
        public String services() {
            return this.discoveryClient.getServices().toString()
                    + ", "
                    + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        }
    }
    
    
  3. 启动类:

    package com.example.springcloudk8sdiscoverydemo;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    
    @SpringBootApplication
    @EnableDiscoveryClient
    public class SpringCloudK8sDiscoveryDemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringCloudK8sDiscoveryDemoApplication.class, args);
        }
    }
    
    
  4. 编写 application.properties

    spring.application.name=spring-cloud-k8s-discovery-demo
    server.port=8088
    
  5. 总结:

    1. DiscoveryClient是个接口,对应的实现类是哪个?

      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-kubernetes-discovery</artifactId>
        <version>1.0.1.RELEASE</version>
      </dependency>
      

      在这里插入图片描述
      spring容器启动时,会寻找classpath下所有spring.factories文件(包括jar文件中的),spring.factories中配置的所有类都会实例化,我们在开发springboot时常用到的XXX-starter.jar就用到了这个技术,效果是一旦依赖了某个starter.jar很多功能就在spring初始化时候自动执行了

    2. discoveryClient.getServices()方法取得了kubernetes的service信息,这背后的机制是什么?java应用是怎样取得所在kubernetes的服务信息的?

      @RequestMapping("/services")
          public String services() {
              return this.discoveryClient.getServices().toString()
                      + ", "
                      + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
          }
      

      discoveryClient对应的类是spring-cloud-kubernetes项目的KubernetesDiscoveryClient.java

      	public List<String> getServices() {
              String spelExpression = this.properties.getFilter();
              Predicate filteredServices;
              if (spelExpression != null && !spelExpression.isEmpty()) {
                  Expression filterExpr = this.parser.parseExpression(spelExpression);
                  filteredServices = (instance) -> {
                      Boolean include = (Boolean)filterExpr.getValue(this.evalCtxt, instance, Boolean.class);
                      return include == null ? false : include;
                  };
              } else {
                  filteredServices = (instance) -> {
                      return true;
                  };
              }
      
              return this.getServices(filteredServices);
          }
      
          public List<String> getServices(Predicate<Service> filter) {
              return (List)((ServiceList)((FilterWatchListDeletable)this.kubernetesClientServicesFunction.apply(this.client)).list()).getItems().stream().filter(filter).map((s) -> {
                  return s.getMetadata().getName();
              }).collect(Collectors.toList());
          }
      

      这段代码的关键在于this.kubernetesClientServicesFunction.apply(this.client).list(),先看KubernetesClientServicesFunction实例的初始化过程,在KubernetesDiscoveryClientAutoConfiguration类中:

      @Bean
      public KubernetesClientServicesFunction servicesFunction(
      			KubernetesDiscoveryProperties properties) {
        if (properties.getServiceLabels().isEmpty()) {
          return KubernetesClient::services;
        }
      
        return (client) -> client.services().withLabels(properties.getServiceLabels());
      }
      
      

      KubernetesClientServicesFunction是个lambda表达式,用于KubernetesClient的时候,返回KubernetesClient.services()的结果,如果指定了标签过滤,就用指定的标签来做过滤(也就是kubernetes中的标签选择器的效果)
      因此,数据来源其实就是上面的this.client,调用其services方法的返回结果;
      最终是调用okhttp的newCall方法向kubernetes的API Server发起http请求,获取service资源的数据列表;

5、部署工程

  1. 官方demo使用插件fabric8-maven-plugin来构建镜像并部署到minikube环境,我这边可能是环境问题没有部署成功,我是将jar包打成镜后部署到minikube;
    1. 编写dockerfile并执行

      FROM openjdk:8u242-jre-slim
      WORKDIR /app/spring-cloud-k8s-discovery-demo
      COPY spring-cloud-k8s-discovery-demo-0.0.1-SNAPSHOT.jar /app/spring-cloud-k8s-discovery-demo
      RUN echo 'Asia/Shanghai' >/etc/timezone
      EXPOSE 8080
      CMD ["java", "-jar", "spring-cloud-k8s-discovery-demo-0.0.1-SNAPSHOT.jar"]
      
      docker build -f spring-cloud-k8s.Dockerfile .
      
    2. 镜像打包完成并推送至docker hub

      docker push zwzhang2022/spring-cloud-k8s:1.0
      
    3. 编写kubenetes.yaml

      apiVersion: v1
      kind: Service
      metadata:
        labels:
          app: spring-cloud-k8s-discovery-demo
        name: spring-cloud-k8s-discovery-demo
        namespace: spring-cloud-k8s-demo
      spec:
        type: NodePort
        ports:
          - port: 8088 #服务端口
            protocol: TCP
            targetPort: 8088
        selector:
          app: spring-cloud-k8s-discovery-demo
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: spring-cloud-k8s-discovery-demo-deployment
        namespace: spring-cloud-k8s-demo
      spec:
        selector:
          matchLabels:
            app: spring-cloud-k8s-discovery-demo
        replicas: 1
        template:
          metadata:
            labels:
              app: spring-cloud-k8s-discovery-demo
          spec:
            containers:
              - name: spring-cloud-k8s-discovery-demo
                image: zwzhang2022/spring-cloud-k8s-discovery-demo:2.0
                imagePullPolicy: Always
                ports:
                  - containerPort: 8088
      
    4. 创建命名空间并查看

      kubectl create namespace spring-cloud-k8s-demo
      kubectl get namespace
      
    5. 创建并查看

      kubectl  apply -f kubenetes.yaml
      kubectl -n kubenetes-demo get pods
      kubectl -n spring-cloud-k8s-demo describe pod <PodName> #查看pod详细信息
      
    6. 进入容器

      kubectl -n spring-cloud-k8s-demo exec -it spring-cloud-k8s-discovery-demo-deployment-8499cbdfc-ddsvs -c spring-cloud-k8s-discovery-demo -- sh
      
    7. 进入容器后 curl 调用接口

      /app # curl http://localhost:8080/health
      health
      
      /app # curl http://localhost:8080/services
      [spring-cloud-k8s-configmap-demo, spring-cloud-k8s-discovery-demo], 2022-05-10 18:28:54
      
      /app # curl http://localhost:8080/getservicedetail?servicename=spring-cloud-k8s-discovery-demo
      Service [spring-cloud-k8s-discovery-demo]'s instance list : [{"host":"172.17.0.3","instanceId":"d63e413d-a4a3-4bf7-a778-734d7edb3daa","metadata":{"app":"spring-cloud-k8s-discovery-demo","kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"annotations\":{},\"labels\":{\"app\":\"spring-cloud-k8s-discovery-demo\"},\"name\":\"spring-cloud-k8s-discovery-demo\",\"namespace\":\"spring-cloud-k8s-demo\"},\"spec\":{\"ports\":[{\"port\":8088,\"protocol\":\"TCP\",\"targetPort\":8088}],\"selector\":{\"app\":\"spring-cloud-k8s-discovery-demo\"},\"type\":\"NodePort\"}}\n"},"port":8088,"scheme":"http://","secure":false,"serviceId":"spring-cloud-k8s-discovery-demo","uri":"http://172.17.0.3:8088"}]
      

以上服务发现部署完成

6、k8s集成feign

  1. 引入依赖库

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-cloud-k8s-feign-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-cloud-k8s-feign-demo</name>
    <description>spring-cloud-k8s-feign-demo</description>
    <properties>
        <java.version>1.8</java.version>
        <springcloud.kubernetes.version>1.0.1.RELEASE</springcloud.kubernetes.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-kubernetes-core</artifactId>
            <version>${springcloud.kubernetes.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-kubernetes-discovery</artifactId>
            <version>${springcloud.kubernetes.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-kubernetes-ribbon</artifactId>
            <version>${springcloud.kubernetes.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-commons</artifactId>
        </dependency>
        <dependency>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <groupId>org.springframework.cloud</groupId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>
        <dependency>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <groupId>org.springframework.cloud</groupId>
        </dependency>
    
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.SR3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
  2. 创建application.yml配置文件

    spring:
      application:
        name: spring-cloud-k8s-feign-demo
    
    product-infra-service:
      ribbon:
        KubernetesNamespace: spring-cloud-k8s-demo
    
    backend:
      ribbon:
        eureka:
          enabled: false
        client:
          enabled: true
        ServerListRefreshInterval: 5000
    
    hystrix:
      command:
        BackendCall:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 5000
      threadpool:
        BackendCallThread:
          coreSize: 5
    feign:
      hystrix:
        enabled: true
    server:
      port: 8082
    
    
    
  3. 启动类代码

    package com.example.springcloudk8sfeigndemo;
    
    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(basePackages = "com.example.springcloudk8sfeigndemo")
    public class SpringCloudK8sFeignDemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringCloudK8sFeignDemoApplication.class, args);
        }
    
    }
    
    
  4. feign接口代码

    package com.example.springcloudk8sfeigndemo;
    
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @FeignClient(name = "spring-cloud-k8s-discovery-demo", fallback = TestClientFallback.class)
    public interface TestClient {
    
        @RequestMapping("/services")
        String services();
    }
    
  5. fallback类代码

    package com.example.springcloudk8sfeigndemo;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class TestClientFallback implements TestClient {
        @Override
        public String services() {
            return "hystrix call back";
        }
    }
    
  6. controller接口

    package com.example.springcloudk8sfeigndemo;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class TestController {
    
        @Autowired
        private TestClient testClient;
    
        @GetMapping("test1")
        public String test1() {
            return testClient.services();
        }
    
    }
    
  7. 部署到k8s验证 (kubenetes.yaml可以参考服务发现)

    /app # curl http://localhost:8082/test1
    [spring-cloud-k8s-configmap-demo, spring-cloud-k8s-discovery-demo, spring-cloud-k8s-feign-demo], 2022-05-12 19:38:25
    /app #
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

写bug的路上

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值