README.md 16.0 KB
Newer Older
偏锋书生's avatar
read  
偏锋书生 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
---
title: duckula3/install
date: 2020-12-12 22:35:39
tags:
---

# (一) 前言
  互联网体系架构具有可控性差、 数据量大、 架构复杂等特点,错综复杂的各业务模块需要解耦,各异构数据需要同步,双活/多活的容灾方案需要高实时性 等,在各种场合都需要一套可靠的数据实时推送方案。mysql已成为互联网项目存储的主力,围绕着它的各外围模块急需实时地获取它的数据,binlog监听是解决此实时同步问题的不二之选。duckula就是为了满足此需求而设计与开发出来的中间件。

# (二)duckula3简介
  duckula3是一款binlog监听的中间件,但它不仅仅是一款binlog监听的中间件,它可以允许用户自主使用binlog数据。可以有多变的使用方式,可以做为中间件独立布署,也可以嵌入到项目中启动布署,可以嵌入到springboot项目,也可以嵌入到纯java项目,它也有专用于flink的source,可以使flink直连数据库,拿到它的实时数据。由于它良好的插件设计,可以支持任何用户自定义的监听开发。

## duckula的由来

   大概在2016年的时候,我在***中间件团队时,当时公司使用了一套叫“精卫”的中间,由于阿里不对它开源,只是使用权,在支撑业务线运行的过程中,发现了较多的问题,如采用回退12秒HA的模式带来的数据重复推送、界面全是手工录入,耗时也易出错,配置非常复杂(特别是分库分表情况往往要1、2个小时才能搞定),HA时启动失败需要重置位点导致的丢数据没有补全方案等方方面面。  由于没有源码,只能干瞪眼。所以那时就下决心解决这个问题。经过一段时间的选型,在github找了几个binlog解释器,就一条:性能不达标,一票否决了,那时也有关注canel,性能是OK,但是它的设计初是解决两地数据复制问题(当时的版本),而与我要找的是精卫的替代方案,它是要满足数据的分类推送(如哪个表推送哪个消息的topic中)。就有了自研的念头。于是就有了zorro中间件。

   离开这家公司后来到了一家央企,无事可干,实在无聊,zorro的设计还是感觉不满意,代码也不能拿出来,但知识是在脑子里的,于是重写binlog中间件,这就是duckula的雏形,纯粹写着玩了。

  等我写完后,离开了央企,到了下一家互联网公司任技术专家,刚好碰到一个“世纪难题”,一张mysql表已3KW了,没有做分库分表,且开发它代码的人都离职了,没人懂里面的细节了,查询条件非常复杂,索引建了无数,但没用,系统越来越慢,而且每天都有5W多的数据新增,而且要保留很长时间的数据(基本上是全部),不能删除,而且实时性要求很高(基本上前一个状态改了马上要能查到,好做下一步操作), 照这样发展,系统肯定得废啊。于是我想到了duckula,但它只有mysql的binlog到kafka这一个模块,并没有监听kafka插入到es模块,而且3KW数据的全量导入ES也是个问题,总不能产生3KW的binlog事件发kafka吧。kafka也得爆(配置不怎么样),于是加紧开发了 这2个模块,加上前面已有的binlog监听模块,这3个模块就完成了从mysql到ES同步的闭环。完美,这就是duckula1初步完成。
偏锋书生's avatar
偏锋书生 已提交
20

