微服务边车模式深度解析:赋能云原生应用的终极指南(自己搞一个简单SideCar?)

什么是SideCar?

file

Sidecar模式定义:

Sidecar 模式是一种常用于微服务架构中的设计模式,该模式允许将应用程序的核心功能与辅助功能(如日志记录、监控、配置管理、网络通信等)分离开来。在这种设计模式中,每个微服务主容器旁边都有一个“边车”(Sidecar)容器运行辅助功能,就像摩托车旁的边车一样,Sidecar 容器和主容器共享同一个生命周期和网络空间。

你专心开车,其他交给我。

file

整体Sidecar就是这样:

file

总结:把非核心业务杂七杂八的东西分离出来,微服务的关注点尽可能只在业务上面,减少业务开发的复杂度。

Sidecar主要干啥?

Sidecar模式通常会处理以下范围的功能:

  1. 网络通信

    • 代理和管理微服务之间的通信,例如用来处理进出的网络流量、服务发现、负载均衡、断路、重试和超时。
  2. 安全性

    • 实现安全协议,如TLS加密、认证、授权和密钥管理。
  3. 监控与日志记录

    • 收集和导出日志、性能度量指标和追踪信息,以供监控系统使用。
  4. 配置管理

    • 动态加载和管理配置数据,而无需重启应用程序。
  5. 故障处理和调试

    • 提供调试支持,记录崩溃报告和性能瓶颈。
  6. 健康检查

    • 周期性地检查主服务的健康,并可实施自我修复措施。
  7. API 网关或接口转换

    • 处理服务的REST或gRPC API,提供API网关功能,或者对老旧系统进行接口转换。
  8. 服务依赖抽象

    • 管理服务间的数据库连接、队列等系统资源的访问。
  9. 请求/响应转换

    • 对进出的请求或响应数据进行转换或扩展。

Sidecar有哪些实现?

Sidecar在容器化和微服务领域有很多实现:

1. Envoy

Envoy是一个开源的、高性能的边缘和服务代理,专门设计用于云原生应用环境。由Lyft公司首次开发发布,后来成为了Cloud Native Computing Foundation(CNCF)的一部分。它的设计允许它同时在应用程序的边缘和内部使用,作为边缘网关、负载均衡器或服务网格的一部分,以提高微服务之间的通信质量和效率。

file

  1. Istio
    Istio是一个开源的服务网格,用于连接、保护、控制和观察在Kubernetes集群中运行的服务。它为微服务提供一种统一的方式来管理网络通信,安全性,策略和观察性,无需改变应用本身的代码。Istio利用了Envoy代理,它作为Sidecar部署在每个服务的Pod中,拦截所有进出Pod的网络通信。
     

    file

    file

  2. Linkerd
    Linkerd是一个开源的服务网格,专门为云原生应用设计,用以在微服务架构中提供可靠的服务间通信。它提供关键功能,如服务发现、负载均衡、故障处理、请求路由和安全性,在不改动服务代码的情况下,使得服务更容易监控、管理和控制。Linkerd是由Buoyant公司开源的,并且是Cloud Native Computing Foundation(CNCF)的一部分。

    file

自己搞一个简单的?

我们个人势单力薄,搞一个像他们这么有高级功能的组件还是挺费时间的,况且我们还在温饱线上挣扎。

但是又想在这块搞点小事情,那么整个简单的。

先来个简单的需求

一个业务系统部署在k8s集群中,每个服务采用一个Pod一个服务的方式部署,每个Pod都有一个Service。

file


就这么简单来一下就可以了,Service关联Pod提供统一访问入口。

那根据SideCar的拓扑,我们可以在Service和Pod中容器之间加一个Sidecar来管理流量,像这样:

file

在这个拓扑中,所有流量先进SVC(逻辑上哈),然后转发给车最后转发给Pod。

车的具体需求?

  1. 管理HTTP流量(TCP的暂时不支持):只开发一个IP白名单规则。如果请求这个服务的IP不在这个白名单中,则返回404,否则转发该请求。
  2. 白名单规则配置:支持单个IP地址,支持CIDR地址。

需求就是这么简单,我们让SVC把流量先转给车,车处理了一下以后再转发给业务服务。

准备开干

首先开发一个HTTP服务器

使用Go built-in API就可以很简单开发实现一个HTTP服务器,就是使用net包:


    http.HandleFunc("/", handler)
    err = http.ListenAndServe(conf.Server.Addr, nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }

COPY

