本文转载自关于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. 十三:SpringBoot-基于Yml配置方式,实现文件上传逻辑

    SpringBoot-基于Yml配置方式,实现文件上传逻辑 1.文件上传 2.搭建文件上传界面 2.1 引入页面模板Jar包 2.2 编写简单的上传页面 2.3 配置页面入口 3.SpringBoot ...

  2. Docker+Prometheus+Alertmanager+Webhook钉钉告警

    Docker+Prometheus+Alertmanager+Webhook钉钉告警 1.环境部署 1.1 二进制部署 1.2 docker部署 1.2.1 webhook 1.2.2 alertma ...

  3. jQuery——选择元素

    ###理解DOM jQuery最强大的特性之一就是能够简化在DOM中选择元素的任务.**DOM(文档对象模型)**充当了JavaScript与网页之间的接口,它以对象网络而非纯文本的形式来表现HTML ...

  4. Centos7服务器安装Docker及Docker镜像加速,Docker删除

    Centos7服务器安装Docker及Docker镜像加速,Docker删除 1.Centos7服务器安装Docker 1.1 root账户登录,查看内核版本如下 1.1.1 卸载服务器旧版本Dock ...

  5. Go语言学习-import

    import我们在写Go代码的时候经常用到import这个命令用来导入包文件,而我们经常看到的方式参考如下:import("fmt")然后我们代码里面可以通过如下的方式调用fmt. ...

  6. 深入理解Java虚拟机读书笔记 -- Java内存区域

    Graal VM: Run Programs Faster Anywhere. 跨语言全栈虚拟机,可以作为"任何语言"的运行平台使用. Java内存结构 程序计数器:线程私有,较小 ...

  7. Python: 捕获正在运行的CMD窗口内容

    最近需要捕获已经在运行的CMD窗口内容,并且需要根据指定输出内容来判断下一步的行动(输入指定内容). 尝试了很多次后,想到一个思路: 通过inspect.exe来获取CMD窗口Name信息通过uiau ...

  8. 2017-2018 ACM-ICPC, Asia Daejeon Regional Contest PART(10/12)

    $$2017-2018\ ACM-ICPC,\ Asia\ Daejeon\ Regional\ Contest$$ \(A.Broadcast\ Stations\) \(B.Connect3\) ...

  9. java中static修改成员变量和函数和其他使用

    一.通过static修饰的成员变量初始化只会初始化一次 //静态变量初始化只会初始化一次 public class zuishuai { public static void main(String[ ...

  10. java——字符串常量池、字符串函数以及static关键字的使用、数组的一些操作函数、math函数

    字符串常量池: 字符串比较函数:  字符串常用方法:  字符串截取函数: 字符串截取函数:  static关键字使用: 要调用类中的static类型的变量的时候,可以用"类名.变量名&quo ...