本文转载自关于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

关于Sidecar Pattern的更多相关文章

  1. image management in kubernet

    Image How can I edit an existing docker image metadata? docker-copyedit Registry Disk kubevirtis a g ...

  2. Kubernetes与容器设计模式

    目录贴:Kubernetes学习系列 在程序设计领域,面向对象设计和面向对象语言是大家最为熟悉和强大的工具,而面向对象除了其强大的核心特性之外,还有人们通过实践总结出来的一系列设计模式,可以用来解决实 ...

  3. 《Kubernetes与云原生应用》系列之容器设计模式

    http://www.infoq.com/cn/articles/kubernetes-and-cloud-native-app-container-design-pattern <Kubern ...

  4. k8s管理pod资源对象(上)

    一.容器于pod资源对象 现代的容器技术被设计用来运行单个进程时,该进程在容器中pid名称空间中的进程号为1,可直接接收并处理信号,于是,在此进程终止时,容器即终止退出.若要在一个容器中运行多个进程, ...

  5. docker,容器,编排,和基于容器的系统设计模式

    目录 从容器说起 背景 docker实现原理 编排之争 基于容器的分布式系统设计之道 单节点协作模式 Sidecar pattern(边车模式) Ambassador pattern(外交官模式) A ...

  6. 浅析 Dapr 里的云计算设计模式

    Dapr 实际上是把分布式系统 与微服务架构实践的挑战以及k8s 这三个主题的全方位的设计组合,特别是Kubernetes设计模式 一书作者Bilgin Ibryam 提出的Multi-Runtime ...

  7. k8s sidecar, Ambassador, Adapter containers

    When you start thinking in terms of Pods, there are naturally some general patterns of modular appli ...

  8. K8S 使用 SideCar 模式部署 Filebeat 收集容器日志

    对于 K8S 内的容器日志收集,业内一般有两种常用的方式: 使用 DaemonSet 在每台 Node 上部署一个日志收集容器,用于收集当前 Node 上所有容器挂载到宿主机目录下的日志 使用 Sid ...

  9. 按照Enterprise Integration Pattern搭建服务系统

    在前一篇文章中,我们已经对Enterprise Integration Pattern中所包含的各个组成进行了简单地介绍.限于篇幅(20页Word以内),我并没有深入地讨论各个组成.但是如果要真正地按 ...

随机推荐

  1. Golang内建库学习笔记(1)-sort和container

    sort库 利用sort.Sort进行排序须实现如下接口 type Interface interface { // 获取数据集合元素个数 Len() int // 如果i索引的数据小于j所以的数据, ...

  2. 将文件转成byte[]文件属组

    /** * * @Description : 读取文件数组 * @Method_Name : fileBuff * @param filePath * @return * @throws IOExce ...

  3. 入坑wsl

    用了一个月的mac os, 又回归windows了, mac确实好看, 终端配合iterm2也很舒服, 奈何终究我们不合适...生态毕竟没有windows那么丰富; 切回windows最无法忍受的就是 ...

  4. python内置常量是什么?

    摘要:学习Python的过程中,我们会从变量常量开始学习,那么python内置的常量你知道吗? 一个新产品,想熟悉它,最好的办法就是查看说明书! 没错,Python也给我们准备了这样的说明书--Pyt ...

  5. Codeforces Round #666 (Div. 2)

    比赛链接:https://codeforces.com/contest/1397 A. Juggling Letters 题意 给出 $n$ 个字符串,可在字符串间任意移动字母,问最终能否使这 $n$ ...

  6. 【洛谷 p3383】模板-线性筛素数(数论)

    题目:给定一个范围N,你需要处理M个某数字是否为质数的询问(每个数字均在范围1-N内).(N<=10000000,M<=100000) 解法:1.欧拉筛O(n),数组近乎100KB:2.( ...

  7. Andrew算法(我确实不懂Graham)

    先解释一下:这两个算法分别都是凸包问题的算法,然后Andrew是Graham的变种,速度更快,更稳定,非常优秀,介于我已经把Graham写的莫名其妙的WA了,所以我选择了这种算法! 我认为在这里,还是 ...

  8. 【noi 2.2_7891】一元三次方程求解(二分枚举+输出程序运行时间)

    对于noi上的题有2种解法: 1.数据很小(N=100),可以直接打for循环枚举和判断. 2.不会"三分",便用二分.利用"两根相差>=1"和 f(x1 ...

  9. Educational DP Contest G - Longest Path (dp,拓扑排序)

    题意:给你一张DAG,求图中的最长路径. 题解:用拓扑排序一个点一个点的拿掉,然后dp记录步数即可. 代码: int n,m; int a,b; vector<int> v[N]; int ...

  10. nginx的log、upstream和server

    一.log 首先一个log格式化的例子. #配置格式main的log log_format main '$host $status [$time_local] $remote_addr [$time_ ...