背景

MySQL库A 到 MySQL库B的增量数据同步需求

DolphinScheduler中配置DataX MySQL To MySQL工作流

工作流定义

工作流定义 > 创建工作流 > 拖入1个SHELL组件 > 拖入1个DATAX组件
SHELL组件(文章)
脚本

echo '文章同步 MySQL To MySQL'

DATAX组件(t_article)
用到2个插件mysqlreader^[1]、mysqlwriter^[2]
选 自定义模板:

{
    "job": {
        "content": [
            {
                "reader": {
                    "name": "mysqlreader",
                    "parameter": {
                        "connection": [
                            {
                                "jdbcUrl": [
                                    "jdbc:mysql://${biz_mysql_host}:${biz_mysql_port}/你的数据库A?useUnicode=true&zeroDateTimeBehavior=convertToNull&characterEncoding=UTF8&autoReconnect=true&useSSL=false&&allowLoadLocalInfile=false&autoDeserialize=false&allowLocalInfile=false&allowUrlInLocalInfile=false"
                                ],
                                "querySql": [
                                    "select a.id,a.title,a.content,a.is_delete,a.delete_date,a.create_date,a.update_date from t_article a.update_date >= '${biz_update_dt}';"
                                ]
                            }
                        ],
                        "password": "${biz_mysql_password}",
                        "username": "${biz_mysql_username}"
                    }
                },
                "writer": {
                    "name": "mysqlwriter",
                    "parameter": {
                        "column": [
                            "`id`",
                            "`title`",
                            "`content`",
                            "`is_delete`",
                            "`delete_date`",
                            "`create_date`",
                            "`update_date`"
                        ],
                        "connection": [
                            {
                                "jdbcUrl": "jdbc:mysql://${biz_mysql_host}:${biz_mysql_port}/你的数据库B?useUnicode=true&zeroDateTimeBehavior=convertToNull&characterEncoding=UTF8&autoReconnect=true&useSSL=false&&allowLoadLocalInfile=false&autoDeserialize=false&allowLocalInfile=false&allowUrlInLocalInfile=false",
                                "table": [
                                    "t_article"
                                ]
                            }
                        ],
                        "writeMode": "replace",
                        "password": "${biz_mysql_password}",
                        "username": "${biz_mysql_username}"
                    }
                }
            }
        ],
        "setting": {
            "errorLimit": {
                "percentage": 0,
                "record": 0
            },
            "speed": {
                "channel": 1,
                "record": 1000
            }
        }
    }
}

reader和writer的字段配置需保持一致

自定义参数:

biz_update_dt: ${global_bizdate}
biz_mysql_host: 你的mysql ip
biz_mysql_port: 3306
biz_mysql_username: 你的mysql账号
biz_mysql_password: 你的mysql密码

# 本文实验环境A库和B库用的同一个实例,如果MySQL是多个实例,可以再新增加参数定义例如 biz_mysql_host_b,在模板中对应引用即可

配置的自定义参数将会自动替换json模板中的同名变量

reader mysqlreader插件中关键配置: a.update_date >= '${biz_update_dt}' 就是实现增量同步的关键配置
writer mysqlwriter插件中关键配置: “

"parameter": {
    "writeMode": "replace",
    ......
}

writeMode为replace,相同主键id重复写入数据,就会更新数据。sql本质上执行的是 replace into

保存工作流

全局变量设置
global_bizdate: $[yyyy-MM-dd 00:00:00-1]

global_bizdate 引用的变量为 DolphinScheduler 内置变量,具体参考官网文档^[3]
结合调度时间设计好时间滚动的窗口时长,比如按1天增量,那么这里时间就是减1天

最终的工作流DAG图为:

爬坑记录

  • 官网下载的DataX不包含ElasticSearchWriter写插件
    默认不带该插件,需要自己编译ElasticSearchWriter插件。
git clone https://github.com/alibaba/DataX.git

为了加快编译速度,可以只编译<module>elasticsearchwriter</module>
项目根目录的pom.xml
<!-- reader --> 全注释掉,<!-- writer -->下只保留<module>elasticsearchwriter</module>其他注释掉,另外<!-- common support module -->也需要保留

如果自己不想编译或者编译失败请搜索🔍 “流水理鱼”微信公众号,或者加我私人微信我给你已经编译好的插件包

by 流水理鱼|wwek

参考

1. DataX MysqlReader 插件文档 https://github.com/alibaba/DataX/blob/master/mysqlreader/doc/mysqlreader.md
2. DataX MysqlWriter 插件文档 https://github.com/alibaba/DataX/blob/master/mysqlwriter/doc/mysqlwriter.md
3. Apache DolphinScheduler 内置参数 https://dolphinscheduler.apache.org/zh-cn/docs/latest/user_doc/guide/parameter/built-in.html

背景

MySQL库A 到 MySQL库B的增量数据同步需求

DolphinScheduler中配置DataX MySQL To MySQL工作流

工作流定义

工作流定义 > 创建工作流 > 拖入1个SHELL组件 > 拖入1个DATAX组件
SHELL组件(文章)
脚本

echo '文章同步 MySQL To MySQL'

DATAX组件(t_article)
用到2个插件mysqlreader^[1]、mysqlwriter^[2]
选 自定义模板:

{
    "job": {
        "content": [
            {
                "reader": {
                    "name": "mysqlreader",
                    "parameter": {
                        "connection": [
                            {
                                "jdbcUrl": [
                                    "jdbc:mysql://${biz_mysql_host}:${biz_mysql_port}/你的数据库A?useUnicode=true&zeroDateTimeBehavior=convertToNull&characterEncoding=UTF8&autoReconnect=true&useSSL=false&&allowLoadLocalInfile=false&autoDeserialize=false&allowLocalInfile=false&allowUrlInLocalInfile=false"
                                ],
                                "querySql": [
                                    "select a.id,a.title,a.content,a.is_delete,a.delete_date,a.create_date,a.update_date from t_article a.update_date >= '${biz_update_dt}';"
                                ]
                            }
                        ],
                        "password": "${biz_mysql_password}",
                        "username": "${biz_mysql_username}"
                    }
                },
                "writer": {
                    "name": "mysqlwriter",
                    "parameter": {
                        "column": [
                            "`id`",
                            "`title`",
                            "`content`",
                            "`is_delete`",
                            "`delete_date`",
                            "`create_date`",
                            "`update_date`"
                        ],
                        "connection": [
                            {
                                "jdbcUrl": "jdbc:mysql://${biz_mysql_host}:${biz_mysql_port}/你的数据库B?useUnicode=true&zeroDateTimeBehavior=convertToNull&characterEncoding=UTF8&autoReconnect=true&useSSL=false&&allowLoadLocalInfile=false&autoDeserialize=false&allowLocalInfile=false&allowUrlInLocalInfile=false",
                                "table": [
                                    "t_article"
                                ]
                            }
                        ],
                        "writeMode": "replace",
                        "password": "${biz_mysql_password}",
                        "username": "${biz_mysql_username}"
                    }
                }
            }
        ],
        "setting": {
            "errorLimit": {
                "percentage": 0,
                "record": 0
            },
            "speed": {
                "channel": 1,
                "record": 1000
            }
        }
    }
}