偏锋书生's avatar
read  
偏锋书生 已提交
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
  接下来公司要上paas系统了,我们把中间件全部迁上k8s,把spring cloud这一套也全部上k8s,那么duckula1的SSH连接主机(就像cachcloud)管理binlog监听任务的这一套必须得变了,把原来的有“服务器”变为k8s的“无服务器”布署模式,而且要试着兼容之前的运行模式,这次改造超出了我当初的预期,花费了大量时间,要考虑的东西实在太多了,好在duckula2版本最终出来了,更进一步的是,把它SaaS化,也就是支持让业务线的同学直接跟据需求配置监听任务,这样就没有基础架构组啥事了。且它后面开发了支持"普罗米修斯"的监控。支持binlog的行列过滤等功能也开发了,于是duckula2变得越来越“重”,它表现在布署非常麻烦,配置项就有几百个。

  应该说我们的使用场景太丰富了(toB行业),  接下来又发生了现在的duckula2无法解决的场景----属地化部署,有一个项目有属地化的需求,给我们的机器资源有限,但是duckula2又对zookeeper、kafka等中间件有依赖,duckula2自身也需要布署一个ops(控制台),不可能有这么多的资源让我布署了,于是跟据需求,我把duckula2又进行了一次重构,形成了一个轻量级的binlog监听工具包叫ducklite,它可以以jar包的形式被项目直接引用,分布式锁从zookeeper改为了mysql锁,表的“列名”,“位点”等元数据存储在mysql里不用zookeeper, 这次真的轻了,只依赖mysql就行了,但它只是临时方案,离完整的binlog解决方案还是有些差距。

  在现实使用ducklite中又发现状况,没有全量方案,最开始上线没多少数据,可以全量修改产生全量的binlog确实没问题,等上了生产后产生了大量数据就玩不转了,还有老客户的旧版本迁移到新系统后,旧系统的数据如何全量推ES?还有,由于ducklite是嵌入到应用系统的,监听任务的开发由业务人员完成的,由于开发人员的素质差异,差的监听执行器往往会影响ducklite的监听任务运行,所以他们经常抱怨“太慢了”,“怎么又死了”,于是下决心在ducklite的基础上开发可以独立布署的新版本:duckula3。

## 功能概述

  duckula的重头戏是binlog监听,但它又不止于binlog监听,它的作用范围有了进一步的延伸,如:把监听的消息实时入ES,通过配置完成mysql到ES的快速全量导入等,这样就有了一个从mysql到ES的闭环。有了duckula后,业务开发人员就不用理会mysql到es的同步问题,只需跟据业务需求开发ES的查询语句就可以了。
### 功能模块
  duckula3可以分为三块:

ops:     调度中心,配置中心,不强依赖,只是方便配置和管理执行器。

执行器: binlog监听执行器/kafka consumer执行器/全量导入执行器,这块是duckula的重心。

插件:     支持执行器往各种不同的存储中间件进行导入,现在支持的有ES5、ES6、ES7、kafka、mysql、log(测试用)、http 等
### 配置项
配置项是为了更好的支持执行器的配置,一切都是为了重用,我们把一个执行器需要的配置项分为6大块

- 布署环境    执行器将会在哪个环境里运行,现在支持 k8s/docker/contos7,duckula会使用它的配置来布署执行器

- 实例    binlog监听执行器需要监听哪个数据库,dump(全量导入)需要扫哪个数据库  等配置信息

- 存储中间件   所有的执行器需要把数据发往哪个地方存储或通知,现在支持ES/mysql等

- 版本    执行器使用了duckula3的哪个版本

- 检查点    检查点(checkpoint)是binlog监听执行器用来做HA(高可用),支持 内存/h2db/mysql 三种类型,只有mysql可以做跨机器的HA,h2db只能在本机做HA,内存不能做HA,它需要借助宿主应用做HA,如flink本身就有checkpoint机制,那么duckula3实现的flink source就需要使用内存类型的检查点,duckula3会把元数据借助flink的checkpoint来存储,从而完成HA的。

### 监控
执行器都有通过jmx暴露普罗米修斯接口。

# (三)安装

## 独立安装

### 独立jar包启动

duckula3设计的初衷就是简单,布署简单,配置简单,使用简单

- 执行初始化SQL脚本,创建数据库使用下面的脚本 :duckula-ops\devops\sql\duckula.sql

    https://gitee.com/rjzjh/duckula-ops/blob/master/devops/sql/duckula.sql
偏锋书生's avatar
readme  
偏锋书生 已提交
65 66 67 68 69
    
- 下载执行jar包:

     https://cloud.189.cn/t/ZfAn2uRvaQZz  
     
偏锋书生's avatar
read  
偏锋书生 已提交
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
- 、、跟据实距情况修改下面配置,并保存到用户home目录的duckula-ops.properties文件

  ```properties
  spring.datasource.dynamic.primary=master
  spring.datasource.dynamic.strict=false
  spring.datasource.dynamic.datasource.master.url=jdbc:mysql://docker.for.win.localhost:3306/duckula?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
  spring.datasource.dynamic.datasource.master.username=root
  spring.datasource.dynamic.datasource.master.password=mysql
  spring.datasource.dynamic.datasource.master.driver-class-name=com.mysql.jdbc.Driver
  spring.cloud.refresh.refreshable=none
  mybatis-plus.mapper-locations=classpath:mybatis/primary/sqlmap/*.xml
  logging.level.net.wicp.tams.app.duckula.controller.dao=DEBUG
  ```