几行代码搞定,额,这还是有点快,让人猝不及防。那这样我们的HTTP服务器就搞定了

其次 读取配置文件

我们用yaml来定义白名单配置,白名单中有IP和CIDR地址。


whitelist:
  - 192.168.1.1
  - 192.168.1.2
  - 10.22.81.0/24
  - ::1

COPY

然后我们使用yaml解析库来读取它。

先来下载一下依赖库:


go get gopkg.in/yaml.v2

COPY

然后使用库提供的api来读取yaml文件:


type Conf struct {
    Server     Server     `yaml:"server"`
    Downstream Downstream `yaml:"downstream"`
    Whitelist  []string   `yaml:"whitelist"`
}

err = yaml.Unmarshal(source, &conf)
    if err != nil {
        log.Panic(err)
    }

COPY

设置HTTP的请求处理函数

我们请求处理函数从X-FORWARDED-FOR协议头来获取请求的Ip列表字符串,字符串以ip1,ip2,ip3,...来组成的。

我们只取第一个,就是上面示例的ip1,因为只有这个IP才表示请求方的IP,其他都是代理方的。

func handler(w http.ResponseWriter, r *http.Request) {
    ipStr := r.Header.Get("X-FORWARDED-FOR")
    if ipStr == "" {
        ipStr = strings.Split(r.RemoteAddr, ":")[0]
    } else {
        ipStr = strings.TrimSpace(strings.Split(ipStr, ",")[0])
    }

    // 如果IP地址在白名单中,那么就转发请求
    if ipInWhitelist(ipStr, conf.Whitelist) {
        serveReverseProxy(conf.Downstream.URL, w, r)
        return
    }

    // 否则返回404
    http.NotFound(w, r)
}

COPY

转发请求

Go内建包net实现了ReverseProxy,我们直接使用httputil.NewSingleHostReverseProxy就可以直接转发HTTP请求,很快~。


func serveReverseProxy(target string, w http.ResponseWriter, r *http.Request) {
    url, _ := url.Parse(target)

    proxy := httputil.NewSingleHostReverseProxy(url)

    r.URL.Host = url.Host
    r.URL.Scheme = url.Scheme
    r.Header.Set("X-Forwarded-Host", r.Header.Get("Host"))
    r.Host = url.Host

    proxy.ServeHTTP(w, r)
}

COPY

这样我们的核心功能就实现了。

一点小细节

实现了核心流程以后,我们还得关注配置中IP的解析。
Go的net 包也提供了IP地址和CIDR地址的解析,我们只需要调用一下

  1. net.ParseIP
  2. net.ParseCIDR
    就可以实现IP解析了。

transformToCIDR 这个函数就给IP地址增加/32转换成CIDR形式,大家可以不用太关注。


func ipInWhitelist(ipStr string, whitelist []string) bool {

    ip := net.ParseIP(ipStr)
    for _, cidr := range whitelist {
        _, ipNet, err := net.ParseCIDR(transformToCIDR(cidr))
        if err != nil {
            return false
        }
        if ipNet.Contains(ip) {
            return true
        }
    }
    return false
}

COPY

部署

开发这个简单的需求一百多行代码就可以搞定了,但是部署怎么办?

我们在k8s中不是有Service嘛,我们Service在配置流量转发规则的时候先转到我们的HTTP Server,然后我们HTTP再转发给业务服务。

Pod改造

原来我们的拓扑是这样的:

file

加上我们自己的sidecar就变成这样了:

file

随之而来的改造

k8s Pod支持一个Pod多个Container,所以我们可以直接在Pod中增加一个Container:
比如:原来我们的Pod定义是这样的:


        - name: my-order-app
          image: my-registry-domain-name/ my-order-app:${my-order-app-version}
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080

COPY

改造后:


      containers:
        - name: sidecar
          image: my-registry-domain-name/my-custom-sidecar:latest
          imagePullPolicy: Always
          ports:
            - containerPort: 8081
        - name: my-order-app
          image: my-registry-domain-name/ my-order-app:${my-order-app-version}
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080

COPY

Pod的改造就完成了,接下来就是Service改造了。

Service改造

我们要把Service的目标端口改成我们自己的Sidecar应用才可以。

比如:原来我们的Service是这样的:
Service端口为8080,转发到app的8080端口中。


apiVersion: v1
kind: Service
metadata:
  name: my-order-app-service
  namespace: my-app
  labels:
    app: my-order-app
spec:
  ports:
    - name: my-order-http
      port: 8080
      protocol: TCP
      targetPort: 8080
  selector:
    app: my-order-app
  type: ClusterIP