reader和writer的字段配置需保持一致

自定义参数:

biz_update_dt: ${global_bizdate}
biz_mysql_host: 你的mysql ip
biz_mysql_port: 3306
biz_mysql_username: 你的mysql账号
biz_mysql_password: 你的mysql密码

# 本文实验环境A库和B库用的同一个实例,如果MySQL是多个实例,可以再新增加参数定义例如 biz_mysql_host_b,在模板中对应引用即可

配置的自定义参数将会自动替换json模板中的同名变量

reader mysqlreader插件中关键配置: a.update_date >= '${biz_update_dt}' 就是实现增量同步的关键配置
writer mysqlwriter插件中关键配置: “

"parameter": {
    "writeMode": "replace",
    ......
}

writeMode为replace,相同主键id重复写入数据,就会更新数据。sql本质上执行的是 replace into

保存工作流

全局变量设置
global_bizdate: $[yyyy-MM-dd 00:00:00-1]

global_bizdate 引用的变量为 DolphinScheduler 内置变量,具体参考官网文档^[3]
结合调度时间设计好时间滚动的窗口时长,比如按1天增量,那么这里时间就是减1天

最终的工作流DAG图为:

爬坑记录

  • 官网下载的DataX不包含ElasticSearchWriter写插件
    默认不带该插件,需要自己编译ElasticSearchWriter插件。
git clone https://github.com/alibaba/DataX.git

为了加快编译速度,可以只编译<module>elasticsearchwriter</module>
项目根目录的pom.xml
<!-- reader --> 全注释掉,<!-- writer -->下只保留<module>elasticsearchwriter</module>其他注释掉,另外<!-- common support module -->也需要保留

如果自己不想编译或者编译失败请搜索🔍 “流水理鱼”微信公众号,或者加我私人微信我给你已经编译好的插件包

by 流水理鱼|wwek

参考

1. DataX MysqlReader 插件文档
2. DataX MysqlWriter 插件文档
3. Apache DolphinScheduler 内置参数

数据同步的方式

数据同步的2大方式

  • 基于SQL查询的 CDC(Change Data Capture):
    • 离线调度查询作业,批处理。把一张表同步到其他系统,每次通过查询去获取表中最新的数据。也就是我们说的基于SQL查询抽取;
    • 无法保障数据一致性,查的过程中有可能数据已经发生了多次变更;
    • 不保障实时性,基于离线调度存在天然的延迟;
    • 工具软件以Kettle(Apache Hop最新版)、DataX为代表,需要结合任务调度系统使用。
  • 基于日志的 CDC:
    • 实时消费日志,流处理,例如 MySQL 的 binlog 日志完整记录了数据库中的变更,可以把 binlog 文件当作流的数据源;
    • 保障数据一致性,因为 binlog 文件包含了所有历史变更明细;
    • 保障实时性,因为类似 binlog 的日志文件是可以流式消费的,提供的是实时数据;
    • 工具软件以Flink CDC、阿里巴巴Canal、Debezium为代表。

基于SQL查询增量数据同步原理

我们考虑用SQL如何查询增量数据? 数据有增加、需改、删除
删除数据采用逻辑删除的方式,比如定义一个is_deleted字段标识逻辑删除
如果数据是 UPDATE的,也就是会被修改的,那么 where update_datetime >= last_datetime(调度滚动时间)就是增量数据
如果数据是 APPEND ONLY 的除了用更新时间还可以用where id >= 调度上次last_id

结合任务调度系统
调度时间是每日调度执行一次,那么 last_datetime = 当前调度开始执行时间 – 24小时,延迟就是1天
调度时间是15分钟一次,那么 last_datetime = 当前调度开始执行时间 – 15分钟,延迟就是15分钟

这样就实现了捕获增量数据,从而实现增量同步

DolphinScheduler + Datax 构建离线增量数据同步平台

本实践使用
单机8c16g
DataX 2022-03-01 官网下载
DolphinScheduler 2.0.3(DolphinScheduler的安装过程略,请参考官网)

DolphinScheduler 中设置好DataX环境变量
DolphinScheduler 提供了可视化的作业流程定义,用来离线定时调度DataX Job作业,使用起来很是顺滑

基于SQL查询离线数据同步的用武之地
为什么不用基于日志实时的方式?不是不用,而是根据场合用。考虑到业务实际需求情况,基于SQL查询这种离线的方式也并非完全淘汰了
特别是业务上实时性要求不高,每次调度增量数据没那么大的情况下,不需要分布式架构来负载,这种情况下是比较合适的选择
场景举例:
网站、APP的百万级、千万级的内容搜索,每天几百篇内容新增+修改,搜索上会用到ES(ElasticSearch),那么就需要把 MySQL内容数据增量同步到ES
DataX就能满足需求!

DolphinScheduler中配置DataX MySQL To ElasticSearch工作流

工作流定义

工作流定义 > 创建工作流 > 拖入1个SHELL组件 > 拖入1个DATAX组件
SHELL组件(文章)
脚本

echo '文章同步 MySQL To ElasticSearch'

DATAX组件(t_article)
用到2个插件mysqlreader、elasticsearchwriter^[1]
选 自定义模板:

