spring-cloud-kubernetes的服务发现和轮询实战(含熔断)_程序员欣宸的博客-CSDN博客

标签: | 发表时间:2020-11-01 08:38 | 作者:
出处:https://xinchen.blog.csdn.net

本文是《spring-cloud-kubernetes实战系列》的第四篇,主要内容是在kubernetes上部署两个应用:Web-Service和Account-Service,通过spring-cloud-kubernetes提供的注册发现能力,实现Web-Service调用Account-Service提供的http服务;

系列文章列表

  1. 《spring-cloud-kubernetes官方demo运行实战》
  2. 《你好spring-cloud-kubernetes》
  3. 《spring-cloud-kubernetes背后的三个关键知识点》
  4. 《spring-cloud-kubernetes的服务发现和轮询实战(含熔断)》
  5. 《spring-cloud-kubernetes与SpringCloud Gateway》
  6. 《spring-cloud-kubernetes与k8s的configmap》

全文概览

本文由以下段落组成:

  1. 环境信息
  2. 常见的SpringCloud注册发现服务一览
  3. 分析kubernetes上如何实现服务注册发现
  4. 本章实战源码下载链接
  5. 实战开发Account-Service服务(服务提供方)
  6. 实战开发Web-Service服务(服务消费方)
  7. 扩容验证ribbon轮询能力
  8. 验证熔断能力

环境信息

本次实战的环境和版本信息如下:

  1. 操作系统:CentOS Linux release 7.6.1810
  2. minikube:1.1.1
  3. Java:1.8.0_191
  4. Maven:3.6.0
  5. fabric8-maven-plugin插件:3.5.37
  6. spring-cloud-kubernetes:1.0.1.RELEASE

上面的linux、minikube、java、maven,请确保已准备好,linux环境下minikube的安装和启动请参考 《Linux安装minikube指南 》

常见的SpringCloud注册发现服务一览

SpringCloud环境最重要的功能是注册发现服务,因此将SpringCloud应用迁移到kubernetes环境时,开发者最关心的问题是在kubernetes上如何将自身服务暴露出去,以及如何调用其他微服务。

先看看普通SpringCloud环境下的注册发现,下图来自spring官方博客,地址是: https://spring.io/blog/2015/07/14/microservices-with-spring,
在这里插入图片描述

由上图可见,应用Account-Service将自己注册到Eureka,这样Web-Service用"account-service"就能在Eureka找到Account-Service服务的地址,然后顺利发送RestFul请求到Account-Service,用上其提供的服务。

分析kubernetes上如何实现服务注册发现

如果将上面的Web-Service和Account-Service两个应用迁移到kubernetes上之后,注册发现机制变成了啥样呢?
第一种:沿用上图的方式,将Eureka也部署在kubernetes上,这样的架构和不用kubernetes时没有啥区别;
第二种,就是今天要实战的内容,使用spring-cloud-kubernetes框架,该框架可以调用kubernetes的原生能力来为现有SpringCloud应用提供服务,架构如下图所示:
在这里插入图片描述
上图表明,Web-Service应用在调用Account-Service应用的服务时,会用okhttp向API Server请求服务列表,API Server收到请求后会去etcd取数据返回给Web-Service应用,这样Web-Service就有了Account-Service的信息,可以向Account-Service的多个Pod轮询发起请求;

