五分钟 k8s入门到实战--跨服务调用

背景
在做传统业务开发的时候,当我们的服务提供方有多个实例时,往往我们需要将对方的服务列表保存在本地,然后采用一定的算法进行调用;当服务提供方的列表变化时还得及时通知调用方。
student:
url:
- 192.168.1.1:8081
- 192.168.1.2:8081
这样自然是对双方都带来不少的负担,所以后续推出的服务调用框架都会想办法解决这个问题。
以 spring cloud 为例:

服务提供方会向一个服务注册中心注册自己的服务(名称、IP等信息),客户端每次调用的时候会向服务注册中心获取一个节点信息,然后发起调用。
但当我们切换到 k8s 后,这些基础设施都交给了 k8s 处理了,所以 k8s 自然得有一个组件来解决服务注册和调用的问题。
也就是我们今天重点介绍的 service。
service
在介绍 service 之前我先调整了源码:
func main() {
http.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) {
name, _ := os.Hostname()
log.Printf("%s ping", name)
fmt.Fprint(w, "pong")
})
http.HandleFunc("/service", func(w http.ResponseWriter, r *http.Request) {
resp, err := http.Get("http://k8s-combat-service:8081/ping")
if err != nil {
log.Println(err)
fmt.Fprint(w, err)
return
}
fmt.Fprint(w, resp.Status)
})
http.ListenAndServe(":8081", nil)
}
新增了一个 /service 的接口,这个接口会通过 service 的方式调用服务提供者的服务,然后重新打包。
make docker
同时也新增了一个 deployment-service.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: k8s-combat-service # 通过标签选择关联
name: k8s-combat-service
spec:
replicas: 1
selector:
matchLabels:
app: k8s-combat-service
template:
metadata:
labels:
app: k8s-combat-service
spec:
containers:
- name: k8s-combat-service
image: crossoverjie/k8s-combat:v1
imagePullPolicy: Always
resources:
limits:
cpu: "1"
memory: 100Mi
requests:
cpu: "0.1"
memory: 10Mi
---
apiVersion: v1
kind: Service
metadata:
name: k8s-combat-service
spec:
selector:
app: k8s-combat-service # 通过标签选择关联
type: ClusterIP
ports:
- port: 8081 # 本 Service 的端口
targetPort: 8081 # 容器端口
name: app
使用相同的镜像部署一个新的 deployment,名称为 k8s-combat-service,重点是新增了一个kind: Service 的对象。
这个就是用于声明 service 的组件,在这个组件中也是使用 selector 标签和 deployment 进行了关联。
也就是说这个 service 用于服务于名称等于 k8s-combat-service 的 deployment。
下面的两个端口也很好理解,一个是代理的端口, 另一个是 service 自身提供出去的端口。
至于 type: ClusterIP 是用于声明不同类型的 service,除此之外的类型还有:
NodePortLoadBalancerExternalName
等类型,默认是ClusterIP,现在不用纠结这几种类型的作用,后续我们在讲到Ingress的时候会具体介绍。
负载测试
我们先分别将这两个 deployment 部署好:
k apply -f deployment/deployment.yaml
k apply -f deployment/deployment-service.yaml
❯ k get pod
NAME READY STATUS RESTARTS AGE
k8s-combat-7867bfb596-67p5m 1/1 Running 0 3h22m
k8s-combat-service-5b77f59bf7-zpqwt 1/1 Running 0 3h22m
由于我新增了一个 /service 的接口,用于在 k8s-combat 中通过 service 调用 k8s-combat-service 的接口。
resp, err := http.Get("http://k8s-combat-service:8081/ping")
其中 k8s-combat-service 服务的域名就是他的服务名称。
如果是跨 namespace 调用时,需要指定一个完整名称,在后续的章节会演示。
我们整个的调用流程如下:

相信大家也看得出来相对于 spring cloud 这类微服务框架提供的客户端负载方式,service 是一种服务端负载,有点类似于 Nginx 的反向代理。
为了更直观的验证这个流程,此时我将 k8s-combat-service 的副本数增加到 2:
spec:
replicas: 2
只需要再次执行:
❯ k apply -f deployment/deployment-service.yaml
deployment.apps/k8s-combat-service configured
service/k8s-combat-service unchanged

不管我们对
deployment的做了什么变更,都只需要apply这个yaml文件即可, k8s 会自动将当前的deployment调整为我们预期的状态(比如这里的副本数量增加为 2);这也就是k8s中常说的声明式 API。
可以看到此时 k8s-combat-service 的副本数已经变为两个了。
如果我们此时查看这个 service 的描述时:
❯ k describe svc k8s-combat-service |grep Endpoints
Endpoints: 192.168.130.133:8081,192.168.130.29:8081
会发现它已经代理了这两个 Pod 的 IP。