{
    "job": {
        "content": [
            {
                "reader": {
                    "name": "mysqlreader",
                    "parameter": {
                        "connection": [
                            {
                                "jdbcUrl": [
                                    "jdbc:mysql://${biz_mysql_host}:${biz_mysql_port}/你的数据库?useUnicode=true&zeroDateTimeBehavior=convertToNull&characterEncoding=UTF8&autoReconnect=true&useSSL=false&&allowLoadLocalInfile=false&autoDeserialize=false&allowLocalInfile=false&allowUrlInLocalInfile=false"
                                ],
                                "querySql": [
                                    "select a.id as pk,a.id,a.title,a.content,a.is_delete,a.delete_date,a.create_date,a.update_date from t_article a.update_date >= '${biz_update_dt}';"
                                ]
                            }
                        ],
                        "password": "${biz_mysql_password}",
                        "username": "${biz_mysql_username}"
                    }
                },
                "writer": {
                    "name": "elasticsearchwriter",
                    "parameter": {
                        "endpoint": "${biz_es_host}",
                        "accessId": "${biz_es_username}",
                        "accessKey": "${biz_es_password}",
                        "index": "t_article",
                        "type": "_doc",
                        "batchSize": 1000,
                        "cleanup": false,
                        "discovery": false,
                        "dynamic": true,
                        "settings": {
                            "index": {
                                "number_of_replicas": 0,
                                "number_of_shards": 1
                            }
                        },
                        "splitter": ",",
                        "column": [
                            {
                                "name": "pk",
                                "type": "id"
                            },
                            {
                                "name": "id",
                                "type": "long"
                            },
                            {
                                "name": "title",
                                "type": "text"
                            },
                            {
                                "name": "content",
                                "type": "text"
                            }
                            {
                                "name": "is_delete",
                                "type": "text"
                            },
                            {
                                "name": "delete_date",
                                "type": "date"
                            },
                            {
                                "name": "create_date",
                                "type": "date"
                            },
                            {
                                "name": "update_date",
                                "type": "date"
                            }
                        ]
                    }
                }
            }
        ],
        "setting": {
            "errorLimit": {
                "percentage": 0,
                "record": 0
            },
            "speed": {
                "channel": 1,
                "record": 1000
            }
        }
    }
}

reader和writer的字段配置需保持一致

自定义参数:

biz_update_dt: ${global_bizdate} 
biz_mysql_host: 你的mysql ip
biz_mysql_port: 3306
biz_mysql_username: 你的mysql账号
biz_mysql_password: 你的mysql密码
biz_es_host: 你的es地址带协议和端口 http://127.0.0.1:9200
biz_es_username: 你的es账号
biz_es_password: 你的es密码

配置的自定义参数将会自动替换json模板中的同名变量

reader mysqlreader插件中关键配置: a.update_date >= '${biz_update_dt}' 就是实现增量同步的关键配置
writer elasticsearchwriter插件中关键配置: “

"column": [
    {
        "name": "pk",
        "type": "id"
    },
    ......
]

type = id 这样配置,就把文章主键映射到es主键 _id 从而实现相同主键id重复写入数据,就会更新数据。如果不这样配置数据将会重复导入es中

保存工作流

全局变量设置
global_bizdate: $[yyyy-MM-dd 00:00:00-1]

global_bizdate 引用的变量为 DolphinScheduler 内置变量,具体参考官网文档^[2]
结合调度时间设计好时间滚动的窗口时长,比如按1天增量,那么这里时间就是减1天

最终的工作流DAG图为:

by 流水理鱼|wwek

参考

1. DataX ElasticSearchWriter 插件文档
2. Apache DolphinScheduler 内置参数

[TOC]

0、前言

image-20210606160820147

为什么使用Elasticsearch (以下简称 ES ) ?

全文搜索能力

ES本身就是一个搜索引擎,技术上基于倒排索引实现的搜索系统。我们做业务不必自己去开发一个搜索引擎,

ES已经满足绝大多数企业的搜索场景的需求。拼多多电商在发展前期,搜索业务使用ES支撑。

复杂查询(多维度组合筛选)

假如某个实体表,例如订单日订单量几十万,运营管理后台通常有十多个维度的组合筛选搜索。你可能会通过缩小查询时间范围来把数据量级降下来,MySQL也许也能一战,但是实际业务场景业务人员不太能接受这样一个小时间段筛选。如果稍微扩大时间段,MySQL这时候就无能为力了。那么把订单表做成“宽表”存入ES,十多个维度的搜索对于ES俩说是毫无压力的。ES群集能轻松支持亿级的宽表多维度组合筛选。这种需求在CRM、BOSS等场景是刚需。

滴滴司机端早期日订单量几十万,运营管理后台大时间跨度且多维度组合筛选就是用ES来实现的。

一个产品是否成熟,公有云是否提供基于该产品的服务是一个风向标。那么ES毫无疑问是成熟的产品。

虽然ES这么好,但是我的数据都在MySQL中那么怎么让数据实时同步到ES中呢?

1、基于应用程序多写

直接通过应用程序数据双写到MySQL和ES

image-20210606174354578

记录删除机制:直接删除

一致性: 需要自行处理,需要对失败错误做好日志记录,做好异常告警并人工补偿

优点: 直接明了,能够灵活控制数据写入,延迟最低

缺点: 与业务耦合严重,逻辑要写在业务系统中

应用双写(同步)

直接通过ES API将数据写入到ES集群中,也就是写入数据库的同时调用ES API写入到ES中

这个过程是同步的

应用双写(MQ异步解耦)

对 应用双写(同步)的改进,引入MQ中间件。

把同步变为异步,做了解耦。

同时引入MQ后双写性能提高,解决数据一致性问题。

缺点是会增加延迟性,业务系统增加mq代码,而且多一个MQ中间件要维护

2、基于binlog订阅

binlog订阅的原理很简单,模拟一个MySQL slave 订阅binlog日志,从而实现CDC(change data capture)

CDC,变更数据获取的简称,使用CDC我们可以从数据库中获取已提交的更改并将这些更改发送到下游,供下游使用。这些变更可以包括INSERT,DELETE,UPDATE等。

记录删除机制:直接删除

一致性: 最终一致性

优点: 对业务系统无任何侵入

缺点: 需要维护额外增加的一套数据同步平台;有分钟级的延迟

Canal

img

https://github.com/alibaba/canal/

阿里巴巴 MySQL binlog 增量订阅&消费组件

Databus

https://github.com/linkedin/databus

Linkedin Databus 分布式数据库同步系统

Maxwell

官网:http://maxwells-daemon.io/

https://github.com/zendesk/maxwell

Flink CDC

https://github.com/ververica/flink-cdc-connectors

flink-cdc-connectors 中文教程

基于flink数据计算平台实现 MySQL binlog订阅直接写入es

Flink CDC抛弃掉其他中间件,实现 MySQL 》Flink CDC》ES 非常简洁的数据同步架构

该方式比较新2020年开始的项目,目前在一些实时数仓上有应用

DTS(阿里云)

阿里云的商业产品,具备好的易用性,省运维成本。

CloudCanal

CloudCanal官网

CloudCannal数据同步迁移系统,商业产品