上图有个细节请注意:WebService应用并不是直接将请求发送给Account-Service在kubernetes创建的service,而是直接发送到具体的Pod上了,之所以具有这个能力,是因为spring-cloud-kubernetes框架通过service拿到了Account-Service对应的所有Pod信息(endpoint),此逻辑可以参考源码KubernetesServerList.java,如下所示:

      publicList<Server>getUpdatedListOfServers(){//用namespace和serviceId做条件,得到该服务对应的所有节点(endpoints)信息Endpoints endpoints=this.namespace!=null?this.client.endpoints().inNamespace(this.namespace).withName(this.serviceId).get():this.client.endpoints().withName(this.serviceId).get();List<Server>result=newArrayList<Server>();if(endpoints!=null){if(LOG.isDebugEnabled()){LOG.debug("Found ["+endpoints.getSubsets().size()+"] endpoints in namespace ["+this.namespace+"] for name ["+this.serviceId+"] and portName ["+this.portName+"]");}//遍历所有的endpoint,取出IP地址和端口,构建成Server实例,放入result集合中for(EndpointSubset subset:endpoints.getSubsets()){if(subset.getPorts().size()==1){EndpointPort port=subset.getPorts().get(FIRST);for(EndpointAddress address:subset.getAddresses()){result.add(newServer(address.getIp(),port.getPort()));}}else{for(EndpointPort port:subset.getPorts()){if(Utils.isNullOrEmpty(this.portName)||this.portName.endsWith(port.getName())){for(EndpointAddress address:subset.getAddresses()){result.add(newServer(address.getIp(),port.getPort()));}}}}}}else{LOG.warn("Did not find any endpoints in ribbon in namespace ["+this.namespace+"] for name ["+this.serviceId+"] and portName ["+this.portName+"]");}returnresult;}

理论分析已经完成,接下来就开始实战吧

源码下载

如果您不打算写代码,也可以从GitHub上下载本次实战的源码,地址和链接信息如下表所示:

名称 链接 备注
项目主页 https://github.com/zq2599/blog_demos 该项目在GitHub上的主页
git仓库地址(https) https://github.com/zq2599/blog_demos.git 该项目源码的仓库地址,https协议
git仓库地址(ssh) [email protected]:zq2599/blog_demos.git 该项目源码的仓库地址,ssh协议

这个git项目中有多个文件夹,本章的Account-Service源码在spring-cloud-k8s-account-service文件夹下,Web-Service源码在spring-cloud-k8s-web-service文件夹下,如下图红框所示:
在这里插入图片描述
下面是详细的编码过程;

开发和部署Account-Service服务

Account-Service服务是个很普通的springboot应用,和spring-cloud-kubernetes没有任何关系:

  1. 通过maven创建一个springboot应用,artifactId是account-service,pom.xml内容如下:
      <?xml version="1.0" encoding="UTF-8"?><projectxmlns="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.1.RELEASE</version><relativePath/><!-- lookup parent from repository --></parent><groupId>com.bolingcavalry</groupId><artifactId>account-service</artifactId><version>0.0.1-SNAPSHOT</version><name>account-service</name><description>Demo project for Spring Cloud service provider run in kubernetes</description><properties><java.version>1.8</java.version><spring-boot.version>2.1.1.RELEASE</spring-boot.version><maven-checkstyle-plugin.failsOnError>false</maven-checkstyle-plugin.failsOnError><maven-checkstyle-plugin.failsOnViolation>false</maven-checkstyle-plugin.failsOnViolation><maven-checkstyle-plugin.includeTestSourceDirectory>false</maven-checkstyle-plugin.includeTestSourceDirectory><maven-compiler-plugin.version>3.5</maven-compiler-plugin.version><maven-deploy-plugin.version>2.8.2</maven-deploy-plugin.version><maven-failsafe-plugin.version>2.18.1</maven-failsafe-plugin.version><maven-surefire-plugin.version>2.21.0</maven-surefire-plugin.version><fabric8.maven.plugin.version>3.5.37</fabric8.maven.plugin.version><springcloud.version>2.1.1.RELEASE</springcloud.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><type>pom</type><scope>import</scope><version>${spring-boot.version}</version></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>${springcloud.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>${springcloud.version}</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring-boot.version}</version><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin><plugin><!--skip deploy --><groupId>org.apache.maven.plugins</groupId><artifactId>maven-deploy-plugin</artifactId><version>${maven-deploy-plugin.version}</version><configuration><skip>true</skip></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>${maven-surefire-plugin.version}</version><configuration><skipTests>true</skipTests><!-- Workaround for https://issues.apache.org/jira/browse/SUREFIRE-1588 --><useSystemClassLoader>false</useSystemClassLoader></configuration></plugin><plugin><groupId>io.fabric8</groupId><artifactId>fabric8-maven-plugin</artifactId><version>${fabric8.maven.plugin.version}</version><executions><execution><id>fmp</id><goals><goal>resource</goal></goals></execution></executions></plugin></plugins></build><profiles><profile><id>kubernetes</id><build><plugins><plugin><groupId>io.fabric8</groupId><artifactId>fabric8-maven-plugin</artifactId><version>${fabric8.maven.plugin.version}</version><executions><execution><id>fmp</id><goals><goal>resource</goal><goal>build</goal></goals></execution></executions><configuration><enricher><config><fmp-service><type>NodePort</type></fmp-service></config></enricher></configuration></plugin></plugins></build></profile></profiles></project>

由上面的pom.xml内容可见,account-service应用是个简单的web应用,和SpringCloud、spring-cloud-kubernetes都没有任何关系,和其他springboot唯一的不同就是用到了fabric8-maven-plugin插件,可以方便的将应用部署到kubernetes环境;

  1. application.yml内容如下,依旧很简单:
      spring:application:name:account-serviceserver:port:8080
  1. 对外提供服务的是AccountController ,方法getName返回了当前容器的hostname,方法health用于响应kubernetes的两个探针,方法ribbonPing用于响应使用了ribbon服务的调用方,它们会调用这个接口来确定当前服务是否正常:
      @RestControllerpublicclassAccountController{privatestaticfinalLogger LOG=LoggerFactory.getLogger(AccountController.class);privatefinalString hostName=System.getenv("HOSTNAME");/**
     * 探针检查响应类
     * @return
     */@RequestMapping("/health")publicStringhealth(){return"OK";}@RequestMapping("/")publicStringribbonPing(){LOG.info("ribbonPing of {}",hostName);returnhostName;}/**
     * 返回hostname
     * @return 当前应用所在容器的hostname.
     */@RequestMapping("/name")publicStringgetName(){returnthis.hostName+", "+newSimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(newDate());}}
  1. 将上述工程的源码放在minikube机器上,确保maven设置正常,然后在pom.xml文件所在目录执行以下命令,即可编译构建工程并部署到kubernetes上:
      mvn cleaninstallfabric8:deploy -Dfabric8.generator.from=fabric8/java-jboss-openjdk8-jdk -Pkubernetes

执行成功后控制台输出如下:

      ...[INFO]Installing /usr/local/work/k8s/ribbon/spring-cloud-k8s-account-service/target/classes/META-INF/fabric8/kubernetes.json to /root/.m2/repository/com/bolingcavalry/account-service/0.0.1-SNAPSHOT/account-service-0.0.1-SNAPSHOT-kubernetes.json[INFO][INFO]<<<fabric8-maven-plugin:3.5.37:deploy(default-cli)<install@ account-service<<<[INFO][INFO][INFO]--- fabric8-maven-plugin:3.5.37:deploy(default-cli)@ account-service ---[INFO]F8: Using Kubernetes at https://192.168.121.133:8443/innamespace default with manifest /usr/local/work/k8s/ribbon/spring-cloud-k8s-account-service/target/classes/META-INF/fabric8/kubernetes.yml[INFO]Using namespace: default[INFO]Updating a Service from kubernetes.yml[INFO]Updated Service: target/fabric8/applyJson/default/service-account-service.json[INFO]Using namespace: default[INFO]Updating Deployment from kubernetes.yml[INFO]Updated Deployment: target/fabric8/applyJson/default/deployment-account-service.json[INFO]F8: HINT: Use thecommand`kubectl get pods -w`towatchyour pods start up[INFO]------------------------------------------------------------------------[INFO]BUILD SUCCESS[INFO]------------------------------------------------------------------------[INFO]Total time:  11.941 s[INFO]Finished at: 2019-06-16T19:00:51+08:00[INFO]------------------------------------------------------------------------
  1. 检查kubernetes上的部署和服务是否正常:
      [root@minikube spring-cloud-k8s-account-service]# kubectl get deploymentsNAME              READY   UP-TO-DATE   AVAILABLE   AGE
account-service   1/1     1            1           69m[root@minikube spring-cloud-k8s-account-service]# kubectl get servicesNAME              TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)AGE
account-service   NodePort    10.105.157.201<none>8080:32596/TCP   69m
kubernetes        ClusterIP   10.96.0.1<none>443/TCP          8d
  1. minikube的service命令可以得到指定服务的访问地址:
      [root@minikube spring-cloud-k8s-account-service]# minikube service account-service --urlhttp://192.168.121.133:32596

可见account-service的服务可以通过这个url访问: http://192.168.121.133:32596

  1. 用浏览器访问地址: http://192.168.121.133:32596/name,如下图所示,可以正常访问account-service提供的服务:
    在这里插入图片描述
    现在account-service服务已经就绪,接下来是开发和部署web-service应用。

开发和部署Web-Service服务

Web-Service服务是个springboot应用,用到了spring-cloud-kubernetes提供的注册发现能力,以轮询的方式访问指定服务的全部pod:

  1. 通过maven创建一个springboot应用,artifactId是web-service,pom.xml内容如下,要重点关注的是spring-cloud-starter-kubernetes-ribbon的依赖:
      <?xml version="1.0" encoding="UTF-8"?><projectxmlns="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.1.RELEASE</version><relativePath/><!-- lookup parent from repository --></parent><groupId>com.bolingcavalry</groupId><artifactId>web-service</artifactId><version>0.0.1-SNAPSHOT</version><name>web-service</name><description>Demo project for Spring Cloud service consumer run in kubernetes</description><properties><java.version>1.8</java.version><spring-boot.version>2.1.1.RELEASE</spring-boot.version><maven-checkstyle-plugin.failsOnError>false</maven-checkstyle-plugin.failsOnError><maven-checkstyle-plugin.failsOnViolation>false</maven-checkstyle-plugin.failsOnViolation><maven-checkstyle-plugin.includeTestSourceDirectory>false</maven-checkstyle-plugin.includeTestSourceDirectory><maven-compiler-plugin.version>3.5</maven-compiler-plugin.version><maven-deploy-plugin.version>2.8.2</maven-deploy-plugin.version><maven-failsafe-plugin.version>2.18.1</maven-failsafe-plugin.version><maven-surefire-plugin.version>2.21.0</maven-surefire-plugin.version><fabric8.maven.plugin.version>3.5.37</fabric8.maven.plugin.version><springcloud.kubernetes.version>1.0.1.RELEASE</springcloud.kubernetes.version><springcloud.version>2.1.1.RELEASE</springcloud.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><type>pom</type><scope>import</scope><version>${spring-boot.version}</version></dependency></dependencies></dependencyManagement><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><version>${springcloud.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>${springcloud.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>${springcloud.version}</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-ribbon</artifactId><version>${springcloud.version}</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId><version>${springcloud.version}</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring-boot.version}</version><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin><plugin><!--skip deploy --><groupId>org.apache.maven.plugins</groupId><artifactId>maven-deploy-plugin</artifactId><version>${maven-deploy-plugin.version}</version><configuration><skip>true</skip></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>${maven-surefire-plugin.version}</version><configuration><skipTests>true</skipTests><!-- Workaround for https://issues.apache.org/jira/browse/SUREFIRE-1588 --><useSystemClassLoader>false</useSystemClassLoader></configuration></plugin><plugin><groupId>io.fabric8</groupId><artifactId>fabric8-maven-plugin</artifactId><version>${fabric8.maven.plugin.version}</version><executions><execution><id>fmp</id><goals><goal>resource</goal></goals></execution></executions></plugin></plugins></build><profiles><profile><id>kubernetes</id><build><plugins><plugin><groupId>io.fabric8</groupId><artifactId>fabric8-maven-plugin</artifactId><version>${fabric8.maven.plugin.version}</version><executions><execution><id>fmp</id><goals><goal>resource</goal><goal>build</goal></goals></execution></executions><configuration><enricher><config><fmp-service><type>NodePort</type></fmp-service></config></enricher></configuration></plugin></plugins></build></profile></profiles></project>
  1. application.yml的内容如下,增加了熔断的配置:
      spring:application:name:web-serviceserver:port:8080backend:ribbon:eureka:enabled:falseclient:enabled:trueServerListRefreshInterval:5000hystrix.command.BackendCall.execution.isolation.thread.timeoutInMilliseconds:5000hystrix.threadpool.BackendCallThread.coreSize:5
  1. 创建一个ribbon的配置类RibbonConfiguration:
      packagecom.bolingcavalry.webservice;importcom.netflix.client.config.IClientConfig;importcom.netflix.loadbalancer.AvailabilityFilteringRule;importcom.netflix.loadbalancer.IPing;importcom.netflix.loadbalancer.IRule;importcom.netflix.loadbalancer.PingUrl;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.context.annotation.Bean;/**
 * @Description: ribbon配置类
 * @author: willzhao E-mail: [email protected]
 * @date: 2019/6/16 11:52
 */publicclassRibbonConfiguration{@AutowiredIClientConfig ribbonClientConfig;/**
     * 检查服务是否可用的实例,
     * 此地址返回的响应的返回码如果是200表示服务可用
     * @param config
     * @return
     */@BeanpublicIPingribbonPing(IClientConfig config){returnnewPingUrl();}/**
     * 轮询规则
     * @param config
     * @return
     */@BeanpublicIRuleribbonRule(IClientConfig config){returnnewAvailabilityFilteringRule();}}
  1. 应用启动类如下,注意增加了服务发现、熔断、ribbon的配置,还定义了restTemplte实例,注意@LoadBalanced注解:
      packagecom.bolingcavalry.webservice;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;importorg.springframework.cloud.client.discovery.EnableDiscoveryClient;importorg.springframework.cloud.client.loadbalancer.LoadBalanced;importorg.springframework.cloud.netflix.ribbon.RibbonClient;importorg.springframework.context.annotation.Bean;importorg.springframework.web.client.RestTemplate;@SpringBootApplication@EnableDiscoveryClient@EnableCircuitBreaker@RibbonClient(name="account-service",configuration=RibbonConfiguration.class)publicclassWebServiceApplication{publicstaticvoidmain(String[]args){SpringApplication.run(WebServiceApplication.class,args);}@LoadBalanced@BeanRestTemplaterestTemplate(){returnnewRestTemplate();}}
  1. 远程调用account-service的http接口的逻辑被放进服务类AccountService中,注意URL中用的是服务名account-service:
      packagecom.bolingcavalry.webservice;importcom.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;importcom.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;importorg.springframework.web.client.RestTemplate;importjava.text.SimpleDateFormat;importjava.util.Date;/**
 * @Description: 这里面封装了远程调用account-service提供服务的逻辑
 * @author: willzhao E-mail: [email protected]
 * @date: 2019/6/16 12:21
 */@ServicepublicclassAccountService{@AutowiredprivateRestTemplate restTemplate;@HystrixCommand(fallbackMethod="getFallbackName",commandProperties={@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1000")})publicStringgetDataFromSpringCloudK8SProvider(){returnthis.restTemplate.getForObject("http://account-service/name",String.class);}/**
     * 熔断时调用的方法
     * @return
     */privateStringgetFallbackName(){return"Fallback"+", "+newSimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(newDate());}}
  1. 最后是响应web请求的WebServiceController类,这里面调用了AccountService的服务,这样我们从web发起请求后,web-service就会远程调用account-service的服务:
      packagecom.bolingcavalry.webservice;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;/**
 * @Description: 测试用的controller,会远程调用account-service的服务
 * @author: willzhao E-mail: [email protected]
 * @date: 2019/6/16 11:46
 */@RestControllerpublicclassWebServiceController{@AutowiredprivateAccountService accountService;/**
     * 探针检查响应类
     * @return
     */@RequestMapping("/health")publicStringhealth(){return"OK";}/**
     * 远程调用account-service提供的服务
     * @return 多次远程调返回的所有结果.
     */@RequestMapping("/account")publicStringaccount(){StringBuilder sbud=newStringBuilder();for(inti=0;i<10;i++){sbud.append(accountService.getDataFromSpringCloudK8SProvider()).append("<br>");}returnsbud.toString();}}
  1. 将上述工程的源码放在minikube机器上,确保maven设置正常,然后在pom.xml文件所在目录执行以下命令,即可编译构建工程并部署到kubernetes上:
      mvn cleaninstallfabric8:deploy -Dfabric8.generator.from=fabric8/java-jboss-openjdk8-jdk -Pkubernetes

执行成功后控制台输出如下:

      ...[INFO]Installing /usr/local/work/k8s/ribbon/spring-cloud-k8s-web-service/target/classes/META-INF/fabric8/kubernetes.json to /root/.m2/repository/com/bolingcavalry/web-service/0.0.1-SNAPSHOT/web-service-0.0.1-SNAPSHOT-kubernetes.json[INFO][INFO]<<<fabric8-maven-plugin:3.5.37:deploy(default-cli)<install@ web-service<<<[INFO][INFO][INFO]--- fabric8-maven-plugin:3.5.37:deploy(default-cli)@ web-service ---[INFO]F8: Using Kubernetes at https://192.168.121.133:8443/innamespace default with manifest /usr/local/work/k8s/ribbon/spring-cloud-k8s-web-service/target/classes/META-INF/fabric8/kubernetes.yml[INFO]Using namespace: default[INFO]Creating a Service from kubernetes.yml namespace default name web-service[INFO]Created Service: target/fabric8/applyJson/default/service-web-service.json[INFO]Using namespace: default[INFO]Creating a Deployment from kubernetes.yml namespace default name web-service[INFO]Created Deployment: target/fabric8/applyJson/default/deployment-web-service.json[INFO]F8: HINT: Use thecommand`kubectl get pods -w`towatchyour pods start up[INFO]------------------------------------------------------------------------[INFO]BUILD SUCCESS[INFO]------------------------------------------------------------------------[INFO]Total time:  12.792 s[INFO]Finished at: 2019-06-16T19:24:21+08:00[INFO]------------------------------------------------------------------------
  1. 检查kubernetes上的部署和服务是否正常:
      [root@minikube spring-cloud-k8s-web-service]# kubectl get deploymentsNAME              READY   UP-TO-DATE   AVAILABLE   AGE
account-service   1/1     1            1           109m
web-service       1/1     1            1           18m[root@minikube spring-cloud-k8s-web-service]# kubectl get svcNAME              TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)AGE
account-service   NodePort    10.105.157.201<none>8080:32596/TCP   109m
kubernetes        ClusterIP   10.96.0.1<none>443/TCP          8d
web-service       NodePort    10.99.211.179<none>8080:30519/TCP   18m
  1. minikube的service命令可以得到指定服务的访问地址:
      [root@minikube spring-cloud-k8s-web-service]# minikube service web-service --urlhttp://192.168.121.133:30519

可见web-service的服务可以通过这个url访问: http://192.168.121.133:30519

  1. 用浏览器访问地址: http://192.168.121.133:30519/account,如下图所示,页面上展示的内容都是web-service调用了account-service的接口返回的,证明kubernetes上的注册发现能力正常:
    在这里插入图片描述

扩容验证ribbon轮询能力

虽然web-service可以正常调用account-service的服务,但始终访问的是一个pod,接下来我们就对account-service的pod进行扩容,将数量调整为2个,看看web-service是否可以轮询调用每个account-service的pod:

  1. 执行以下命令即可将pod数量调整为2个:
      kubectl scale --replicas=2 deployment account-service
  1. 检查account-service的pod,发现已经有两个了(account-service-5554576647-m29xr和account-service-5554576647-zwwml):
      [root@minikube spring-cloud-k8s-web-service]# kubectl get podsNAME                               READY   STATUS    RESTARTS   AGE
account-service-5554576647-m29xr   1/1     Running   0          53m
account-service-5554576647-zwwml   1/1     Running   0          20s
web-service-6d775855c7-7lkvr       1/1     Running   0          29m
  1. 用浏览器访问地址: http://192.168.121.133:30519/account,如下图所示,account-sercice返回的hostname已经变成了两种,和前面查到的pod的name一致,可见web-service的确是通过ribbon轮询访问了多个account-service的pod:
    在这里插入图片描述

验证熔断能力

接下来验证web-service配置的熔断服务是否可以生效:

  1. 执行以下命令将account-service的deployment删除:
      kubectl delete deployment account-service
  1. 再浏览器访问地址: http://192.168.121.133:30519/account,如下图所示,页面上的"Fallback"是配置的熔断方法返回的内容,可见熔断配置已经生效:
    在这里插入图片描述
  2. 再回到web-service的pom.xml所在位置执行以下命令,这样会重新构建部署一次web-service服务:
      mvn cleaninstallfabric8:deploy -Dfabric8.generator.from=fabric8/java-jboss-openjdk8-jdk -Pkubernetes
  1. 再浏览器访问地址: http://192.168.121.133:30519/account,如下图所示,服务成功恢复:
    在这里插入图片描述

至此,spring-cloud-kubernetes的服务发现和轮询实战(含熔断)就全部完成了,利用API Server提供的信息,spring-cloud-kubernetes将原生的kubernetes服务带给了SpringCloud应用,帮助传统微服务更好的融合在kubernetes环境中,如果您也在考虑将应用迁移到kubernetes上,希望本文能给您一些参考。


相关 [spring cloud kubernetes] 推荐:

Spring Cloud Kubernetes指南

- -
当我们构建微服务解决方案时,SpringCloud和Kubernetes都是最佳解决方案,因为它们为解决最常见的挑战提供组件. 但是,如果我们决定选择Kubernetes作为我们的解决方案的主要容器管理器和部署平台,我们仍然可以主要通过SpringCloudKubernetes项目使用SpringCloud的有趣特性.

拥抱Kubernetes,再见了Spring Cloud - 简书

- -
相信很多开发者在熟悉微服务工作后,才发现:. 以为用 Spring Cloud 已经成功打造了微服务架构帝国,殊不知引入了 k8s 后,却和 Cloud Native 的生态发展脱轨. 从 2013 年的 Spring Boot. 2012年10月,Mike Youngstrom在Spring jira中创建了一个功能需求,要求在Spring框架中支持无容器Web应用程序体系结构.

spring cloud项目改造为spring-cloud-kubernetes项目_水中加点糖-CSDN博客

- -
(一)基础k8s yaml脚本发布. (二)helm+shell脚本优化大量冗余配置发布. (三)jenkins用户审核的流水化方式部署. (四)service mesh(istio)服务网格化发布. (五)istio对项目进行金丝雀部署. spring-cloud-kubernetes之开发环境搭建.

Spring Cloud 使用 Kubernetes 作为注册中心_HelloWood-CSDN博客

- -
Spring Cloud 可以使用 Kubernetes 作为注册中心,实现服务注册和发现. 创建两个应用,Consumer 和 Provider,Provider 提供一个 REST 接口供 Consumer 调用. 指定服务的名称,用于实现调用. 添加  @EnableDiscoveryClient启用服务发现.

部署微服务的时候,Spring Cloud 和 Kubernetes 哪个更好? - DockOne.io

- -
【编者的话】本文比较了当下最火热的两大微服务开发平台:Spring Cloud和Kubernetes的优缺点,并指出结合二者的优点来组合使用,将在微服务旅程上获得更大成功. 当我们需要部署微服务的时候,哪个更好. Spring Cloud还是Kubernetes. 答案是都可以,只是各自有其优势. Kubernetes都宣称自己是开发和运行微服务的最佳环境,但是它们的本质非常不一样,所追求的目标也不同.

大话 Spring Cloud

- - IT瘾-dev
研究了一段时间spring boot了准备向spirng cloud进发,公司架构和项目也全面拥抱了Spring Cloud. 在使用了一段时间后发现Spring Cloud从技术架构上降低了对大型系统构建的要求,使我们以非常低的成本(技术或者硬件)搭建一套高效、分布式、容错的平台,但Spring Cloud也不是没有缺点,小型独立的项目不适合使用.

Spring Cloud限流详解 | Spring Cloud|周立

- -
限流往往是一个绕不开的话题. 本文详细探讨在Spring Cloud中如何实现限流. Zuul上实现限流是个不错的选择,只需要编写一个过滤器就可以了,关键在于如何实现限流的算法. 常见的限流算法有漏桶算法以及令牌桶算法. https://www.cnblogs.com/LBSer/p/4083131.html,写得通俗易懂,你值得拥有,我就不拽文了.

spring-cloud-kubernetes的服务发现和轮询实战(含熔断)_程序员欣宸的博客-CSDN博客

- -
本文是《spring-cloud-kubernetes实战系列》的第四篇,主要内容是在kubernetes上部署两个应用:Web-Service和Account-Service,通过spring-cloud-kubernetes提供的注册发现能力,实现Web-Service调用Account-Service提供的http服务;.

使用istio对spring cloud kubernetes项目进行金丝雀发布_水中加点糖-CSDN博客_istio springcloud

- -
(一)基础k8s yaml脚本发布. (二)helm+shell脚本优化大量冗余配置发布. (三)jenkins用户审核的流水化方式部署. (四)service mesh(istio)服务网格化发布. (五)istio对项目进行金丝雀部署. spring-cloud-kubernetes之开发环境搭建.

spring cloud kubernetes在pod模式下服务调用源码解析_水中加点糖-CSDN博客

- -
之所以只看pod模式下的服务调用链路,是因为在service模式下不会走缓存,效率低,并且负载均衡模式不能由spring cloud框架所控制,不太灵活. feign调用时用的org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient中的execute方法调用的.