COPY

现在我们要把Target改成8081,也就是我们的Sidecar HTTP服务器端口。


apiVersion: v1
kind: Service
metadata:
  name: my-order-app-service
  namespace: my-app
  labels:
    app: my-order-app
spec:
  ports:
    - name: my-order-http
      port: 8080
      protocol: TCP
      targetPort: 8081
  selector:
    app: my-order-app
  type: ClusterIP

COPY

这样我们的Sidecar就搞定了。

总结

通过使用Sidecar模式,我们能够实现对微服务架构的强化,也就是关注点分离,让你专注于开车,开好车,开快车。
它提供了一种有效的方式去分摊微服务的辅助功能(如日志记录、监控、配置管理、网络通信等),而无需改动微服务的核心业务逻辑。这带来了显著的优点,包括简化开发复杂度、增强服务的可维护性和可伸缩性,以及提供了横切关注点(cross-cutting concerns)的统一管理。

优点

关注点分离:通过将非核心功能从应用程序逻辑中分离出来,开发者可以更专注于业务逻辑。
可插拔性:Sidecar可以独立于应用程序部署和更新,使得维护工作更加灵活。
一致性:在多个服务中应用相同的配置和策略,不需要在每个服务上单独配置。
扩展性:新增功能时,可以在不影响现有服务的情况下,在Sidecar中添加新的组件。
增强的能力:例如,集中日志处理、安全性控制、以及动态路由等。

缺点(Sidecar的通病):

资源使用:每个Sidecar都会消耗额外的计算和内存资源,这可能导致资源的浪费。
复杂性:虽然单个服务的复杂性降低了,但整体架构可能会因为增加的组件而变得复杂。
调试困难:由于Sidecar模式涉及多个容器协同工作,调试和追踪问题可能比传统单体应用更加困难。
网络延迟:每个请求都要通过Sidecar代理,可能会增加网络延迟。

参考

微服务侧车模式深度解析:赋能云原生应用的终极指南(自己搞一个简单SideCar?) – 小厂程序员

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/542931.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

回归预测 | Matlab基于RIME-SVR霜冰算法优化支持向量机的数据多输入单输出回归预测

回归预测 | Matlab基于RIME-SVR霜冰算法优化支持向量机的数据多输入单输出回归预测 目录 回归预测 | Matlab基于RIME-SVR霜冰算法优化支持向量机的数据多输入单输出回归预测预测效果基本描述程序设计参考资料 预测效果 基本描述 1.Matlab基于RIME-SVR霜冰算法优化支持向量机的数…

【数据结构】习题之消失的数字和轮转数组

👑个人主页:啊Q闻 🎇收录专栏:《数据结构》 🎉前路漫漫亦灿灿 前言 消失的数字这道题目我会和大家分享三种思路。 还有一道题目是轮转数组,,也会分享三种思路,大…

照片和视频一键换脸,ROOP ROPE FaceFusion 中文版汉化版整合包下载安装

AI 人脸替换工具离线版下载地址:点击下载 AI 人脸替换工具离线版,将视频和图片的面孔替换为您选择的面孔。您只需要一张所需脸部的图像。没有数据集,就没有训练。工具包含 ROOP ROPE FaceFusion 三款人脸替换工具解压即用无需安装。 汉化整合…

【SpringBoot实战篇】注册接口

💕🌸🍀开发接口的流程:明确需求 -》阅读接口文档-》思路分析-》开发-》测试🍀🌸💕 开始前小知识-配置lombok👈🍀 lombok 在编译阶段,为实体类自动生成setter getter toSt…

教你将配置好的conda环境迁移到其它设备

文章目录 问题分析存在的方法环境要求方法步骤1. 下载conda pack2. 打包原环境3. 新设备还原环境4. 查看环境 问题分析 好不容易配置好的conda环境,要在另一个设备上运行,还要重新配置,好麻烦。 存在的方法 pip install -r requirement.txt …

一.表单校验

为什么要表单验证? 是为了减轻服务器的压力,让用户体验更好,保证输入的数据符合要求 常用的表单验证 日期格式 表单元素是否为空 用户名和密码 E-mail 地址 身份证号码 实现验证的思路 问题:当输入的表单数据不符合要求时&…

【在线服务,如何做网络加速】

为什么需要 ToC的业务,由于服务直接提供给用户使用,所以对服务的时延,平响要求比较高。如果因为跨地域的网络传输而造成较高时延,而用户有感的话体验不好,这个时候则需要做网络加速。 服务网络加速 开始之前 先考虑…