3、基于SQL抽取

基于SQL查询的数据抽取同步

这种方式需要满足2个基本条件

1、MySQL的表必须有唯一键字段(和ES中_id对应)

2、MySQL的表必须有一个“修改时间”字段,该记录任何一个字段修改都需要更新“修改时间”

有了唯一键字段就可以知道修改某条记录后同步哪条ES记录,有了修改时间字段就可以知道同步到哪儿了。

满足了这2个基本条件这样就可实现增量实时同步。

记录删除机制:逻辑删除,在MySQL中增加逻辑删除字段,ES搜索时过滤状态

一致性: 依赖修改时间字段;延迟时间等于计划任务多久执行一次

优点: 对业务系统无任何侵入,简单方便;课用JOIN打宽表

缺点: MySQL承受查询压力;需要业务中满足2个基本条件

logstash

我们使用 Logstash 和 JDBC 输入插件来让 Elasticsearch 与 MySQL 保持同步。从概念上讲,Logstash 的 JDBC 输入插件会运行一个循环来定期对 MySQL 进行轮询,从而找出在此次循环的上次迭代后插入或更改的记录。如要让其正确运行,必须满足下列条件:

  1. 在将 MySQL 中的文档写入 Elasticsearch 时,Elasticsearch 中的 “_id” 字段必须设置为 MySQL 中的 “id” 字段。这可在 MySQL 记录与 Elasticsearch 文档之间建立一个直接映射关系。如果在 MySQL 中更新了某条记录,那么将会在 Elasticsearch 中覆盖整条相关记录。请注意,在 Elasticsearch 中覆盖文档的效率与更新操作的效率一样高,因为从内部原理上来讲,更新便包括删除旧文档以及随后对全新文档进行索引。
  2. 当在 MySQL 中插入或更新数据时,该条记录必须有一个包含更新或插入时间的字段。通过此字段,便可允许 Logstash 仅请求获得在轮询循环的上次迭代后编辑或插入的文档。Logstash 每次对 MySQL 进行轮询时,都会保存其从 MySQL 所读取最后一条记录的更新或插入时间。在下一次迭代时,Logstash 便知道其仅需请求获得符合下列条件的记录:更新或插入时间晚于在轮询循环中的上一次迭代中所收到的最后一条记录。
input {
  jdbc {
    jdbc_driver_library => "<path>/mysql-connector-java-8.0.16.jar"
    jdbc_driver_class => "com.mysql.jdbc.Driver"
    jdbc_connection_string => "jdbc:mysql://<MySQL host>:3306/es_db"
    jdbc_user => <my username>
    jdbc_password => <my password>
    jdbc_paging_enabled => true
    tracking_column => "unix_ts_in_secs"
    use_column_value => true
    tracking_column_type => "numeric"
    schedule => "*/5 * * * * *"
    statement => "SELECT *, UNIX_TIMESTAMP(modification_time) AS unix_ts_in_secs FROM es_table WHERE (UNIX_TIMESTAMP(modification_time) > :sql_last_value AND modification_time < NOW()) ORDER BY modification_time ASC"
  }
}
filter {
  mutate {
    copy => { "id" => "[@metadata][_id]"}
    remove_field => ["id", "@version", "unix_ts_in_secs"]
  }
}
output {
  # stdout { codec =>  "rubydebug"}
  elasticsearch {
      index => "rdbms_sync_idx"
      document_id => "%{[@metadata][_id]}"
  }
}

配置Logstash的计划任务,定时执行

4、总结

前期建议采用 基于SQL抽取的方式做同步,后期数据量大了建议采用基于binlog订阅的方式同步。

如果本身有现成的Flink平台可用,推荐使用Flink CDC。

什么是最佳的 MySQL 同步 ElasticSearch 方案?

答案是选择缺点可以接受,又满足需求,拥有成本最低的方案。

“完美”的方案往往拥有成本会比较高,所以需要结合业务环境的上下文去选择。

流水理鱼觉得没有一招鲜的方案,因为每种方案都有利弊,所以选取适合你当下业务环境的方案。那么这样的方案就是最佳方案。

5、参考

MySQL 数据实时同步到 Elasticsearch 的技术方案选型和思考 by 万凯明

如何使用 Logstash 和 JDBC 确保 Elasticsearch 与关系型数据库保持同步

监听mysql的binlog日志工具分析:canal、Maxwell、Databus、DTS

1.简介

使用微创联合M5S空气检测仪、树莓派3b+、prometheus、grafana实现空气质量持续监控告警WEB可视化

grafana dashboard效果:

image-20201031171328947

2.背景

2.1 需求:

1.新办公地址的甲醛(HCHO)、异味(TVOC)做个监测

2.能够把这些空气指标进行WEB展示

3.监控告警关心的空气指标,告警发送到钉钉上

2.2 已有硬件:

树莓派3b+ (长期吃灰中)以下简称树莓派

微创联合M5S空气检测仪(版本:M5S温湿+锂电+TVOC+数据导出 17年485元价格购买 )以下简称空气检测仪

M5S 家用 激光PM2.5检测仪 甲醛 CO2 空气质量 雾霾甲醛 检测仪

【在售价】380.00 元(基础版)

【立即下单】点击链接立即下单:https://s.click.taobao.com/zREU4vu

img

3.设计

把空气检测仪的usb插到树莓派上(树莓派上通过串口读取数据),供电也是通过树莓派供电

相关软件运行在树莓派上

3.1 硬件:

空气检测仪如何导出数据?

空气检测仪是有数据导出版本,自带串口转USB(ch340芯片)

打开空气检测仪并通过检测仪左侧 FUN 按钮,把屏幕切换到第 3 屏,这个时候串口中就会持续输出监控数据

在linux上设备文件符为“/dev/ttyUSB0”

cat /dev/ttyUSB0
#可以看到
24.9 45.2 23 32 35 26 33 35 4419 1301 159 8 3 0 0.006 0.21

