关于Sidecar Pattern
本文转载自关于Sidecar Pattern
导语
Sidecar 是一个很纠结的名字,我们在翻译技术雷达时采用了一个比较通俗的翻译,即边车,而这个词随着微服务的火热与 Service Mesh 的逐渐成熟而进入人们的视野。虽然很多企业在自己的后台应用中已经大量的使用了 Sidecar,但是也是没有意识到这是一个极为有用的 pattern,今天我们就来聊一聊。
什么是 Sidecar 与 Sidecar pattern?
Sidecar 直接表示就是挎斗摩托车,也就是常说的“三蹦子”,如果你经常玩吃鸡,你一定不陌生。在“三蹦子”中,往往有个挎子,它不提供动力,但是也是这个机动装置的一个重要的组成部分,如果坐着一个妹子就可以给开车的你喂水果。
sidecar
我们目前很多程序都是奔着 Cloud Native 的目标去的,我们的代码注定是要跑在云上的,当有人问我如果我要做到 Cloud Native 时,有没有合适的学习资料之类的时,我会考虑如果你是有一定经验的开发者,并且对 Design Pattern 有一些了解,那么你非常适合这本来自微软 P & P Group 的书 Cloud Design Patterns,虽然这本书很简单,实例也不多,但是更多的是启发性。我也是在 Cloud Design Pattern 这本书中学到了很多,sidecar 也是其中之一,并且我们写了很多很多 Sidecar 用于管理自己的 Service Mesh 。
[Pattern is] a solution to a problem in a context.
为什么你需要 Sidecar?
非常简单,想象一下你要编写一堆 Web Service API,使用 JSON 作为数据格式暴露给前端,这个应用程序是用最常见的 Spring Boot 编写的,然后你要把他丢在你的虚拟机或者 k8s 上,你除了写代码,还需要考虑什么?
- DNS
- 反向代理
- 服务发现
- 服务注册
- 负载均衡
- HTTPS
- 弹性
- 日志
- 性能监控 APM
- 警报
- 终端安全
- 获取配置
- 等等
很多同事都对这些事情嗤之以鼻,毕竟大多数人的核心工作还是写代码,把应用做起来,至于这些事情是 ops 做的事儿,或者工程师可以做一部分,比如配置日志、给端点加个证书配置等等。于是我问一个朋友,Spring Boot 自带的 server 你知道怎么配证书和日志,那么 node express 呢?那么 on rails 呢?那么 play framework 呢?特别是当你决心要实现微服务架构的时候,这些看起来比较麻烦又很简单的事儿,反倒最消耗人,我们不希望给每个服务都做一遍,但是又不得不做一遍。所以,sidecar 的出现可以让我们以更优雅的方式解决这个事情,刚才我们提到的大量的功能都可以用 out-of-process 的方式实现,比如说反向代理。
Ruby 的 Unicorn Server 是一个很好的 Rack 容器,但是它对慢连接很敏感,而且不是很好处理 access log,熟悉 NGINX 的你一定想到了,如果我在虚拟机上开启一个 NGINX 进程,并且将 443 端口暴露出去,然后在这个 NGINX 中配置好 access log 与证书,并且将收到的请求使用 linux socket 的方式转发给 unicorn(或者直接走 docker network),这样我的 unicorn server 不就很简单了,我甚至都不需要配置。这样的一个 NGINX 就是一个 sidecar,它实现了访问记录、端点安全、进程隔离、并且轻量。你的应用程序不用再在乎这些,大约长得像这样:
server {
listen 80;
...
location / {
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Request-Start "t=\${msec}";
proxy_set_header Host \$http_host;
proxy_redirect off;
proxy_pass http://backend;
...
再举一个例子,我们每个应用程序都会记录日志,而我们并不希望日志保存在每台机器上或者容器中,我们希望每个应用是不产生任何状态的。但是这很难,我们必须开发所谓的日志收集系统,并且相关的日志组件,往往我们只能兼顾一两个流行语言或平台,例如 Java 与 JavaScript,而且我们还得维护这些东西,直到公司倒闭。有没有更优雅的解决办法呢?答案是有,在 12 factor app: logs 中,我们希望以事件流的方式去处理日志,如果我的应用把日志丢到 stdout 与 stderr 中,然后有人来自动收集,归档并发送到日志中心呢?这就是日志收集器,这也是一个 sidecar。
Sidecar 核心思想
Sidecar 不是应用程序的必要组成部分,当你使用 docker-compose 在本地启动一个小服务做开发测试的时候,Sidecar 并不会起作用,所以它不影响你的核心功能。但是,Sidecar 在真正的生产环境中,是和你的应用程序绑定在一起的,应用在哪里启动,它就出现在哪里。我们的应用不论是在虚拟机或者是在容器中,每一个应用的实体,都有大量的 sidecar 来做这种与核心功能无关的活儿。
每个“三蹦子”都有自己的 sidecar,每个 sidecar 都是紧紧的 attach 到它的“三蹦子”上的。
没有上容器云之前的 Sidecar 例子
那么,引用并修改一下 sidecar 的特性
- Sidecar 是独立于其应用程序之外的,不使用应用程序的运行环境与编程语言。比如你可以使用 JavaScript 去做日志收集器,而不用关心应用程序用的什么语言,你们使用进程通信的方式或者更粗暴的流
- Sidecar 是可以访问一些相同的系统资源的,和应用程序一样。这样你才能进行系统监控与收集程序的健康数据。但是也有一些数据是在应用程序内打桩,然后暴露出去的比如 transaction
- Sidecar 实际上对性能的损失非常小,特别是使用了容器化技术后,本来启动容器就是很廉价的事情,而且使用 docker image 发布 sidecar 让这个事情成本更低
- Sidecar 同样可以进行应用程序扩展,比如说,我们可以将 circuit breaker 实现在 sidecar 中,这样就可以避免代码中使用各种 circuit breaker 的实现,你的代码依旧可以简单的 RestTemplate 去做你想做的事儿,也不用担心下游服务的实效,导致串联失效的问题
Sidecar 的适合场景
如果你们公司已经开始使用微服务架构,践行了小组自治,那么大量的应用程序会用各种流行语言编写,并且使用了各种不同的框架,那么 Sidecar 就是你一定要考虑的。使用 out-of-process 的方式封装共有的一些功能,让应用程序变得简单,而这些共有的功能,最理想的情况下就是部署脚本中的一些配置。
Sidecar 在微服务领域是服务治理的重要工具,也是实现 Service Mesh 的必备工具,在 Service Mesh 的概念下,我们希望提供一层额外的抽象来保证服务的简单、可以相互调用,并且帮助我们轻松的解决服务发现、服务调用、服务监控、服务注册等等功能,这额外的一层可以通过 sidecar 来实现。不论是 Istio 还是 conduit 很多关键功能就是这么实现的。当然,很多情况下我们还是会自己去写适合自己组织架构的 sidecar,之前我们提到的 NGINX 与日志收集器就是一些很好的例子。而之前我们列举出一个 Web Service 可能会需要的功能,也有一部分是根据你的云平台进行裁剪的,比如负载均衡和弹性,完全可以使用 AWS 的 ELB 与 AutoScaling 来解决。
那么什么时候不适用呢?
- 应用程序过小,或者成本问题:如果没有使用微服务架构或者你的程序就一个 MVC App 就解决了,那就不需要使用 sidecar,毕竟开发成本很高
- 对性能要求极高:进程间通信还是有成本的,有时也是会有显著的延迟或者被阻塞;docker network 的性能也是赶不上进程间通信的,所以如果你的应用有小于毫秒级别的性能要求的话,这个 sidecar 不适合你
Sidecar 与 DevOps
我在与别人聊 Sidecar 时,很多朋友觉得这个东西的难点不在于创建一个又一个的 sidecar,而是在于如何在部署时,按照应用程序的要求将 sidecar 与应用程序紧紧的组合在一起。这是非常难的,首先每个企业使用的平台并不相同,每个企业的部署方式也不一样,这是没有通用解的问题,只能按照现有情况。在之前我们使用 aws ec2 + docker 时,我们会在 ec2 的 launch config 中去启动不同的 docker image 并且配置其 docker network,但这是一种比较低效的做法,因为只是使用 docker image 来封装你的产出物,而不是使用其作为秒级开启的容器。但是如果在 k8s 上做这件事儿,我们更倾向于在一个容器中把应用的事情做好,很难做到每个应用所运行的容器上都有 attached sidecars。所以这个话题没有好的回答,只能说是 It depends。
Reference
- https://docs.microsoft.com/en-us/azure/architecture/patterns/
- https://rubygems.org/gems/unicorn/versions/5.1.0
- https://www.nginx.com/blog/what-is-a-service-mesh/
- https://12factor.net
- https://istio.io/
- https://github.com/runconduit/conduit
- https://martinfowler.com/bliki/CircuitBreaker.html
- http://www.baeldung.com/rest-template
关于Sidecar Pattern的更多相关文章
- image management in kubernet
Image How can I edit an existing docker image metadata? docker-copyedit Registry Disk kubevirtis a g ...
- Kubernetes与容器设计模式
目录贴:Kubernetes学习系列 在程序设计领域,面向对象设计和面向对象语言是大家最为熟悉和强大的工具,而面向对象除了其强大的核心特性之外,还有人们通过实践总结出来的一系列设计模式,可以用来解决实 ...
- 《Kubernetes与云原生应用》系列之容器设计模式
http://www.infoq.com/cn/articles/kubernetes-and-cloud-native-app-container-design-pattern <Kubern ...
- k8s管理pod资源对象(上)
一.容器于pod资源对象 现代的容器技术被设计用来运行单个进程时,该进程在容器中pid名称空间中的进程号为1,可直接接收并处理信号,于是,在此进程终止时,容器即终止退出.若要在一个容器中运行多个进程, ...
- docker,容器,编排,和基于容器的系统设计模式
目录 从容器说起 背景 docker实现原理 编排之争 基于容器的分布式系统设计之道 单节点协作模式 Sidecar pattern(边车模式) Ambassador pattern(外交官模式) A ...
- 浅析 Dapr 里的云计算设计模式
Dapr 实际上是把分布式系统 与微服务架构实践的挑战以及k8s 这三个主题的全方位的设计组合,特别是Kubernetes设计模式 一书作者Bilgin Ibryam 提出的Multi-Runtime ...
- k8s sidecar, Ambassador, Adapter containers
When you start thinking in terms of Pods, there are naturally some general patterns of modular appli ...
- K8S 使用 SideCar 模式部署 Filebeat 收集容器日志
对于 K8S 内的容器日志收集,业内一般有两种常用的方式: 使用 DaemonSet 在每台 Node 上部署一个日志收集容器,用于收集当前 Node 上所有容器挂载到宿主机目录下的日志 使用 Sid ...
- 按照Enterprise Integration Pattern搭建服务系统
在前一篇文章中,我们已经对Enterprise Integration Pattern中所包含的各个组成进行了简单地介绍.限于篇幅(20页Word以内),我并没有深入地讨论各个组成.但是如果要真正地按 ...
随机推荐
- Golang内建库学习笔记(1)-sort和container
sort库 利用sort.Sort进行排序须实现如下接口 type Interface interface { // 获取数据集合元素个数 Len() int // 如果i索引的数据小于j所以的数据, ...
- 将文件转成byte[]文件属组
/** * * @Description : 读取文件数组 * @Method_Name : fileBuff * @param filePath * @return * @throws IOExce ...
- 入坑wsl
用了一个月的mac os, 又回归windows了, mac确实好看, 终端配合iterm2也很舒服, 奈何终究我们不合适...生态毕竟没有windows那么丰富; 切回windows最无法忍受的就是 ...
- python内置常量是什么?
摘要:学习Python的过程中,我们会从变量常量开始学习,那么python内置的常量你知道吗? 一个新产品,想熟悉它,最好的办法就是查看说明书! 没错,Python也给我们准备了这样的说明书--Pyt ...
- Codeforces Round #666 (Div. 2)
比赛链接:https://codeforces.com/contest/1397 A. Juggling Letters 题意 给出 $n$ 个字符串,可在字符串间任意移动字母,问最终能否使这 $n$ ...
- 【洛谷 p3383】模板-线性筛素数(数论)
题目:给定一个范围N,你需要处理M个某数字是否为质数的询问(每个数字均在范围1-N内).(N<=10000000,M<=100000) 解法:1.欧拉筛O(n),数组近乎100KB:2.( ...
- Andrew算法(我确实不懂Graham)
先解释一下:这两个算法分别都是凸包问题的算法,然后Andrew是Graham的变种,速度更快,更稳定,非常优秀,介于我已经把Graham写的莫名其妙的WA了,所以我选择了这种算法! 我认为在这里,还是 ...
- 【noi 2.2_7891】一元三次方程求解(二分枚举+输出程序运行时间)
对于noi上的题有2种解法: 1.数据很小(N=100),可以直接打for循环枚举和判断. 2.不会"三分",便用二分.利用"两根相差>=1"和 f(x1 ...
- Educational DP Contest G - Longest Path (dp,拓扑排序)
题意:给你一张DAG,求图中的最长路径. 题解:用拓扑排序一个点一个点的拿掉,然后dp记录步数即可. 代码: int n,m; int a,b; vector<int> v[N]; int ...
- nginx的log、upstream和server
一.log 首先一个log格式化的例子. #配置格式main的log log_format main '$host $status [$time_local] $remote_addr [$time_ ...