spring-cloud-kubernetes的服务发现和轮询实战(含熔断)

public List 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 result = new ArrayList();

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(new Server(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(new Server(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 + “]”);

}

return result;

}

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

源码下载

如果您不打算写代码,也可以从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文件夹下,如下图红框所示:

spring-cloud-kubernetes的服务发现和轮询实战(含熔断)_第1张图片

下面是详细的编码过程;

开发和部署Account-Service服务

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

  1. 通过maven创建一个springboot应用,artifactId是account-service,pom.xml内容如下:

xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>

4.0.0

org.springframework.boot

spring-boot-starter-parent

2.1.1.RELEASE

com.bolingcavalry

account-service

0.0.1-SNAPSHOT

account-service

Demo project for Spring Cloud service provider run in kubernetes

1.8

2.1.1.RELEASE

false

false

false

3.5

2.8.2

2.18.1

2.21.0

3.5.37

2.1.1.RELEASE

org.springframework.boot

spring-boot-dependencies

pom

import

${spring-boot.version}

org.springframework.boot

spring-boot-starter

${springcloud.version}

org.springframework.boot

spring-boot-starter-web

${springcloud.version}

org.springframework.boot

spring-boot-maven-plugin

${spring-boot.version}

repackage

org.apache.maven.plugins

maven-deploy-plugin

${maven-deploy-plugin.version}

true

org.apache.maven.plugins

maven-surefire-plugin

${maven-surefire-plugin.version}

true

false

io.fabric8

fabric8-maven-plugin

${fabric8.maven.plugin.version}

fmp

resource

kubernetes

io.fabric8

fabric8-maven-plugin

${fabric8.maven.plugin.version}

fmp

resource

build

NodePort

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

  1. application.yml内容如下,依旧很简单:

spring:

application:

name: account-service

server:

port: 8080

  1. 对外提供服务的是AccountController ,方法getName返回了当前容器的hostname,方法health用于响应kubernetes的两个探针,方法ribbonPing用于响应使用了ribbon服务的调用方,它们会调用这个接口来确定当前服务是否正常:

@RestController

public class AccountController {

private static final Logger LOG = LoggerFactory.getLogger(AccountController.class);

private final String hostName = System.getenv(“HOSTNAME”);

/**

  • 探针检查响应类

  • @return

*/

@RequestMapping("/health")

public String health() {

return “OK”;

}

@RequestMapping("/")

public String ribbonPing(){

LOG.info(“ribbonPing of {}”, hostName);

return hostName;

}

/**

  • 返回hostname

  • @return 当前应用所在容器的hostname.

*/

@RequestMapping("/name")

public String getName() {

return this.hostName

  • ", "

  • new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”).format(new Date());

}

}

  1. 将上述工程的源码放在minikube机器上,确保maven设置正常,然后在pom.xml文件所在目录执行以下命令,即可编译构建工程并部署到kubernetes上:

mvn clean install fabric8: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/ in namespace 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 the command kubectl get pods -w to watch your 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 deployments

NAME READY UP-TO-DATE AVAILABLE AGE

account-service 1/1 1 1 69m

[root@minikube spring-cloud-k8s-account-service]# kubectl get services

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

account-service NodePort 10.105.157.201 8080:32596/TCP 69m

kubernetes ClusterIP 10.96.0.1 443/TCP 8d

  1. minikube的service命令可以得到指定服务的访问地址:

[root@minikube spring-cloud-k8s-account-service]# minikube service account-service --url

http://192.168.121.133:32596

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

  1. 用浏览器访问地址:http://192.168.121.133:32596/name ,如下图所示,可以正常访问account-service提供的服务:

spring-cloud-kubernetes的服务发现和轮询实战(含熔断)_第2张图片

现在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的依赖:

xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>

4.0.0

org.springframework.boot

spring-boot-starter-parent

2.1.1.RELEASE

com.bolingcavalry

web-service

0.0.1-SNAPSHOT