读取过程中,按一下检测仪上的 RST 键,可以显示每列数据对应的字段定义,(按完后需要再按 FUN 键切换到第 3 屏

*--------------------------------------- Data Output Format Definition ----------------------------------------*
TEMP HUMI CH_PM1.0 CH_PM2.5 CH_PM10 US_PM1.0 US_PM2.5 US_PM10 >0.3um >0.5um >1.0um >2.5um >5.0um >10um HCHO TVOC
TEMP HUMI CH_PM1.0 CH_PM2.5 CH_PM10 US_PM1.0 US_PM2.5 US_PM10 >0.3um >0.5um >1.0um >2.5um >5.0um >10um HCHO TVOC
25.1 43.3 21 29 31 22 29 31 3843 1136 170 6 2 0 0.003 0.2
25.1 43.2 22 30 31 23 30 31 3876 1156 170 5 2 0 0.005 0.16
25.1 43.3 22 30 31 23 30 31 3963 1174 164 6 2 0 0.003 0.21
25.2 43.3 22 30 31 23 30 31 3942 1163 167 6 2 0 0.007 0.21

带二氧化碳检测的版本在HCHO字段前多一个CO2字段

更多资料看空气检测仪配套的资料

3.2 软件:

软件监控采用prometheus + grafana的方案

本文为流水理鱼wwek原创 www.iamle.com

现在只需要实现一个串口(/dev/ttyUSB0) exporter即可把空气监测仪的数据打通给prometheus使用

最后配置prometheus取空气检测仪的exporter数据,并配置grafana面板

监控告警直接使用grafana带的监控告警

4.实现

*安装配置wclh_air_detector_exporter 获得空气检测仪数据

wclh_air_detector_exporter读取串口数据并把数据进行结构化,然后输出metrics

M5S Temperature and Humidity+lithium battery+CO2+TVOC PM2.5 CO2(S8)TEMP&HUMI Detector Haze PM2.5 sensors Laser PM2.5 detector

M5S 家用 激光PM2.5检测仪 甲醛 CO2 空气质量 雾霾甲醛 检测仪

WCLH_AIR_DETECTOR_EXPORTER_VERSION=0.1.3
wget https://github.com/wwek/wclh_air_detector_exporter/releases/download/v${WCLH_AIR_DETECTOR_EXPORTER_VERSION}/wclh_air_detector_exporter_${WCLH_AIR_DETECTOR_EXPORTER_VERSION}_linux_armv7.tar.gz
tar zxvf wclh_air_detector_exporter_${WCLH_AIR_DETECTOR_EXPORTER_VERSION}_linux_armv7.tar.gz
mkdir -p /data/soft/wclh_air_detector_exporter
mv wclh_air_detector_exporter /data/soft/wclh_air_detector_exporter
cd /data/soft/wclh_air_detector_exporter

#./wclh_air_detector_exporter -serial_port /dev/ttyUSB0

#自动启动&进程守护
sudo bash -c 'cat > /etc/systemd/system/wclh_air_detector_exporter.service << EOF [Unit] Description=https://github.com/wwek/wclh_air_detector_exporter Wants=network-online.target After=network-online.target [Service] Restart=on-failure #User=root ExecStart=/data/soft/wclh_air_detector_exporter/wclh_air_detector_exporter [Install] WantedBy=default.target EOF' sudo systemctl daemon-reload sudo systemctl status wclh_air_detector_exporter sudo systemctl start wclh_air_detector_exporter sudo systemctl enable wclh_air_detector_exporter sudo systemctl status wclh_air_detector_exporter curl http://localhost:9166/metrics ``` ## 安装配置prometheus ``` PROMETHEUS_VERSION=2.22.0 wget https://github.com/prometheus/prometheus/releases/download/v${PROMETHEUS_VERSION}/prometheus-${PROMETHEUS_VERSION}.linux-armv7.tar.gz tar zxvf prometheus-${PROMETHEUS_VERSION}.linux-armv7.tar.gz mkdir -p /data/soft/ mv prometheus-${PROMETHEUS_VERSION}.linux-armv7 prometheus &amp;&amp; mv prometheus /data/soft/ #自动启动&amp;进程守护 sudo bash -c 'cat &gt; /etc/systemd/system/prometheus.service &lt;&lt; EOF
[Unit]
Description=https://prometheus.io
Wants=network-online.target
After=network-online.target

[Service]
Restart=on-failure
#User=root
ExecStart=/data/soft/prometheus/prometheus --config.file="/data/soft/prometheus/prometheus.yml"

[Install]
WantedBy=default.target
EOF'

sudo systemctl daemon-reload
sudo systemctl status prometheus
sudo systemctl start prometheus
sudo systemctl enable prometheus
sudo systemctl status prometheus

curl http://localhost:9090
#<a href="/graph">Found</a>.

安装配置grafana

sudo apt-get install -y apt-transport-https
sudo apt-get install -y software-properties-common wget
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list
sudo apt-get update
sudo apt-get install grafana
sudo systemctl daemon-reload
sudo systemctl start grafana-server
sudo systemctl enable grafana-server
sudo systemctl status grafana-server

curl http://localhost:3000
#<a href="/login">Found</a>.

grafana 中先配置 prometheus(http://localhost:9090)数据源,然后导入 “grafana-dashboard.json”空气检测仪的dashboard

监控告警

直接使用grafana自带的告警功能,将关心的指标进行监控并告警

转载,原文 敖小剑  https://skyao.io/talk/202004-mecha-mesh-through-to-the-end/

摘要

Servicemesh落地实践三年,效果一直并不理想,到了该反思的时候了。Mecha作为面向服务的分布式能力抽象层,是Servicemesh模式的自然进化版本,预计也将是云原生化和Mesh化的必然趋势,让我们将Mesh进行到底。

Mecha介绍

什么是Macha?

Mecha一词,相信爱好动漫的同学应该都不陌生。是的,就是大家熟悉的那个Mecha(机甲):

Mecha这个词之所以出现在这里,主要是因为 Bilgin Ibryam 的这个博客文章 “Multi-Runtime Microservices Architecture”,提出了微服务架构的一个新的设想:Multiple Runtime。

备注:这篇博客文章强烈推荐阅读,我甚至建议在阅读本文之前先阅读这篇文章,因为我今天的内容,可以视为对这个文章的深度解读和思考。为了方便,这里提供一份中文翻译版本 多运行时微服务架构

在这篇博客中,Bilgin Ibryam 首先分析并总结了分布式应用的四大需求:

  • 生命周期(Lifecycle)
  • 网络(Networking)
  • 状态(State)
  • 捆绑(Binding)

由于每种需求存在的问题和局限性,导致传统解决方案如企业服务总线(ESB)及其变体(例如面向消息的中间件,更轻量级的集成框架等)不再适用。随着微服务架构的发展,以及容器和Kubernetes的普及和广泛使用,云原生思想开始影响这些需求的实现方式。未来的架构趋势是通过将所有传统的中间件功能移至其他运行时来全面发展,最后的目标是在服务中只需编写业务逻辑。

备注:详情请见原文,为了节约篇幅,这里只做简单概述,不完全引用原文内容。

下图是传统中间件平台和云原生平台的对比,传统中间件以各种SDK的方式提供能力,而云原生平台则通过各种外围Runtime(典型如大家熟悉的Servicemesh/Istio):

因此作者引入了Multiple Runtime的概念:

作者提出:很可能在将来,我们最终将使用多个运行时来实现分布式系统。多个运行时,不是因为有多个微服务,而是因为每个微服务都将由多个运行时组成,最有可能是两个运行时-自定义业务逻辑运行时和分布式原语运行时。

对多运行时微服务架构和Mecha的说明:

您还记得电影《阿凡达》和科学家们制作的用于去野外探索潘多拉的 Amplified Mobility Platform (AMP)“机车服”吗?这个多运行时架构类似于这些 Mecha-套装,为类人驾驶员赋予超能力。在电影中,您要穿上套装才能获得力量并获得破坏性武器。在这个软件架构中,您将拥有构成应用核心的业务逻辑(称为微逻辑/micrologic)和提供强大的开箱即用的分布式原语的sidecar mecha组件。Micrologic与mecha功能相结合,形成多运行时微服务,该服务将进程外功能用于其分布式系统需求。最棒的是,Avatar 2即将面世,以帮助推广这种架构。我们最终可以在所有软件会议上用令人赞叹的机甲图片代替老式的边车摩托车;-)。接下来,让我们看看该软件架构的详细信息。

这是一个类似于客户端-服务器体系结构的双组件模型,其中每个组件都是独立的运行时。它与纯客户端-服务器架构的不同之处在于,这两个组件都位于同一主机上,彼此之间有可靠的网络连接。这两个组件的重要性相当,它们可以在任一方向上发起操作并充当客户端或服务器。其中的一个组件称为Micrologic,拥有非常少的业务逻辑,把几乎所有分布式系统问题都剥离出去了。另一个伴随的组件是Mecha,提供了我们在本文中一直讨论的所有分布式系统功能(生命周期除外,它是平台功能)。

作者在这里正式提出了Mecha的理念:

思路大体是:Smart Runtime, Dumb Pipes

我对Mecha的理解是:业务逻辑在编码开始阶段应该是“裸奔”的,专注于业务逻辑的实现,而尽量不涉及到底层实现逻辑;而在运行时,则应该装备“机甲”,全副武装,大杀四方。熟悉的味道是吧?标准而地道的云原生思想。

Mecha的本质

作者在原文中探讨了Mecha运行时的特性:

  1. Mecha是通用的,高度可配置的,可重用的组件,提供分布式原语作为现成的能力。
  2. Mecha 可以与单个Micrologic组件一起部署(Sidecar模式),也可以部署为多个共享(注:我称之为Node模式)。
  3. Mecha不对Micrologic运行时做任何假设。它与使用开放协议和格式(例如HTTP/gRPC,JSON,Protobuf,CloudEvents)的多语言微服务甚至单体一起使用。
  4. Mecha以简单的文本格式(例如YAML,JSON)声明式地配置,指示要启用的功能以及如何将其绑定到Micrologic端点。
  5. 与其依靠多个代理来实现不同的目的(例如网络代理,缓存代理,绑定代理),不如使用一个Mecha提供所有这些能力。

下面是我对上述特性的个人理解:

  1. Mecha提供的是能力,以分布式原语体现的各种能力,而不局限于单纯的网络代理。
  2. Mecha的部署模型,不局限于Sidecar模式,Node模式在某些场景下(如Edge/IoT,Serverless FaaS)可能会是更好的方式。至少,Mecha下有机会按需选择,而不是绑死在Sidecar模式上
  3. Mecha和Micrologic之间的交互是开放而有API标准的,Mecha和Micrologic之间的“协议”体现在API上,而不是TCP通讯协议。这提供了一个契机:一个统一Micrologic和Mecha之间通讯方式的契机。
  4. Mecha可以以声明式的方式进行配置和控制,这非常符合云原生的理念,同样也使得API更关注于能力本身,而不是能力如何配置。
  5. 应用需要的能力如此之多(参见上面的图:分布式应用的四大需求),如果每个能力都对应一个代理(不管是Node还是Sidecar),数量会非常夸张,带来的运维压力会很可怕。因此,如Mecha这个名字暗示的,运行时应该是整套的形式提供能力,而不是分散。

如果用一句话来总结,那么我认为Mecha的本质应该是:

“面向应用的分布式能力抽象层”

如Servicemesh的本质是服务间通讯的抽象层一样,Mecha的本质是应用需要的各种分布式能力和原语,包括但不限于服务间通讯。

从这个角度上说,Mecha覆盖的范围是Servicemesh的超集:毕竟Servicemesh只覆盖到应用的部分需求(服务间通讯,还只限于同步/一对一/request-response模式),还有更多的分布式能力和原语有待覆盖。

换一句话说,Mecha的目标应该是:“将Mesh进行到底!”

Mecha的优势和未来

作者指出:Mecha的好处是业务逻辑和越来越多的分布式系统问题之间的松耦合。

下图是业务逻辑和分布式系统问题在不同架构中的耦合:

其实思路和Servicemesh是一脉相承的,只是覆盖的分布式能力更广泛一些。

有一个问题:Mecha会不会成为微服务架构的演进的下一个形态?我个人的答案:是,随着云原生的推进,分布式能力(以传统中间件为典型代表)下沉是大势所趋,Mesh化的范围必然会继续扩大,也就离Mecha的形态越来越近了。这也就是本文标题的立意所在,Mecha会是微服务乃至云原生的下一站。

微软Dapr

在介绍完 Mecha/Multiple Runtime 的理念之后,我们来看看目前微软新推出来的Dapr项目 —— 这应该是业界第一个Multiple Runtime的开源实践项目。

项目地址:https://github.com/dapr/dapr。

Dapr介绍

Dapr 是 Distributed Application Runtime (分布式应用运行时)的缩写,官方介绍说Dapr是“一种可移植的,事件驱动的运行时,用于构建跨云和边缘的分布式应用”。

Dapr的详细介绍是:

Dapr是一种可移植的,serverless的,事件驱动的运行时,它使开发人员可以轻松构建弹性,无状态和有状态微服务,这些服务运行在云和边缘上,并包含多种语言和开发框架。

Dapr 整理了构建微服务应用为开放,独立的构建块的最佳实践,使您能够使用自己选择的语言和框架来构建可移植的应用程序。 每个构建块都是独立的,您可以在应用中使用其中的一个或多个。

Dapr的功能和定位,下面这一张图就可以概括了:

  • 最底下基础设施是各种云平台(主流公有云都支持)或者边缘环境
  • 其上是dapr提供的分布式能力,dapr称之为“building block”。
  • 这些building block的能力,以统一的API(支持HTTP和gRPC)对外提供服务
  • 应用可以用各种语言编写,然后通过dapr提供的API使用这些能力,dapr也提供客户端类库来简化对API的调用,实现了多语言的支持。

Dapr提供的具体分布式能力(building block)如下图所示:

每个building block提供的具体能力请参加 Dapr 的官方文档:https://github.com/dapr/docs/tree/master/concepts。

Dapr的API例子

我们来看一下应用调用Darp API的例子,体验一下使用Dapr的方式。

以 Service Invocation / 服务调用为例:

部署和调用方式与 Servicemesh/Istio 极为相似,但是,差别在于:Dapr是以提供API的方式提供API背后的能力,而不是提供提供协议代理的方式。

上图中1,是ServiceA发起请求来调用一个远程服务。其HTTP request 如下所示:

POST/GET/PUT/DELETE http://localhost:<daprPort>/v1.0/invoke/<appId>/method/<method-name>

其中:

  • 参数 daprPort 是Dapr Runtime启动的监听端口,用来接受应用的 outbound 请求
  • 参数 appId 是远程应用在darp中的关联id,每个注册到dapr的应用都有一个唯一的appId
  • 参数 method-name 是要调用的远程应用的方法名或者URL

负载可以存放在HTTP body中随请求发送,如 json。

注意,虽然都是提供相同的功能,这里体现了Dapr(或者说背后的Mecha)和Servicemesh在方式上的差异:暴露API还是代理通讯协议。

我们看一个更明显的例子,dapr提供的 “publish/subscriptions” 能力,让应用可以方便的发布消息,或者订阅主题并接收消息。下图是应用发布消息,请求直接发给dapr即可:

例子中,参数 topic 指定了消息要发往的主题(例子中是 deathStarStatus)。后续dapr会完成将消息入queue,然后推送到订阅了该topic的应用。接收消息的方式也类似,不过这次是darp主动发起:

  1. dapr首先会请求应用,咨询应用需要订阅那些主题(topic),如例子中应用返回的的TopicA / TopicB
  2. dapr实现主题订阅,在接收到消息之后,再把消息发送给应用,通过URL参数的不同来区分不同的主题

注意在这个调用期间,无论是收发消息,应用完全不用理会底层pub/sub的实现机制(比如是kafka,还是rocketmq,还是其他公有云提供的消息机制),也完全不用引入该实现机制的客户端SDK,只是简单的使用darp定义的API即可,从而实现了和底层的解耦,以及“厂商不绑定”。

为了进一步简化调用的过程(毕竟发一个最简单的HTTP GET请求也要应用实现HTTP协议的调用/连接池管理等),dapr提供了各个语言的SDK,如 java / go / python / dotnet / js / cpp / rust 。另外同时提供HTTP客户端和gRPC客户端。

我们以 Java 为例,java的 client API 接口定义如下:

public interface DaprClient {  
   Mono<Void> publishEvent(String topic, Object event);
   Mono<Void> invokeService(Verb verb, String appId, String method, Object request);
    ......
}

具体可见:

https://github.com/dapr/java-sdk/blob/master/sdk/src/main/java/io/dapr/client/DaprClient.java

分析和总结

前面介绍了Multiple Runtime / Mecha 的架构思想,以及参考实现之一的微软Dapr项目。

由于 Multiple Runtime / Mecha 这个思想非常的新,刚刚提出不久,而微软 Dapr 项目也是一个新出来的项目,不管是理论思想还是实践都处于非常早期的状态,也还没有形成完善的方法论。

特别申明:以下内容更多是我个人当下的理解和感悟,仅代表个人意见,肯定有很多不成熟甚至谬误的地方,欢迎指正和探讨。

Mecha和Dapr的启示

  1. Mesh 模式应该推向更大的领域

    随着云原生的深入,应用需要的分布式能力应该全面下沉,而不仅仅局限于Servicemesh提供的服务间通讯能力;应用形态会朝纯业务逻辑这个目标更进一步,应用更加的云原生化。

    这是大势所趋,也是Mecha架构出现和发展的原动力。

  2. Mecha强调是“提供能力”,而不是通讯代理

    Mecha的使用方式和Servicemesh有非常大的差异:Mecha强调的是提供分布式能力给应用使用,这些能力最终以封装完善的API的方式呈现。API体现的是应用对能力的“需求”和“意愿”,不涉及到如何实现,实现是Mecha的职责,采用什么样的实现也是由Mecha来控制。

    在Servicemesh下,不存在这个需求:Servicemesh提供的是服务间通讯能力,这个能力是由sidecar来提供,没有其他的更底层的实现,不存在隔离和替换的可能。受服务通讯协议和报文schema的限制,Servicemesh只能做请求的“转发”,能力聚焦在“如何转发”上,没有其他需要隔离和替代的能力。

    当Mecha把能力扩展到Servicemesh之外时,很多能力是由外部系统提供:比如 pub-sub 能力可以由不同的Message Queue实现;状态管理能力可以连接不同的Key-Value实现。此时能力的隔离性和可替代性就成为关键需求:解耦应用和能力实现,容许Mecha替换底层实现(进而实现供应商不锁定等)。

  3. 不强求“零侵入”

    在Servicemesh中,“零侵入”是一个非常强调的特性,为此不惜引入 iptables 等流量劫持方案。“零侵入”在某些特殊场景下会发挥巨大的优势,如旧有应用不做改造的前提下接入servicemesh。好处自然不言而喻,但零侵入也有自身的限制:客户端必须能发出符合服务器端要求的网络通讯请求,这个过程外部无法插手。

    对于服务间通讯,这个不是大问题。但是对于其他能力,由于有和实现解耦的需求,再通过客户端自行发起原生协议的请求就不合适了。因此,Mecha中更倾向于采用低侵入的轻量级SDK方案,同样也可以实现跨语言和跨平台,只是需要付出实现各种语言SDK的代价。由于这个SDK足够轻量,因此代价还不算很高。

    而这些少量的工作量,少量的侵入,可以换取轻量级SDK能提供的各种便利和配合(简单理解:开后门),可以实现能力的抽象和API的封装。权衡利弊,Mecha下更倾向于轻量级SDK方案。

  4. 不限定 Sidecar 部署

    Sidecar部署模式,存在资源占用、维护成本增加等缺点,在某些情况下可能并不合适:

    • 边缘网络,IoT场景:资源非常有限,不适合启动太多Sidecar
    • FaaS场景:应用自身足够轻量,甚至比Sidecar还要轻量
    • Serverless场景:Scale to Zero时,对冷启动速度有严格要求,Sidecar的启动和初始化可能拖累应用启动速度

    Mecha下,部署模式不限定于 Sidecar ,在合适时容许选择 Node 模式,甚至 Node 模式和 Sidecar 模式混合使用。

  5. API和配置是关键

    API是分布式能力的抽象,需要要对(开发上层业务应用的)客户友好,简单好用,稳定不变。这些API 也需要标准化,被社区广泛接受和采纳,才能实现厂商不锁定和自由迁移,提升客户价值。

    另外,API还需要配合配置使用,在把能力抽象为API时,是不提供能力的细节控制的。这些控制将在运行时由Mecha根据配置实现,可以理解为:“API + 配置 = 完整的能力”。

    API和配置的制订以及标准化,预计将会是Mecha成败的关键。

Mecha的精髓

Program to an interface, not an implementation.

Design Patterns: Elements of Reusable Object-Oriented Software (GOF, 1994)

Mecha的精髓,要从上面这句名言开始:

  1. 在Mecha下,为了实现解耦可替换, Runtime 隔离了底层实现,因此演变为:”Program to an Runtime, not an implementation.“”
  2. 考虑到 Runtime 不管是部署为Sidecar模式,还是部署为 Node 模式,都是Localhost,因此有: “Program to an Localhost, not an implementation.”
  3. 为了简化开发,Mecha还是会提供轻量级SDK,提供API作为能力的抽象:“Program to an API, not an implementation.”
  4. 考虑到 API 通常是以 interface 的形式提供,因此绕了一圈,Mecha最后还是回到原点:“Program to an interface, not an implementation.”

个人理解,Mecha的精髓就在于这几个关键点:隔离/抽象/解耦/可替换。如下图所示:

  • 在Mecha下,MicroLogic(也就是业务逻辑的代码实现)不容许直接使用底层实现提供的分布式能力
  • Mecha Runtime将为Micro Logic提供分布式能力,同时隔离应用和底层实现
  • 为了方便使用,提供轻量级SDK,其中的API层实现了分布式能力的抽象,应用只需面向API编程
  • 轻量级SDK和Mecah Runtime配合,完成对底层实现的解耦和可替换。

Mecha的实现原则

在Mecha的实现上,我理解的原则是这样:

  1. Runtime 是主力,要做厚
  2. 轻量级SDK 主要是给 Runtime 打配合,要做薄

具体的职责划分:

  1. 轻量级SDK:实现多语言接入,低侵入(但不追求零侵入)
  2. API 接口:由轻量级SDK中提供统一,目标社区化+标准化,给开发者提供一致的编程体验,同时提供可移植性
  3. 应用:轻量级SDK/Runtime配合,提供各种分布式能力,应用无感,只需简单使用API,不耦合底层实现

在Mecha架构中,Runtime 自然是整个架构的核心,扮演类似Servicemesh中数据平面的角色

  • 所有分布式能力使用的过程(包括访问内部生态体系和访问外部系统)都被 Runtime 接管和屏蔽实现
  • 通过CRD/控制平面实现声明式配置和管理(类似Servicemesh)
  • 部署方式上 Runtime 可以部署为Sidecar模式,或者Node模式,取决于具体需求,不强制

备注:Mecha有非常多的能力,实现上也有非常多的细节,这里先做一个High Level的概述。细节后面会有一系列文章一一覆盖,欢迎多交流讨论。

Mecha总结

大概是在3月初,当时我第一次阅读 “Multi-Runtime Microservices Architecture” 这篇文章,有一种豁然开朗的感觉,尤其是有很多之前在反复考虑和权衡但是下不了结论的问题,在这个文章中得到了清晰的解答。可谓受益匪浅。

在Servicemesh探索和实践的这三年中,遇到很多问题,有很多之前没有想到过的问题浮现。比如,以前一直觉得Servicemesh中引入Sidecar带来的最大麻烦会是性能,但实际上,从目前的实践看,Sidecar引入后带来的维护代价才是更令人头疼的事情,相比之下Sidecar引入带来的性能损失显得无伤大雅。

总结一下我个人对 Mecha 架构的核心理解,主要是两点:

  1. Mecha是云原生化和Mesh化的必然趋势:云原生在继续发展,应用需要的分布式能力需要继续下沉,越来越多的能力会以sidecar的形式出现,这是大势所趋。但不可能出现一个应用部署十几个sidecar的局面,这会是运维地狱。因此,必然需要出现新的形态来解决Sidecar过多的问题,合并为一个或者多个Sidecar就会成为必然。
  2. Mecha是Servicemesh模式的自然进化版本:Servicemesh落地实践三年了,效果一直并不理想,到了该反思反省的时候了;而且Mecha的范围也远不止服务间通讯,新的需求下应该有新的思考和突破。Servicemesh现有的固定模式,在Mecha下可以尝试打破以探索新的方式:不必拘泥于Sidecar,试试Node模式;不必拘泥于通讯协议转发,试试Runtime提供能力解耦底层实现;不必拘泥于零侵入,试试在应用中保留一个足够轻的轻量级SDK。

正如曾有说法,说“微服务是SOA实践中正确的部分(the Good Part)”,我希望在 Mecha 的探索和实践中,能够从Servicemesh的实践中吸取成功的经验和失败的教训,希望 Mecha 也能成为Servicemesh的Good Part。希望在云原生的演进路线中,Mecha 可以继微服务和Servicemesh之后,成为云原生落地实践的下一站。

回到现实,目前 Mecha 和 Multi-Runtime 还是一个非常新的想法,Dapr 项目也才刚刚起步,Mecha 要探索的道路还很漫长,一切都还需要摸索着前进。

附录:参考资料

在文章的最后,特别鸣谢 “Multi-Runtime Microservices Architecture”一文的作者 “Bilgin Ibryam”,我非常认可这篇文章中的思想和理念,分析归纳的非常到位,提炼和升华的能力令人佩服。

作者介绍:

Red Hat的首席架构师,Apache Software Foundation 的 committer 和成员。开源的布道师,博客作者,偶尔演讲,著有书籍 Kubernetes Patterns 和 Camel Design Patterns 。

本文参考了 Bilgin Ibryam 出品的如下内容: