consul的service mesh功能初体验

|作者简介

consul之前一直被当成一个服务发现、分布式KV服务、服务健康检查服务等,但此前发布的1.2版本,宣称其实现了Service Mesh方案。而今年被称为Service Mesh的关键之年,就在这里跟大家分享一下自己的研究结果。

|试用consul的service mesh

升级consul至1.2版本

macOS下升级consul很简单,简单用brew命令就好

brew update consul

为了方便后面修改consul的配置文件,添加一个 -config-dir参数

/usr/local/opt/consul/homebrew.mxcl.consul.plist

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0">  <dict>    <key>KeepAlive</key>    <dict>      <key>SuccessfulExit</key>      <false/>    </dict>    <key>Label</key>    <string>homebrew.mxcl.consul</string>    <key>ProgramArguments</key>    <array>      <string>/usr/local/opt/consul/bin/consul</string>      <string>agent</string>      <string>-dev</string>      <string>-advertise</string>      <string>127.0.0.1</string>      <string>-config-dir</string>      <string>/usr/local/etc/consul.d</string>    </array>    <key>RunAtLoad</key>    <true/>    <key>WorkingDirectory</key>    <string>/usr/local/var</string>    <key>StandardErrorPath</key>    <string>/usr/local/var/log/consul.log</string>    <key>StandardOutPath</key>    <string>/usr/local/var/log/consul.log</string>  </dict></plist>

这个配置文件中,我添加了以下两行:

<string>-config-dir</string><string>/usr/local/etc/consul.d</string>

写两个模拟的微服务

用golang写两个小程序,用以模拟两个微服务。

service1.go

package mainimport (    "net/http"    "log"    "io")func TestServer(w http.ResponseWriter, req *http.Request) {    resp, err := http.Get("http://127.0.0.1:8082/test2")    if resp != nil && resp.Body != nil {        defer resp.Body.Close()    }    if err != nil {        w.Write([]byte("make request failed\n"))        return    }    io.Copy(w, resp.Body)}func main() {    http.HandleFunc("/test1", TestServer)    err := http.ListenAndServe(":8081", nil)    if err != nil {        log.Fatal("ListenAndServe: ", err)    }}

service2.go

package mainimport (    "io"    "net/http"    "log")func TestServer(w http.ResponseWriter, req *http.Request) {    io.WriteString(w, "hello, world!\n")}func main() {    http.HandleFunc("/test2", TestServer)    err := http.ListenAndServe(":8082", nil)    if err != nil {        log.Fatal("ListenAndServe: ", err)    }}

这里模拟微服务 service1调用 service2

在consul里配置两个服务

在consul的配置文件目录下新建两个json文件,用来配置上述两个服务。

/usr/local/etc/consul.d/01_service1.json:

{    "service": {      "name": "service1",      "port": 8081,      "connect": {        "proxy": {          "config": {            "upstreams": [{               "destination_name": "service2",               "local_bind_port": 38082            }]          }        }      }    }  }

/usr/local/etc/consul.d/01_service2.json:

{    "service": {      "name": "service2",      "port": 8082,      "connect": {        "proxy": {        }      }    }  }

然后执行命令重新加载consul的配置

consul reload

修改service1中引用service2的代码:

