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

微服务边车模式深度解析:赋能云原生应用的终极指南(自己搞一个简单SideCar?)通过使用 Sidecar 模式 我们能够实现对微服务架构的强化 也就是关注点分离 让你专注于开车 开好车 开快车

大家好,欢迎来到IT知识分享网。

什么是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

那根据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

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

一点小细节

  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

随之而来的改造

 - 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应用才可以。

 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可以独立于应用程序部署和更新,使得维护工作更加灵活。
一致性:在多个服务中应用相同的配置和策略,不需要在每个服务上单独配置。
扩展性:新增功能时,可以在不影响现有服务的情况下,在Sidecar中添加新的组件。
增强的能力:例如,集中日志处理、安全性控制、以及动态路由等。



缺点(Sidecar的通病):

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


参考

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

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/134555.html

(0)
上一篇 2025-07-11 16:20
下一篇 2025-07-11 16:26

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信