下单后快团团团长如何隐藏跟团人/团员/顾客的信息?

一、功能说明 有的团长不希望展示顾客跟单购买的信息,可以通过设置显示匿名头像微信名匿名隐藏。 二、具体操作步骤 在团购设置中点击“更多团购设置”,再点击“隐私设置”,在这里可以设置跟团人的展示信息。 注意1: 当跟团人显…

unity动画的关键帧添加event-同步语音

在iclone中做的语音嘴型动画,因是用下图自带的方式语音生成的动画,而不是用plugin(面捕live会连同语音一起导出),所以导出来到Unity中,之后口型、动作、表情等没有声音。 我需要把原有的语音也重新在unity中加载上,原来…

【HTML】简单制作一个唱片动画效果

目录 前言 开始 HTML部分 CSS部分 效果图 总结 前言 无需多言,本文将详细介绍一段代码,具体内容如下: 开始 首先新建文件夹,创建两个文本文档,其中HTML的文件名改为[index.html],CSS的…

python+playwright 学习-88 禁止加载图片等资源

前言 对于爬虫的小伙伴来说,有时候只需抓取页面的文本,不用加载图片,可以加快操作页面速度,那么我们可以设置禁止加载图片等资源。 禁止图片加载 根据url地址的后缀,图片资源后缀一般是png,jpg,jpeg,gif等格式。 from playwright.sync_api import sync_playwrightwith…

二叉树例题分享

文章目录 二叉树例题分享[235. 二叉搜索树的最近公共祖先](https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/)[701. 二叉搜索树中的插入操作](https://leetcode.cn/problems/insert-into-a-binary-search-tree/)[108. 将有序数组转换为二叉搜索树…

Pixel 手机上连接提示受阻,无法上网-解决方法

命令行中输入 adb shell settings delete global captive_portal_https_urladb shell settings delete global captive_portal_http_url输入服务器信息 adb shell settings put global captive_portal_http_url http://connect.rom.miui.com/generate_204adb shell settings …

【Canvas与艺术】绘制方形斜纹生化危险Biohazard标志

【关键点】 绘制切角矩形、三角形比较费工&#xff0c;有时间可以把相关代码做成函数。 【成果图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <…

【Golang学习笔记】从零开始搭建一个Web框架(四)

文章目录 模板渲染静态文件支持HTML 模板渲染 错误恢复完结撒花~~ 前情提示&#xff1a; 【Golang学习笔记】从零开始搭建一个Web框架&#xff08;一&#xff09;-CSDN博客 【Golang学习笔记】从零开始搭建一个Web框架&#xff08;二&#xff09;-CSDN博客 【Golang学习笔记】从…

ChatGLM3初体验

mac本地化部署ChatGLM3 写在前面环境准备1. python环境2. 安装第三方依赖torch3.下载模型 代码准备1.clone代码 run效果 写在前面 建议直接去看官方文档 https://github.com/THUDM/ChatGLM3?tabreadme-ov-file 环境准备 1. python环境 python -V ## 3.11.42. 安装第三方依…

怎么提升公众号上限

正常可以申请多少个公众号&#xff1f;目前如果我们是企业主体的话&#xff08;包括个体户&#xff09;&#xff0c;申请公众号默认是可以申请2个公众号数量的。不过对于很多公司来说&#xff0c;2个公众号的数量肯定是远远不够用的&#xff0c;不同的产品不同品牌不同部门都可…

倍增法学习

这里i为开始下标&#xff0c;j是2的次幂

OSPF 开放式最短路径优先协议

目录 技术产生原因&#xff1a;因为RIP存在不足 OSPF优点&#xff1a; RIPV2和OSPFV2比较&#xff1a; 相同点&#xff1a; 不同点&#xff1a; OSPF的结构化部署 --- 区域划分 区域划分的主要目的&#xff1a; 区域边界路由器 --- ABR &#xff1a; 区域划分的要求&am…

医疗图像分割 | 基于Pyramid-Vision-Transformer算法实现医疗息肉分割

项目应用场景 面向医疗图像息肉分割场景&#xff0c;项目采用 Pytorch Pyramid-Vision-Transformer 深度学习算法来实现。 项目效果 项目细节 > 具体参见项目 README.md (1) 模型架构 (2) 项目依赖&#xff0c;包括 python 3.8、pytorch 1.7.1、torchvision 0.8.2(3) 下载…