......func TestServer(w http.ResponseWriter, req *http.Request) {    //resp, err := http.Get("http://127.0.0.1:8082/test2")    resp, err := http.Get("http://127.0.0.1:38082/test2")    if resp != nil && resp.Body != nil {        defer resp.Body.Close()    }    if err != nil {        w.Write([]byte("make request failed\n"))        return    }    io.Copy(w, resp.Body)}......

跑起来啦

将service1、service2跑起来,然后用curl命令访问service1

> go run service1.go &> /dev/null> go run service2.go &> /dev/null> curl http://127.0.0.1:8081/test1# 如果出现以下输出,则说明一切正常,Bingo!hello, world!

|其它玩法

除了Service Mesh的玩法,consul 1.2还提供了SDK的用法。简单来说就是Go语言开发的微服务按照它的规范修改服务提供方、服务消费方的代码,服务间的调用将会自动使用底层的connect隧道。这个使用方法不太符合service mesh的初衷,做过微服务框架sdk的我不是太喜欢,这里就不详细讲了,可以参考官方给出的文档。

Connect Native原理

Connect Native Go语言项目改造指引

|consul的service mesh原理分析

其实consul的文档本身说的比较明白,这里结合consul-ui及代码大概分析一下。

当给consul的服务配置里添加了 "connect":{"proxy":{}}后,consul将会为每个服务实例创建一个专门的隧道代理,如下图所示:

隧道代理的作用是当以connect模式连入时,会自动建立一条到原服务实例的tcp隧道,后面tcp层以上的应用协议数据流将在这条tcp隧道上传输,具体代码在 https://github.com/hashicorp/consul/blob/master/connect/proxy/listener.go#NewPublicListener

而涉及服务间调用时,在consul服务配置里添加服务 UpstreamListener声明,服务消费方访问服务时需使用 UpstreamListener的地址。 UpstreamListener实际上是一个反向代理,当访问它时,它会以connect模式连接对应的服务实例 ConnectProxy,具体代码在 https://github.com/hashicorp/consul/blob/master/connect/proxy/listener.go#NewUpstreamListener

结合上述两条规则,整个数据链路就通了。

这里有一个问题,为啥一定要connect模式的隧道代理呢?反向代理服务不能直接连接原来的目标服务地址吗?

看了https://github.com/hashicorp/consul/blob/master/connect/service.go#Dial大概知道原因了。因为connect模式的隧道代理是使用TLS加密的,这样物理服务器节点之间的网络流量就走TLS安全连接了,再加上intentions机制,服务间的调用安全性上有了很大保障。还有一个原因,如果采用Connect-Native的方式集成consul的service mesh功能,底层连接是TLS,上层就可以很方便地走HTTP/2.0协议了。

|consul的service mesh优缺点分析

优点:

1. 直接使用tcp隧道,因此直接支持各类基于tcp的协议代理,如HTTP/1.1、HTTP/2.0、GRPC。

2. 实现原理简单, https://github.com/hashicorp/consul/blob/master/connect/ https://github.com/hashicorp/consul/tree/master/api/connect*.gohttps://github.com/hashicorp/consul/tree/master/agent/connect/下的关键文件不超过20个,逻辑很容易就看清了。

3. 直接结合consul做服务注册与服务发现,集成度高。

缺点:

1. 目前的负载均衡算法还很简单,就是随机,见下面:

2. 一些微服务框架的基本功能还不具备,如超时、重试、熔断、流量分配等,可以从 https://github.com/hashicorp/consul/blob/master/connect/proxy/listener.go#handleConn这里开始扩展。

3. 需要手动修改consul的服务配置;服务消费方要根据consul里的服务配置,修改调用其它服务的地址(这里跟service mesh的初衷有些不符)。

|总结

目前来看consul的service mesh方案还比较简单,功能很基本,但具备进一步扩展的空间,可以好好研究学习它的代码。

|参考

  1. https://www.hashicorp.com/blog/consul-1-2-service-mesh
  2. https://www.consul.io/intro/getting-started/connect.html
  3. https://www.consul.io/docs/agent/options.html
  4. https://www.consul.io/docs/connect/intentions.html
  5. https://www.consul.io/docs/connect/native.html
  6. https://www.consul.io/docs/connect/native/go.html
  7. https://www.consul.io/docs/connect/configuration.html
  8. https://www.consul.io/docs/connect/proxies.html
  9. https://www.consul.io/docs/connect/dev.html
  10. https://www.consul.io/docs/connect/ca/consul.html

原文发布于微信公众号 - 腾讯云TStack(gh_035269c8aa5f)

原文发表时间:2018-10-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏北京马哥教育

学了Python后,我走哪里都可以连WIFI!为什么?反正就是这么强!

? WIFI破解,Python程序员必学技能。WIFI已经完全普及,现在Python程序员没网,走到哪里都不怕!教你们一招,如何在图片中提取Python脚本代...

7189
来自专栏大宽宽的碎碎念

实现一个靠谱的Web认证两种认证JWT怎么存储认证信息防止CSRF总是使用https认证信息不应该永久有效总结一下

51710
来自专栏FreeBuf

如何利用Fluxion诱惑目标用户获取WPA密码

前言 由于ISP替代了易受攻击的路由器,供渗透测试人员选择的诸如Reaver这样的工具越来越少,对于特定的目标,哪些工具有用与否能够确定的也很少。而如果采用暴力...

3406
来自专栏实用工具入门教程

如何部署 MQTT 服务器

MQTT是一种机器到机器的消息传递协议,旨在为“物联网”设备提供轻量级的发布/订阅通信。Mosquitto是一种流行的MQTT服务器(或MQTT中的代理),具有...

2K4
来自专栏java达人

JWT VS Session

作者:Prosper Otemuyiwa 译者:java达人 来源:https://ponyfoo.com/articles/json-web-tokens-...

4646
来自专栏程序猿DD

研究consul的service mesh功能

来源:https://jeremy-xu.oschina.io/2018/07/%E7%A0%94%E7%A9%B6consul%E7%9A%84service...

2473
来自专栏源哥的专栏

基于linux的嵌入IPv4协议栈的内容过滤防火墙系统(8)-附录

0 通常用于分析操作系统。这一方法能够工作是因为在一些系统中“0”是无效端口,当你试图使用一种通常的闭合端口

842
来自专栏FreeBuf

关于C/S架构系统的安全监测

由于工作需求,需要对一大批C/S架构的系统进行测试,所以这几天一直在摸索怎么个套路法,踩过的坑就不发了,直接奔我个人的套路: C/S架构的系统,说最直白一点就是...

4238
来自专栏SpringBoot 核心技术

OAuth 2和JWT - 如何设计安全的API?

6292
来自专栏架构师小秘圈

互联网安全威胁及应对方案

作者:蒋海滔,阿里巴巴国际事业部,高级技术专家,爱好Java/JavaScript,长期关注高性能、并发编程以及Web安全。 来自:高可用架构(ID:ArchN...

4034

扫码关注云+社区

领取腾讯云代金券