- 启动ops。   

  简单启动   : java -jar -server duckula-ops.jar

### 在docker中启动:

前面的文件配置和初始化步骤不变,然后执行:

docker run -d -it --name=duckula-ops -v C:/Users/Administrator:/home/duckula  -p 8080:8080  registry.cn-hangzhou.aliyuncs.com/rjzjh/duckula:ops.3.0.0

停止任务:docker stop duckula-ops

删除任务:docker rm duckula-ops

### 在k8s里启动

要在k8s里启动,首先需要安装helm3,具体安装步骤,k8s的config相关配置, 请自行google。

1. 找到源码的这个目录: duckula-ops\devops\k8s\duckula3-ops

2. cmd到这个目录下,跟据实际情况修改文件:values.yaml,再执行命令:

   helm install  -name rjzjh .\duckula3-ops\  --namespace default

3. 查看相关日志:

偏锋书生's avatar
1  
偏锋书生 已提交
110
   ![日志查看](https://rjzjh.gitee.io/images/duckula3/k8s-view-log.png)
偏锋书生's avatar
read  
偏锋书生 已提交
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162


4. 本地访问地址

  设置本地转发:kubectl port-forward po/rjzjh-duckula-ops-58f87bf5b9-pl7k2   8080:8080  -n   default

  访问地址:http://localhost:8080/



###  在java编译工具中启动(ide,eclipse等)

1. 下载源码,安装好jdk和maven,编译成功

2. 修改配置文件

  如上创建好配置文件duckula-ops.properties,你可以在bootstrap.yml修改配置文件的位置。

3. 启动springboot的启动类
      启动类为:net.wicp.tams.duckula.ops.App

4. 打docker镜像

   先通过maven打包或本地安装jar: maven clean install -Dmaven.test.skip=true -Dmaven.javadoc.skip=true

   切换到target目录下执行:docker build -t   registry.cn-hangzhou.aliyuncs.com/rjzjh/duckula:duckula-ops.3.0.0  .

   上面的group:registry.cn-hangzhou.aliyuncs.com/rjzjh/duckula跟据自己的情况进行替换。

5. 推送镜像到image私服

   docker login -u XXXXX 

   docker push  registry.cn-hangzhou.aliyuncs.com/rjzjh/duckula:duckula-ops.3.0.0  .

## 嵌入式使用
duckula3可以做为一个jar包的方式存在于一个项目的依赖中,如同使用其它的工具类一样,只要引入相关的jar包,很简单的做些配置就可以在宿主项目中跑起来。duckula3已上传到maven中央库,可以在任何使用maven的项目是直接使用,maven坐标为:

```xml
	<dependency>
			<groupId>net.wicp.tams</groupId>
			<artifactId>common-binlog-alone</artifactId>
            <version>最大版本</version>
	</dependency>
```

下面的示例项目在oschina上:https://gitee.com/rjzjh/duckula3-dev-demo

###  纯java(非spring boot)

项目结构如下:

偏锋书生's avatar
1  
偏锋书生 已提交
163
![java结构](https://rjzjh.gitee.io/images/duckula3/java-struct.png)
偏锋书生's avatar
read  
偏锋书生 已提交
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233


主文件入口:

```java
package net.wicp.tams.duckula.demo.cuslistener;

import java.io.IOException;
import java.util.Properties;
import net.wicp.tams.common.Conf;
import net.wicp.tams.common.apiext.IOUtil;
import net.wicp.tams.common.binlog.alone.BusiAssit;

public class Main {
	public static void main(String[] args) throws IOException {
		Properties props = IOUtil.fileToProperties("/common-binlog-chk-mysql.properties", Main.class);
		Conf.overProp(props);
		BusiAssit.startListenerForConfig();
		System.in.read();
	}
}
```

配置文件:

```properties
#插件可以看common-es-plugin的test
common.binlog.alone.binlog.global.busiPluginDir=null
#默认的监听服务配置,如果有多套,复制此配置并修改global.conf为conf.XXXX(见下面示例)
common.binlog.alone.binlog.global.conf.host= localhost
common.binlog.alone.binlog.global.conf.port = 3307
common.binlog.alone.binlog.global.conf.username = root
common.binlog.alone.binlog.global.conf.password = mysql
common.binlog.alone.binlog.global.conf.listener = net.wicp.tams.duckula.demo.cuslistener.TestListener
common.binlog.alone.binlog.global.conf.rds = false
#设置了groupId表示需要做分布式锁,同一个groupId+ip就是一个集群分布式锁
common.binlog.alone.binlog.global.conf.groupId = 20000
#默认使用CheckPointH2db,还提供了CheckPointMemory的chk实现,CheckPointMysql多进程的HA机制
common.binlog.alone.binlog.global.chk=net.wicp.tams.common.binlog.alone.checkpoint.CheckPointMysql
#如果其它与配置相同就可以不配置
common.binlog.alone.binlog.global.chk.mysql.defaultdb=tams
#cur表示从当前最新位点启动,last表示从记录的最后位点启动,pos表示从上面设置的gtids启动
common.binlog.alone.binlog.global.conf.haType = last
#为了做HA,必须填一个,否则不能区分lastPo
common.binlog.alone.binlog.conf.abc.clientId=20000
#监听规则,这是2组,就是test库的user_info和user_addr表被监听,这两张表有binlog时才会给到上面配置的listener
common.binlog.alone.binlog.conf.abc.rule=test`user_info`{}&test`user_addr`{}
```

由于使用的是具有HA和分布式锁的最完备的CheckPointMysql,所以配置项会多一些,而且需要在监听项上创建一个tams数据库(binlog监听时需要存储元数据),监听的帐号对这个库具有建表权限(通过表锁来实现分布式锁),上面这些配置都有说明。

实际上可以使用的配置项会非常多,而且会不断的增加,如果不熟悉的使用者肯定搞晕,所以会有duckula-ops帮助配置和布署。

示例项目见:duckula3-dev-demo-cuslistener

### spring boot

  在spring boot项目中嵌入式使用duckula3,除了上面提及的的maven坐标依赖外,还需引入另一个jar包:

```xml
<dependency>
	<groupId>net.wicp.tams</groupId>
	<artifactId>common-spring-autoconfig</artifactId>
    <version>最后一个版本</version>
</dependency>
```

在启动类需要中入enable注解:


偏锋书生's avatar
1  
偏锋书生 已提交
234
![springboot主入口](https://rjzjh.gitee.io/images/duckula3/springboot-main.png)
偏锋书生's avatar
read  
偏锋书生 已提交
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273

springconfpres配置是指像你数据库连接地址的配置,跟据实际情况修改。

接下来就创建一个监听器,使用注解的方式说明:

```java
//chk默认为CheckPointH2db,如果不变无需配置。conf:随意,不能重复  rule:监听配置,监听duckula库sys_user表
@BinlogListener(conf = "abc", chk = "net.wicp.tams.common.binlog.alone.checkpoint.CheckPointMemory", rule = "duckula`sys_user`{}")
public class TestListener extends AbsBinlogListener {
	@Override
	public void doBusiTrue(Rule rule, DuckulaEvent duckulaEvent, boolean isSplit) {
		String username = DuckulaAssit.getValue(duckulaEvent, "username", 0);
		System.out.println("username=" + username);
	}

	// 当修改表时触发,如加字段
	@Override
	public Result doAlterTableCallBack(Rule rule, ColHis colHis, String sql) {
		return Result.getSuc();
	}

	@Override
	public void doInit(Rule rule, int index) {

	}
}
```

示例项目见:duckula3-dev-demo-springboot

### flink source

duckula3也可以在flink里使用,已完成用于监听binlog的source开发。

用法见博文:https://blog.csdn.net/rjzjh/article/details/100864012

## 访问

  到了见证成果的时候了:
偏锋书生's avatar
1  
偏锋书生 已提交
274
![首页](https://rjzjh.gitee.io/images/duckula3/home.png)
偏锋书生's avatar
read  
偏锋书生 已提交
275 276

布署页:
偏锋书生's avatar
1  
偏锋书生 已提交
277
![布署页](https://rjzjh.gitee.io/images/duckula3/deploy.png)
偏锋书生's avatar
read  
偏锋书生 已提交
278 279 280 281 282