spring-cloud-kubernetes服务发现之在k8s环境下开发spring cloud应用
通常情况下,我们的线上的服务在迁移到k8s环境下的时候,都是采用平滑迁移的方案。服务治理与注册中心等都是采用原先的组件。比如spring cloud应用,在k8s环境下还是用原来的一套注册中心(如eureka),服务治理(hystrix,ribbon)等。但是当我们开发新的应用时,我们是可以借助于sping-cloud-kubernetes组件为我们提供的服务发现、负载均衡等来摈弃像eureka这样的注册中心。本文主要通过构建两个spring cloud 服务来演示spring-cloud-kubernetes组件如何做服务的发现,负载均衡等。
一、使用spring-cloud-kubernetes做服务发现
分别开发两个服务,服务提供者:product_infra_service, 并通过FeignClient的方式对外提供接口,供消费者调用。服务消费者:product_infra_consumer.
首先新建一个module:product-infra-service-api:该项目中配置pom文件的相关依赖如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency> <!--Service Interface API--> <!--Feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
</dependencies>
该项目中定义接口如下:
@FeignClient(name="${feign.product-infra.name:product-infra-service}",fallback = PropertyClientFallback.class)
public interface PropertyClient { @GetMapping(value="properties")
List<String> getProperties();
}
hystrix的fallback类定义如下:
@Component
public class PropertyClientFallback implements PropertyClient{ @Override
public List<String> getProperties() {
return new ArrayList<String>();
}
}
接下来,新建服务提供者 product-infra-service项目,在该项目中实现PropertyClient接口。pom文件依赖配置如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--Service Interface API-->
<dependency>
<groupId>com.maidao.center.product_infra</groupId>
<artifactId>product-infra-service-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<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>
</dependencies>
定义controller 类如下:
@RestController
@RequestMapping
public class PropertyController implements PropertyClient{ @GetMapping("properties")
public List<String> getProperties(){
ArrayList<String> properties = new ArrayList<>();
properties.add("properties1");
properties.add("properties2");
return properties;
} }
编译打包成镜像后将项目部署到k8s环境,并在k8s环境下定义服务pod实例所关联到的service:本例中定义k8s service name 为 product-infra-service(与定义的应用名相同).
新建消费者项目:product-infra-consumer,pom文件配置依赖如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency> <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-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> <!--Service Interface API-->
<dependency>
<groupId>com.maidao.center.product_infra</groupId>
<artifactId>product-infra-service-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
应用配置如下:
server:
port: 8080 product-infra-service:
ribbon:
KubernetesNamespace: ${namespace} (k8s namespace,实际根据自己服务部署的namespace配置对应的名字) 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
新建ProductInfraConsumerController类:通过PropertyClient的引用调用提供者提供的接口。
@RestController
@RequestMapping
public class ProductInfraConcumerController { @Autowired
private PropertyClient propertyClient; @GetMapping("properties")
public List<String> getProductProperties(){ return propertyClient.getProperties(); } }
可以看到代码没有变化,调用方式没有变化,在消费者项目中去掉了原先的EurekaClient发现服务的调用。服务发现机制采用的是,spring-cloud-kubernetes-discovery。负载均衡组件采用的是:spring-cloud-starter-kubernetes-ribbon。
最后将product-infra-consumer编译打包成镜像后,部署到k8s环境下。
最后通过curl 命令在k8s环境下调用product-infra-consumer的controller方法来测试服务之间的通信:如下所示:
[root@iZbp174tf9563rykf3bbjjZ ~]# curl http://172.30.28.100:8080/properties ["properties1","properties2"]
停掉product-infra-service服务,再次发起请求,降级fallback方法生效:
[root@iZbp174tf9563rykf3bbjjZ ~]# curl http://172.30.28.98:8080/properties []
可以看到在没有eureka注册中心的情况下,定义的两个服务能够正常通信,且代码不需要做任何变动,只需要在消费者服务中引入spring-cloud-kubernetes相关依赖即可,spring-cloud-kubernetes组件起到了服务发现以及负载均衡的作用。
二、spring-cloud-kubernetes 服务发现流程
spring-cloud-kubernetes框架提供了调用kubernetes的原生能力来为现有SpringCloud应用提供服务,架构如下图所示:
从上图可以看出product-infra-consumer在调用product-infra-service时,通过FeignClient组件拿到service name信息,最底层通过ok-http3,根据service name 调用 api server 获取该service下对应的Pod信息,拿到Pod信息后通过,轮询的方式向这些pod发送请求。spring-cloud-starter-kubernetes-ribbon组件中的KubernetesServerList 继承了 ribbon-loaderbanlancer组件中的AbstractServerList以及实现了 ServerList类中的方法,并通过 KubernetesClient提供的能力向k8s api server 发送请求信息。通过服务名获取pod信息的源码如下:
public List<Server> getUpdatedListOfServers() {
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 = new ArrayList<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 + "]");
}
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;
}
spring-cloud-kubernetes服务发现之在k8s环境下开发spring cloud应用的更多相关文章
- eclips环境下开发spring boot项目,application.properties配置文件下中文乱码解决方案
如以上,application.properties文件下中文乱码.发生乱码一般都是由于编码格式不一样导致的. 打开Window-Preferences-General-content Types-T ...
- Spring Cloud Eureka 服务发现 4.2
在微服务架构中,服务发现可以说是最为核心和基础的模块,该模块主要用于实现各个微服务实例的自动化注册与发现.在Spring Cloud的子项目中,Spring Cloud Netflix提供了Eur ...
- Kubernetes服务发现入门:如何高效管理服务?
愈发复杂的应用程序正在依靠微服务来保持可扩展性和提升效率.Kubernetes为微服务提供了完美的环境,并能够让其与Kubernetes的工具组件和功能兼容.当应用程序的每个部分放置在一个容器中,整个 ...
- 一文看懂 Kubernetes 服务发现: Service
Service 简介 K8s 中提供微服务的实体是 Pod,Pod 在创建时 docker engine 会为 pod 分配 ip,"外部"流量通过访问该 ip 获取微服务.但 ...
- Docker Kubernetes 服务发现原理详解
Docker Kubernetes 服务发现原理详解 服务发现支持Service环境变量和DNS两种模式: 一.环境变量 (默认) 当一个Pod运行到Node,kubelet会为每个容器添加一组环境 ...
- 【原创】K8S环境下研发如何本地调试?kt-connect使用详解
K8S环境下研发如何本地调试?kt-connect使用详解 背景 注:背景有点啰嗦,讲讲一路走来研发本地调试的变化,嫌烦的可以直接跳过,不影响阅读. 2019年 我在的公司当时是个什么情况,只有两个J ...
- 在非k8s 环境下 的应用 使用 Dapr Sidekick for .NET
在k8s 环境下,通过Operator 可以管理Dapr sidecar, 在虚拟机环境下,我们也是非常需要这样的一个管理组件,类似下图:在这张图片中,在上图左面,我们看到了"dapr.ex ...
- 【新书推荐】《ASP.NET Core微服务实战:在云环境中开发、测试和部署跨平台服务》 带你走近微服务开发
<ASP.NET Core 微服务实战>译者序:https://blog.jijiechen.com/post/aspnetcore-microservices-preface-by-tr ...
- 笔记:Spring Cloud Eureka 服务发现与消费
服务发现与消费,其服务发现的任务是由Eureka的客户端完成,而服务的消费任务由Ribbon.JerseyClient等完成,Ribbon是一个基于HTTP和TCP的客户端负载均衡器:使用Jersey ...
随机推荐
- c# 第31节 构造函数与析构函数、new关键字作用
本节内容: 1:构造和析构的简介 2:构造函数的定义和使用 3:new关键字的作用 4:析构函数的定义和使用 1:构造和析构的简介 2:构造函数的定义和使用 构造函数: 当实例化的一个对象,就默认执行 ...
- 目标检测中的pooling操作
1.SPPnet池化过程 假设这个feature map的尺寸是M*N*256,将这个feature map的每一个channel以4*4,2*2和1*1来划分格子,每个格子里面做max poolin ...
- Apex 企业设计模式
FFLIB 是一个免费的框架,对 Apex 进行了扩展.它的结构实现了 Salesforce 推荐的Apex 企业设计模式. 在学习如何使用 FFLIB 框架之前,我们先来了解一下 Apex 企业设计 ...
- bolb与base64的图片互转
直接看图简单明了. 注:便于测试你可以自己用base64图片测试互转一下.这里base64图片太长了就不给予展示了,望理解
- Note | Ubuntu
目录 0. 教程 1. 安装 2. 系统 0. 教程 <Linux就该这么学>:https://www.cnblogs.com/RyanXing/p/9462850.html 1. 安装 ...
- 深度解密Go语言之unsafe
目录 指针类型 什么是 unsafe 为什么有 unsafe unsafe 实现原理 unsafe 如何使用 获取 slice 长度 获取 map 长度 map 源码中的应用 Offsetof 获取成 ...
- vue与Element实际应用参考
https://www.cnblogs.com/dmcl/p/6722315.html https://www.cnblogs.com/hbb0b0/p/8399996.html https://ww ...
- 1+x 证书 Web 前端开发 MySQL 知识点梳理
官方QQ群 1+x 证书 Web 前端开发 MySQL 知识点梳理 http://blog.zh66.club/index.php/archives/199/
- JSONObject解析json数据
首先先看一下我们要解析的json数据是什么样子的: 代码: String url="http://113.57.190.228:8001/Web/Report/GetBigMSKReport ...
- KVM学习笔记--静态迁移
.静态迁移过程如下 (1)确定虚拟机关闭状态 (2)准备迁移oeltest02虚拟机,查看该虚拟机配置的磁盘文件 (3)导入虚拟机配置文件 [root@node1~]# virsh dumpxml o ...