此时我进入了 k8s-combat-7867bfb596-67p5m 的容器:
k exec -it k8s-combat-7867bfb596-67p5m bash
curl http://127.0.0.1:8081/service
并执行两次 /service 接口,发现请求会轮训进入 k8s-combat-service 的代理的 IP 中。
由于 k8s service 是基于 TCP/UDP 的四层负载,所以在 http1.1 中是可以做到请求级的负载均衡,但如果是类似于 gRPC 这类长链接就无法做到请求级的负载均衡。
换句话说 service 只支持连接级别的负载。
如果要支持 gRPC,就得使用 Istio 这类服务网格,相关内容会在后续章节详解。
总结
总的来说 k8s service 提供了简易的服务注册发现和负载均衡功能,当我们只提供 http 服务时是完全够用的。
相关的源码和 yaml 资源文件都存在这里:
https://github.com/crossoverJie/k8s-combat
五分钟 k8s入门到实战--跨服务调用的更多相关文章
- SpringCloud微服务之跨服务调用后端接口
SpringCloud微服务系列博客: SpringCloud微服务之快速搭建EurekaServer:https://blog.csdn.net/egg1996911/article/details ...
- spring cloud 入门系列五:使用Feign 实现声明式服务调用
一.Spring Cloud Feign概念引入通过前面的随笔,我们了解如何通过Spring Cloud ribbon进行负责均衡,如何通过Spring Cloud Hystrix进行服务断路保护,两 ...
- 五分钟快速搭建 Serverless 免费邮件服务
1. 引言 本文将带你快速基于 Azure Function 和 SendGrid 构建一个免费的Serverless(无服务器)的邮件发送服务,让你感受下Serverless的强大之处. 该服务可以 ...
- 五分钟快速搭建Serverless免费邮件服务
1. 引言 本文将带你快速基于 Azure Function 和 SendGrid 构建一个免费的Serverless(无服务器)的邮件发送服务,让你感受下Serverless的强大之处. 该服务可以 ...
- nginx入门与实战 安装 启动 配置nginx Nginx状态信息(status)配置 正向代理 反向代理 nginx语法之location详解
nginx入门与实战 网站服务 想必我们大多数人都是通过访问网站而开始接触互联网的吧.我们平时访问的网站服务 就是 Web 网络服务,一般是指允许用户通过浏览器访问到互联网中各种资源的服务. Web ...
- Sping Boot入门到实战之实战篇(一):实现自定义Spring Boot Starter——阿里云消息队列服务Starter
在 Sping Boot入门到实战之入门篇(四):Spring Boot自动化配置 这篇中,我们知道Spring Boot自动化配置的实现,主要由如下几部分完成: @EnableAutoConfigu ...
- Spring Cloud实战之初级入门(六)— 服务网关zuul
目录 1.环境介绍 2.api网关服务 2.1 创建工程 2.3 api网关中使用token机制 2.4 测试 2.5 小结 3.一点点重要的事情 1.环境介绍 好了,不知不觉中我们已经来到了最后一篇 ...
- SpringCloud实战之初级入门(二)— 服务注册与服务调用
目录 1.环境介绍 2.服务提供 2.1 创建工程 2.2 修改配置文件 2.3 修改启动文件 2.5 亲测注意事项 3.服务调用 3.1 创建工程 3.2 修改配置文件 3.3 修改启动文件 3.4 ...
- 五分钟给你的 gRPC服务 加上 HTTP 接口
gRPC 服务要加 HTTP 接口? go-zero 给大家带来极简的 RESTful 和 gRPC 服务开发体验的同时,社区又给我们提出了新的期望: 我想只写一次代码 既要 gRPC 接口 也要 H ...
- Nginx入门到实战
location 语法 location 有”定位”的意思, 根据Uri来进行不同的定位. 在虚拟主机的配置中,是必不可少的,location可以把网站的不同部分,定位到不同的处理方式上. 比如, 碰 ...
随机推荐
- 如何让别人访问你本地允许的Vue本地项目
步骤一: 将config/index.js 中的host: localhost 改为 host:'0.0.0.0'步骤二:在package.json 将scripts 下面的dev 后 ...
- 企业battle宝典Q1 每一个身处于抑郁与困难的朋友必看!
里面有看不懂的可以留言,我会解释!
- Android-NDK开发——基本概念
在Android开发中,有时候出于安全,性能,代码共用的考虑,需要使用C/C++编写的库.虽然在现代化工具链的支持下,这个工作的难度已经大大降低,但是毕竟万事开头难,初学者往往还是会遇到很多不可预测的 ...
- 大数据实战手册-开发篇之pycharm远程开发调试
2.1 pycharm远程开发调试 2.1.1 python版本一致 #版本都保持3.6.6 #root cd /usr/local/python3/bin/pip3 list 备注:[python模 ...
- mysql截取函数,拼接函数,大写函数例子
题目:这题目是牛客网sql题,因为牵扯到3个函数,都是自己没怎么用过的,所以记录一下. 答案:是别人的解题思路 可以看出在mysql中提供的函数可以供我们使用来操作字段,非常的方便
- 【Java】并行执行任务
在实际的应用上,我们平时需要调用第三方的接口,可能会调用多个接口,串行执行的话, 就需要等待所有的接口调用完成之后才获取到结果,那我们有没有并行的方法的呢? 串行执行 以下是三个接口,假设他们额的执行 ...
- 项目完成小结:使用Blazor和gRPC开发大模型客户端
前言 先介绍下这个项目. 最近我一直在探索大语言模型,根据不同场景训练了好几个模型,为了让用户测试使用,需要开发前端. 这时候,用 Gradio 搭建的前端是不太够的,虽说 GitHub 上也有一堆开 ...
- 2021-7-12 VUE的组件认识
VUE组件简单实例 <!DOCTYPE html> <html> <head> <title> </title> </head> ...
- XCTF-favorite_number
题目 (xctf.org.cn) 判断,既要数组强等于,又要首元素不等:php有下标越界溢出漏洞,因此0可以通过整型溢出得到 绕过if判断 playload:stuff[4294967296]=adm ...
- DHorse v1.3.0 发布,基于k8s的发布平台
综述 DHorse是一个简单易用.以应用为中心的云原生DevOps系统,具有持续集成.持续部署.微服务治理等功能,无需安装依赖Docker.Maven.Node等环境即可发布Java.Vue.Reac ...