1.EMQX-简介、渲染安装部署、模板码渲基础功能、渲染python代码测试
2.云原生DevOps落地方案
EMQX-简介、安装部署、渲染基础功能、模板码渲函证系统源码python代码测试
MQTT属于是渲染物联网的通信协议,在MQTT协议中有两大角色:客户端(发布者/订阅者),模板码渲服务端(Mqtt broker);针对客户端和服务端需要有遵循该协议的渲染的具体实现,EMQ/EMQX就是模板码渲MQTT Broker的一种实现。
EMQX是渲染基于 Erlang/OTP 平台开发的 MQTT 消息服务器,是模板码渲开源社区中最流行的 MQTT 消息服务器。EMQ X 是渲染开源百万级分布式 MQTT 消息服务器(MQTT Messaging Broker),用于支持各种接入标准 MQTT协议的模板码渲设备,实现从设备端到服务器端的渲染消息传递,以及从服务器端到设备端的设备控制消息转发。从而实现物联网设备的数据采集,和对设备的操作和控制。
到目前为止,比较流行的 MQTT Broker 有几个:使用 C 语言实现的 MQTT Broker,使用 Erlang 语言开发的 MQTT Broker,使用 Node.JS 开发的 MQTT Broker,同样使用 Erlang 开发的 MQTT Broker。从支持 MQTT5.0、稳定性、扩展性、集群能力等方面考虑,EMQX 的表现应该是最好的。
与别的MQTT服务器相比EMQ X 主要有以下的特点:经过+版本的迭代,EMQ X 目前为开源社区中最流行的 MQTT 消息中间件,在各种客户严格的生产环境上经受了严苛的考验;支持丰富的物联网协议,包括 MQTT、MQTT-SN、CoAP、 LwM2M、LoRaWAN 和 WebSocket等;优化的架构设计,支持超大规模的设备连接。企业版单机能支持百万的 MQTT 连接;集群能支持千万级别的 MQTT 连接;易于安装和使用;灵活的扩展性,支持企业的一些定制场景;中国本地的技术支持服务,通过微信、QQ等线上渠道快速响应客户需求;基于 Apache 2.0 协议许可,学校网站html源码完全开源。EMQ X 的代码都放在 Github 中,用户可以查看所有源代码;EMQ X 3.0 支持 MQTT 5.0 协议,是开源社区中第一个支持 5.0协议规范的消息服务器,并且完全兼容 MQTT V3.1 和 V3.1.1 协议。除了 MQTT 协议之外,EMQ X 还支持别的一些物联网协议;单机支持百万连接,集群支持千万级连接;毫秒级消息转发。EMQ X 中应用了多种技术以实现上述功能;利用 Erlang/OTP 平台的软实时、高并发和容错(电信领域久经考验的语言);全异步架构;连接、会话、路由、集群的分层设计;消息平面和控制平面的分离等;扩展模块和插件,EMQ X 提供了灵活的扩展机制,可以实现私有协议、认证鉴权、数据持久化、桥接发和管理控制台等的扩展;桥接:EMQ X 可以跟别的消息系统进行对接,比如 EMQ X Enterprise 版本中可以支持将消息转发到 Kafka、RabbitMQ 或者别的 EMQ 节点等;共享订阅:共享订阅支持通过负载均衡的方式在多个订阅者之间来分发 MQTT 消息。比如针对物联网等 数据采集场景,会有比较多的设备在发送数据,通过共享订阅的方式可以在订阅端设置多个订阅者来实现这几个订阅者之间的工作负载均衡。
典型的物联网平台包括设备硬件、数据采集、数据存储、分析、Web / 移动应用等。EMQX 位于数据采集这一层,分别与硬件和数据存储、分析进行交互,是物联网平台的核心:前端的硬件通过 MQTT 协议与位于数据采集层的 EMQX 交互,通过 EMQX 将数据采集后,通过 EMQX 提供的数据接口,将数据保存到后台的持久化平台中(各种关系型数据库和 NOSQL 数据库),或者流式数据处理框架等,上层应用通过这些数据分析后得到的结果呈现给最终用户。
EMQX 公司主要提供三个产品,可在官网首页产品导航查看每一种产品;主要体现在支持的连接数量、产品功能和商业服务等方面的spring 源码解读 书籍区别。
完整的 MQTT V3.1/V3.1.1 及 V5.0 协议规范支持;QoS0, QoS1, QoS2 消息支持;持久会话与离线消息支持;Retained 消息支持;Last Will 消息支持;TCP/SSL 连接支持;MQTT/WebSocket/SSL 支持;HTTP 消息发布接口支持;$SYS/# 系统主题支持;客户端在线状态查询与订阅支持;客户端 ID 或 IP 地址认证支持;用户名密码认证支持;LDAP 认证;Redis、MySQL、PostgreSQL、MongoDB、HTTP 认证集成;浏览器 Cookie 认证;基于客户端 ID、IP 地址、用户名的访问控制 (ACL);多服务器节点集群 (Cluster);支持 manual、mcast、dns、etcd、k8s 等多种集群发现方式;网络分区自动愈合;消息速率限制;连接速率限制;按分区配置节点;多服务器节点桥接 (Bridge);MQTT Broker 桥接支持;Stomp 协议支持;MQTT-SN 协议支持;CoAP 协议支持;Stomp/SockJS 支持;延时 Publish ($delay/topic);Flapping 检测;黑名单支持;共享订阅 ($share/:group/topic);TLS/PSK 支持;规则引擎;空动作 (调试);消息重新发布;桥接数据到 MQTT Broker;检查 (调试);发送数据到 Web 服务。
EMQ X 目前支持的操作系统:Centos6、Centos7、OpenSUSE tumbleweed、Debian 8、Debian 9、Debian 、Ubuntu .、Ubuntu .、Ubuntu .、macOS .、macOS .、macOS .、Windows Server 。产品部署建议 Linux 服务器,不推荐 Windows 服务器。安装的方式有很多种,可供自由选择:Shell脚本安装、包管理器安装、二进制包安装、ZIP压缩包安装、Homebrew安装、Docker运行安装、Helm安装、源码编译安装。
Dashboard界面查看基本信息。
身份认证是大多数应用的重要组成部分,MQTT 协议支持用户名密码认证,启用身份认证能有效阻止非法客户端的连接。EMQ X 中的linux 源码安装vim认证指的是当一个客户端连接到 EMQ X 的时候,通过服务器端的配置来控制客户端连接服务器的权限。EMQ X 的认证支持包括两个层面:MQTT 协议本身在 CONNECT 报文中指定用户名和密码,EMQ X 以插件形式支持基于 Username、ClientID、HTTP、JWT、LDAP 及各类数据库如 MongoDB、MySQL、PostgreSQL、Redis 等多种形式的认证;在传输层上,TLS 可以保证使用客户端证书的客户端到服务器的身份验证,并确保服务器向客户端验证服务器证书。也支持基于 PSK 的 TLS/DTLS 认证。
EMQ X 支持使用内置数据源(文件、内置数据库)、JWT、外部主流数据库和自定义 HTTP API 作为身份认证数据源。连接数据源、进行认证逻辑通过插件实现的,每个插件对应一种认证方式,使用前需要启用相应的插件。客户端连接时插件通过检查其 username/clientid 和 password 是否与指定数据源的信息一致来实现对客户端的身份认证。(v5.0以上默认集成)EMQ X 支持的认证方式:内置数据源、外部数据库、其他。认证结果:认证成功、认证失败、忽略认证(ignore)。
EMQ X 默认配置中启用了匿名认证,任何客户端都能接入 EMQ X。没有启用认证插件或认证插件没有显式允许/拒绝(ignore)连接请求时,EMQ X 将根据匿名认证启用情况决定是否允许客户端连接。
可以订阅多个主题。
安装 paho-mqtt:导入 Paho MQTT 客户端。
通过TCP连接:设置 broker、port、topic、client_id,连接 MQTT Broker。
通过SSL/TLS连接:设置 broker、手机版源码下载port、topic、client_id,连接 MQTT Broker,使用 CA certificate,设置用户名密码。
订阅主题:设置 on_message 回调函数,当收到消息时执行。
取消订阅:通过以下代码取消订阅,此时应指定取消订阅的主题。
发布消息:通过以下代码发布消息,设置消息内容、主题,调用 publish 方法。
接收消息:通过以下代码指定客户端对消息事件进行监听,并在收到消息后执行回调函数,将接收到的消息及其主题打印到控制台。
断开连接:如客户端希望主动断开连接,可以通过如下代码实现。
完整代码:导入 random、time、paho.mqtt.client as mqtt_client,设置 broker、port、topic、client_id,连接 MQTT Broker,设置 on_connect 回调函数,设置 publish 回调函数,运行客户端。
云原生DevOps落地方案
DevOps简述
顾名思义,DevOps是开发(Development)与运维(Operations)的融合,旨在打破开发与运维之间的隔阂,促进开发、运营和质量保障(QA)等部门之间的交流与协作。通过小规模、快速迭代的方式开发和部署产品,以便快速应对客户需求的变化。DevOps强调开发运维一体化,强化团队间的沟通与快速反馈,实现快速交付产品和提高交付质量。
DevOps并非新工具集,而是一种思想、一种文化,旨在改变传统开发运维模式,采用最佳实践。通常通过CI/CD(持续集成、持续部署)自动化工具和流程实现DevOps理念,以流水线形式改变开发人员和测试人员发布软件的方式。随着Docker和Kubernetes(以下简称k8s)等技术的普及,容器云平台基础设施不断完善,加速了开发和运维角色的融合,使云原生的DevOps实践成为未来趋势。以下将基于混合容器云平台详细讲解云原生DevOps的落地方案。
云原生DevOps特点
DevOps是PaaS平台中关键功能模块,包括以下重要能力:支持代码克隆、编译代码、运行脚本、构建发布镜像、部署yaml文件以及部署Helm应用等环节;支持丰富的流水线设置,如资源限额、流水线运行条数、推送代码以及推送镜像触发流水线运行等,提供端到端高效流水线能力;提供开箱即用的镜像仓库中心;提供流水线缓存功能,可自由配置整个流水线或每个步骤的运行缓存,在代码克隆、编译代码、构建镜像等步骤利用缓存缩短运行时间,提升执行效率。
云原生DevOps实现
简单来说,云原生DevOps内部功能设计主要通过k8s提供的自定义controller功能实现,基本逻辑是根据业务需求抽象出多个CRD(Custom Resource Definition,自定义资源对象),编写对应的controller实现业务逻辑。为了实现CI/CD功能,抽象出多个CRD对象,如下所示:
我们知道配置流水线通常需要对接代码仓库,包括仓库地址、仓库授权信息等,因此需要3个CRD对象来记录源代码仓库的相关信息。
设计好DevOps中与仓库相关的3个CRD对象后,需要再定义3个CRD对象来描述流水线相关的信息。
pipeline步骤功能有多种类型,包括运行脚本、构建发布镜像、发布应用模板、部署YAML、部署应用等。为了提供这些功能,采用Jenkins作为底层CI/CD工具,docker registry作为镜像仓库中心,minio作为日志存储中心等。这些服务运行在pipeline所在项目的命名空间下。综上,设计的CI/CD系统功能实现逻辑如下:
如上,第一次运行流水线时,系统会在数据面k8s中部署Jenkins、minio等基础工具的服务,同时在管理面启动一个goroutine,实时同步数据面中流水线的作业状态到管理面的CRD对象中。当触发pipeline执行逻辑时,会产生一个pipelineExecution CRD对象,记录本次运行pipeline的状态信息。当goroutine(syncState)发现有新的执行实例产生时,会通过Jenkins引擎接口启动Jenkins server端流水线作业的运行,Jenkins server端收到信息后会启动单独的一个Jenkins slave pod进行流水线作业的响应。同时,goroutine(syncState)会不断通过引擎接口轮询pipeline执行实例的运行情况,更新pipelineExecution CRD的状态(运行成功或失败等)。当pipeline执行实例发生状态变化时,会触发其对应的controller业务逻辑,通过Jenkins引擎接口与Jenkins server通信进行不同操作,如暂停流水线的运行、运行完毕清除不需要的资源等。当流水线作业发生状态变化时,又会通过goroutine(syncState)更改pipeline执行实例的状态,进而触发对应的controller业务代码进行不同业务逻辑处理,循环往复,直至流水线运行结束。这就是整个pipeline执行时的一个逻辑流程。
CRD定义
以下是详细的CRD结构体讲解,敏感信息使用了’*‘代替。
pipelineSetting:该结构体保存着整个项目下所有pipeline的运行环境信息,如CPU/内存资源限额、缓存路径以及流水线运行的最大并行个数等,不同功能的配置信息保存在不同的CRD下。
pipeline:该结构体记录着流水线的配置元信息,如该流水线对接哪个项目代码、与仓库通信的认证信息以及上次该流水线运行的结果等。如下图所示:
详细的结构字段讲解如下:
pipelineExecution:流水线执行实例,每当流水线运行一次,会产生一个该对象记录着流水线的执行结果等信息。如下图所示:
详细的结构字段讲解如下:
至此,我们完成了流水线功能的基础对象定义。
controller实现
除了抽象出对应的CRD外,还需要编写对应的controller代码实现对应的业务逻辑,如当pipeline运行时,需要产生pipeline执行实例,并实时同步其运行的状态信息等。
当触发流水线执行逻辑时,系统会根据pipeline CRD对象和该流水线对应的代码仓库中的配置文件(.cubepaas.devops.yml)产生一个pipelineExecution CRD对象,这时会触发pipelineExecution对应的controller运行业务逻辑。以下只摘取重要的代码逻辑,如下所示:
其中,deploy函数的逻辑是第一次运行时通过判断数据面中是否存在pipeline的命名空间,如果存在就代表基础资源已经配置完成,直接走reconcileRb函数,该函数的逻辑见下面;如果不存在,就会在数据面中初始化必要的基础资源,如pipeline命名空间、Jenkins、docker、minio服务、配置configMap、secret等。
reconcileRb函数的功能是遍历所有namespace,对其调谐rolebindings,目的是让pipeline serviceAccount(jenkins)对该project下的所有namespace具有所需的操作权限,这样Jenkins server才能够在数据面中正常提供CI/CD基础服务。
goroutine(syncState)的代码逻辑比较简单,当产生新的pipeline执行实例时就会启动Jenkins server端流水线作业的运行并实时同步其运行状态到pipeline执行实例中。代码逻辑如下:
缓存支持
云环境下的流水线是通过启动容器来运行具体的功能步骤,每次运行流水线可能会被调度到不同的计算节点上,这会导致一个问题:容器运行完不会保存数据,每当流水线重新运行时,又会重新拉取代码、编译代码、下载依赖包等,失去了本地宿主机编译代码、构建镜像时缓存的作用,大大延长了流水线运行时间,浪费了很多不必要的时间、网络和计算成本等。为了提高用户使用流水线的体验,加入支持缓存的功能。
为了让流水线具有缓存功能,需要在流水线运行时加入持久化数据的能力。首先想到的是k8s提供的本地持久化存储(即Local Persistent Volume,以下简称Local PV),或依赖远程存储服务器来提供持久化,远程存储效率依赖于网络,并且还需要保证远程存储高可用,这会带来很多复杂性,也一定程度上失去了缓存的作用。综合考虑,我们选择本地存储实现缓存,但是k8s提供的Local PV是需要和节点绑定在一起的,也就是说一旦流水线调度到某个节点上运行,那么下次运行还会绑定到该节点运行,虽然实现了缓存的作用,但是也造成了流水线每次只能在该节点上运行,如果有多条流水线同时跑,可能会导致该节点资源耗尽或者缓存冲突,失去了云平台本身根据资源使用情况平衡调度的特性。
因此,为了平衡缓存与调度间的关系,我们采用了挂载hostPath Volume方式,这样依托于k8s强大的容器调度能力,我们可以同时运行很多条流水线而不用担心资源耗尽或缓存冲突的问题,但是流水线每次运行时可能会被调度到不同的节点上,如果当前节点没有运行过流水线,则起不到缓存的作用。那么如何解决hostPath Volume缓存与调度间的尴尬关系呢?我们巧妙地利用了k8s提供的亲和性调度特性,当流水线运行时我们会记录当前运行节点,下次运行时通过设置Pod的亲和性优先调度到该节点上,随着流水线运行次数越来越多,我们会得到一个运行节点列表。如下所示:
执行实例调度信息会保存到pipeline CRD对象中,每次运行流水线时,系统会根据节点列表设置Pod的亲和性,默认我们会取最近运行流水线的个节点,原则是最近运行流水线的节点优先级越高。代码如下:
创新性的“Hostpath Volume + 亲和性调度”缓存设计方案,不仅实现了流水线的并发性缓存功能,而且实现复杂度低,可自由配置任一阶段、步骤的缓存开关以及缓存路径。无缓存与有缓存运行的对比如下图所示,可见通过缓存加速大大提高了流水线的运行效率。
HCaaS DevOps使用
以上设计在HCaaS平台上得到实现()。在HCaaS控制台上点击DevOps标签,通过代码授权后,即可通过UI界面轻松地编辑流水线,也可通过编辑yaml文件配置具体的功能步骤,如图所示:
通过点击查看日志,你可以看到pipeline各个阶段运行的详细日志信息,如下图所示:
注意首次运行pipeline时系统会从网络下载Jenkins、docker、minio以及其他pipeline-tools镜像,请稍作等待。如果长时间未运行,请查看网络是否有问题。