web-service

Demo project for Spring Cloud service consumer run in kubernetes

1.8

2.1.1.RELEASE

false

false

false

3.5

2.8.2

2.18.1

2.21.0

3.5.37

1.0.1.RELEASE

2.1.1.RELEASE

org.springframework.boot

spring-boot-dependencies

pom

import

${spring-boot.version}

org.springframework.cloud

spring-cloud-kubernetes-core

${springcloud.kubernetes.version}

org.springframework.cloud

spring-cloud-kubernetes-discovery

${springcloud.kubernetes.version}

org.springframework.cloud

spring-cloud-starter-kubernetes-ribbon

${springcloud.kubernetes.version}

org.springframework.cloud

spring-cloud-commons

${springcloud.version}

org.springframework.boot

spring-boot-starter

${springcloud.version}

org.springframework.boot

spring-boot-starter-web

${springcloud.version}

org.springframework.cloud

spring-cloud-starter-netflix-ribbon

${springcloud.version}

org.springframework.cloud

spring-cloud-starter-netflix-hystrix

${springcloud.version}

org.springframework.boot

spring-boot-maven-plugin

${spring-boot.version}

repackage

org.apache.maven.plugins

maven-deploy-plugin

${maven-deploy-plugin.version}

true

org.apache.maven.plugins

maven-surefire-plugin

${maven-surefire-plugin.version}

true

false

io.fabric8

fabric8-maven-plugin

${fabric8.maven.plugin.version}

fmp

resource

kubernetes

io.fabric8

fabric8-maven-plugin

${fabric8.maven.plugin.version}

fmp

resource

build

NodePort

  1. application.yml的内容如下,增加了熔断的配置:

spring:

application:

name: web-service

server:

port: 8080

backend:

ribbon:

eureka:

enabled: false

client:

enabled: true

ServerListRefreshInterval: 5000

hystrix.command.BackendCall.execution.isolation.thread.timeoutInMilliseconds: 5000

hystrix.threadpool.BackendCallThread.coreSize: 5

  1. 创建一个ribbon的配置类RibbonConfiguration:

package com.bolingcavalry.webservice;

import com.netflix.client.config.IClientConfig;

import com.netflix.loadbalancer.AvailabilityFilteringRule;

import com.netflix.loadbalancer.IPing;

import com.netflix.loadbalancer.IRule;

import com.netflix.loadbalancer.PingUrl;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Bean;

/**

  • @Description: ribbon配置类

  • @author: willzhao E-mail: [email protected]

  • @date: 2019/6/16 11:52

*/

public class RibbonConfiguration {

@Autowired

IClientConfig ribbonClientConfig;

/**

  • 检查服务是否可用的实例,

  • 此地址返回的响应的返回码如果是200表示服务可用

  • @param config

  • @return

*/

@Bean

public IPing ribbonPing(IClientConfig config){

return new Pin

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

gUrl();

}

/**

  • 轮询规则

  • @param config

  • @return

*/

@Bean

public IRule ribbonRule(IClientConfig config){

return new AvailabilityFilteringRule();

}

}

  1. 应用启动类如下,注意增加了服务发现、熔断、ribbon的配置,还定义了restTemplte实例,注意@LoadBalanced注解:

package com.bolingcavalry.webservice;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;

import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;

import org.springframework.cloud.netflix.ribbon.RibbonClient;

import org.springframework.context.annotation.Bean;

import org.springframework.web.client.RestTemplate;

@SpringBootApplication

@EnableDiscoveryClient

@EnableCircuitBreaker

@RibbonClient(name=“account-service”, configuration = RibbonConfiguration.class)

public class WebServiceApplication {

public static void main(String[] args) {

SpringApplication.run(WebServiceApplication.class, args);

}

@LoadBalanced

@Bean

RestTemplate restTemplate(){

return new RestTemplate();

}

}

你可能感兴趣的:(程序员,面试,java,后端)