├── .gitignore ├── README.md ├── pom.xml └── src └── main ├── java ├── CanalStarter.java ├── canal │ ├── CanalChangeInfo.java │ ├── CanalMsg.java │ ├── CanalMsgContent.java │ ├── CanalMsgHandler.java │ ├── CanalMsgMQHandlerImpl.java │ ├── CanalPool.java │ └── CanalService.java ├── consts │ └── CommonConstant.java ├── elasticsearch │ ├── User.java │ └── UserRepository.java └── rabbitmq │ ├── MessageReceiver.java │ └── MessageSender.java └── resources ├── canal └── example.properties ├── elasticsearch └── elasticsearch.xml ├── rabbitmq ├── rabbitmq.properties └── rabbitmq.xml └── spring └── applicationContext.xml /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # IDE 3 | .idea/ 4 | *.iml 5 | target/ 6 | 7 | 8 | 9 | *.class 10 | 11 | # Mobile Tools for Java (J2ME) 12 | .mtj.tmp/ 13 | 14 | # Package Files # 15 | *.jar 16 | *.war 17 | *.ear 18 | 19 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 20 | hs_err_pid* 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jeet-search 2 | 一套基于ES的搜索方案 3 | 4 | ## 环境 5 | - 系统环境:MacOS 10.12 6 | - 数据库:MySQL 5.7.16 7 | - ES版本:stable 2.4.4 8 | - binlog订阅消费组件:canal-1.0.23 9 | - 消息队列:RabbitMQ 3.6.6(注:在canal比较新的版本里已自带投递到MQ的功能) 10 | 11 | ## 原理 12 | - 业务方更新MySQL表记录 13 | - canal模拟mysql slave的交互协议,伪装自己为mysql slave,向mysql master发送dump协议 14 | - mysql master收到dump请求,开始推送binary log给slave(也就是canal) 15 | - canal解析binary log对象(原始为byte流) 16 | - canal客户端将解析后数据发送到到RabbitMQ 17 | - 业务方消费MQ,调用ES API更新索引,实现索引的实时更新 18 | 19 | ## MySQL配置 20 | 修改my.cnf,开启binlog 21 | ``` 22 | [mysqld] 23 | log-bin=mysql-bin #添加这一行就ok 24 | binlog-format=ROW #选择row模式 25 | server_id=1 #配置mysql replaction需要定义,不能和canal的slaveId重复 26 | ``` 27 | 新建canal用户并分配权限 28 | ```sql 29 | CREATE USER canal IDENTIFIED BY 'canal'; 30 | GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%'; 31 | -- GRANT ALL PRIVILEGES ON *.* TO 'canal'@'%' ; 32 | FLUSH PRIVILEGES; 33 | ``` 34 | 35 | ## canal配置 36 | 修改instance.properties,更多配置[戳此](https://github.com/alibaba/canal/wiki/AdminGuide) 37 | ``` 38 | ## mysql serverId 39 | canal.instance.mysql.slaveId = 1234 40 | 41 | # position info,需要改成自己的数据库信息 42 | canal.instance.master.address = 127.0.0.1:3306 43 | canal.instance.master.journal.name = 44 | canal.instance.master.position = 45 | canal.instance.master.timestamp = 46 | 47 | #canal.instance.standby.address = 48 | #canal.instance.standby.journal.name = 49 | #canal.instance.standby.position = 50 | #canal.instance.standby.timestamp = 51 | 52 | # username/password,需要改成自己的数据库信息 53 | canal.instance.dbUsername = canal 54 | canal.instance.dbPassword = canal 55 | canal.instance.defaultDatabaseName = 56 | canal.instance.connectionCharset = UTF-8 57 | 58 | # table regex 59 | canal.instance.filter.regex = .*\\..* 60 | ``` 61 | 62 | ## elasticsearch配置 63 | 修改elasticsearch.yml 64 | ```yml 65 | cluster.name: jeet-search 66 | ``` 67 | 68 | ## 踩坑 69 | - RabbitMQ topic exchange 路由键a.*无法匹配a.b.c,只有a.*.*才能匹配a.b.c 70 | - spring-data-elasticsearch 暂时不支持ES5,所以最后选择了2.4.4版本 71 | 72 | ## RoadMap 73 | - 2017.3.18 74 | * 启动项目 75 | * 搭建canal,rabbitmq,es环境 76 | - 2017.3.19 77 | * 实现canal和rabbitmq部分逻辑 78 | - 2017.3.25 79 | * 引入Spring框架重构代码 80 | - 2017.4.2 81 | * ES5.x 很多配套的组件不支持,改用2.4.4 82 | * 实现索引构建 83 | - 2017.9.8 84 | * 优化代码,规范项目结构 85 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.bug1024 8 | jeet-search 9 | 1.0-SNAPSHOT 10 | 11 | 12 | jeet-search 13 | 4.2.3.RELEASE 14 | 2.8.8 15 | 1.0.22 16 | 4.11 17 | 1.1.7 18 | 1.6.2 19 | 1.6.2 20 | 21 | 22 | 23 | 24 | 25 | org.springframework 26 | spring-tx 27 | ${spring.version} 28 | 29 | 30 | org.springframework 31 | spring-beans 32 | ${spring.version} 33 | jar 34 | 35 | 36 | org.springframework 37 | spring-context 38 | ${spring.version} 39 | jar 40 | 41 | 42 | org.springframework 43 | spring-aspects 44 | ${spring.version} 45 | 46 | 47 | org.springframework 48 | spring-orm 49 | ${spring.version} 50 | 51 | 52 | org.springframework 53 | spring-test 54 | ${spring.version} 55 | 56 | 57 | org.springframework 58 | spring-web 59 | ${spring.version} 60 | 61 | 62 | org.springframework 63 | spring-webmvc 64 | ${spring.version} 65 | 66 | 67 | 68 | 69 | com.fasterxml.jackson.core 70 | jackson-annotations 71 | ${jackson.version} 72 | 73 | 74 | com.fasterxml.jackson.core 75 | jackson-databind 76 | ${jackson.version} 77 | 78 | 79 | 80 | 81 | org.springframework.data 82 | spring-data-elasticsearch 83 | 2.0.4.RELEASE 84 | 85 | 86 | 87 | 88 | org.springframework.amqp 89 | spring-rabbit 90 | 1.7.1.RELEASE 91 | 92 | 93 | 94 | 95 | com.alibaba.otter 96 | canal.client 97 | ${canal.version} 98 | 99 | 100 | 101 | 102 | junit 103 | junit 104 | ${junit.version} 105 | 106 | 107 | 108 | 109 | org.projectlombok 110 | lombok 111 | 1.16.12 112 | 113 | 114 | 115 | 116 | 117 | spring-libs-snapshot 118 | Spring Snapshot Repository 119 | http://repo.spring.io/libs-snapshot 120 | 121 | 122 | 123 | 124 | 125 | 126 | org.apache.maven.plugins 127 | maven-compiler-plugin 128 | 3.1 129 | 130 | 1.8 131 | 1.8 132 | 133 | 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /src/main/java/CanalStarter.java: -------------------------------------------------------------------------------- 1 | import canal.CanalService; 2 | import org.slf4j.Logger; 3 | import org.slf4j.LoggerFactory; 4 | import org.springframework.context.support.ClassPathXmlApplicationContext; 5 | 6 | /** 7 | * 启动CanalService 8 | * @author bug1024 9 | * @date 2017-11-03 10 | */ 11 | public class CanalStarter { 12 | private static Logger logger = LoggerFactory.getLogger(CanalStarter.class); 13 | 14 | public static void main(String[] args) { 15 | try { 16 | ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:/spring/applicationContext.xml"); 17 | CanalService canalService = (CanalService) context.getBean("canalService"); 18 | canalService.start(); 19 | } catch (Exception e) { 20 | logger.warn("canal service error", e); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/canal/CanalChangeInfo.java: -------------------------------------------------------------------------------- 1 | package canal; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 7 | * @author bug1024 8 | * @date 2017-09-08 9 | */ 10 | @Data 11 | public class CanalChangeInfo { 12 | 13 | private String name; 14 | 15 | private String value; 16 | 17 | private Object update; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/canal/CanalMsg.java: -------------------------------------------------------------------------------- 1 | package canal; 2 | 3 | import consts.CommonConstant; 4 | import lombok.Data; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | * canal消息 10 | * 11 | * @author bug1024 12 | * @date 2017-03-25 13 | */ 14 | @Data 15 | public class CanalMsg { 16 | 17 | private String key; 18 | 19 | private CanalMsgContent canalMsgContent; 20 | 21 | CanalMsg(CanalMsgContent canalMsgContent) { 22 | this.key = CommonConstant.CANAL_MSG_KEY_PREFIX + CommonConstant.KEY_SEPARATOR + canalMsgContent.getDbName() + CommonConstant.KEY_SEPARATOR + canalMsgContent.getTableName(); 23 | this.canalMsgContent = canalMsgContent; 24 | } 25 | 26 | CanalMsg() { 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/canal/CanalMsgContent.java: -------------------------------------------------------------------------------- 1 | package canal; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Canal基础信息 包括表名等 9 | * @author bug1024 10 | * @date 2017-09-08 11 | */ 12 | @Data 13 | public class CanalMsgContent { 14 | 15 | private String binLogFile; 16 | private Long binlogOffset; 17 | private String dbName; 18 | private String tableName; 19 | private String eventType; 20 | private List dataBefore; 21 | private List dataAfter; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/canal/CanalMsgHandler.java: -------------------------------------------------------------------------------- 1 | package canal; 2 | 3 | /** 4 | * canal消息处理 5 | * 6 | * @author bug1024 7 | * @date 2017-03-25 8 | */ 9 | public interface CanalMsgHandler { 10 | 11 | Boolean handle(CanalMsg canalMsg); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/canal/CanalMsgMQHandlerImpl.java: -------------------------------------------------------------------------------- 1 | package canal; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | import rabbitmq.MessageSender; 8 | 9 | /** 10 | * 利用MQ处理canal消息处理 11 | * 12 | * @author bug1024 13 | * @date 2017-03-25 14 | */ 15 | @Service 16 | public class CanalMsgMQHandlerImpl implements CanalMsgHandler { 17 | 18 | private static Logger logger = LoggerFactory.getLogger(CanalMsgMQHandlerImpl.class); 19 | 20 | @Autowired 21 | private MessageSender messageSender; 22 | 23 | @Override 24 | public Boolean handle(CanalMsg canalMsg) { 25 | return messageSender.sendMessage(canalMsg.getKey(), canalMsg.getCanalMsgContent()); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/canal/CanalPool.java: -------------------------------------------------------------------------------- 1 | package canal; 2 | 3 | import com.alibaba.otter.canal.client.CanalConnector; 4 | import com.alibaba.otter.canal.client.CanalConnectors; 5 | import com.alibaba.otter.canal.common.utils.AddressUtils; 6 | import consts.CommonConstant; 7 | import org.springframework.stereotype.Service; 8 | 9 | import java.net.InetSocketAddress; 10 | 11 | /** 12 | * @author bug1024 13 | * @date 2017-03-25 14 | */ 15 | @Service 16 | public class CanalPool { 17 | 18 | public CanalConnector getConnector() { 19 | // @TODO 基于zookeeper动态获取canal server的地址 20 | com.alibaba.otter.canal.client.CanalConnector connector = CanalConnectors.newSingleConnector(new InetSocketAddress(AddressUtils.getHostIp(), CommonConstant.CANAL_PORT), 21 | CommonConstant.CANAL_DEST, 22 | "", 23 | ""); 24 | 25 | return connector; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/canal/CanalService.java: -------------------------------------------------------------------------------- 1 | package canal; 2 | 3 | import com.alibaba.otter.canal.client.CanalConnector; 4 | import com.alibaba.otter.canal.protocol.CanalEntry; 5 | import com.alibaba.otter.canal.protocol.Message; 6 | import consts.CommonConstant; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Service; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | /** 16 | * canal客户端服务 17 | * 18 | * @author bug1024 19 | * @date 2017-03-25 20 | */ 21 | @Service 22 | public class CanalService { 23 | 24 | private static Logger logger = LoggerFactory.getLogger(CanalService.class); 25 | 26 | @Autowired 27 | private CanalMsgHandler canalMsgHandler; 28 | 29 | @Autowired 30 | private CanalPool canalPool; 31 | 32 | public void start() { 33 | int emptyCount = 0; 34 | CanalConnector canalConnector = canalPool.getConnector(); 35 | try { 36 | canalConnector.connect(); 37 | canalConnector.subscribe(".*\\..*"); 38 | canalConnector.rollback(); 39 | 40 | while (emptyCount < CommonConstant.CANAL_TOTAL_EMPTY_COUNT) { 41 | // 获取指定数量的数据 42 | Message message = canalConnector.getWithoutAck(CommonConstant.BATCH_SIZE); 43 | long batchId = message.getId(); 44 | int size = message.getEntries().size(); 45 | if (batchId == -1 || size == 0) { 46 | emptyCount++; 47 | System.out.println(emptyCount); 48 | try { 49 | Thread.sleep(1000); 50 | } catch (InterruptedException e) { 51 | 52 | } 53 | } else { 54 | emptyCount = 0; 55 | processEntry(message.getEntries()); 56 | } 57 | 58 | // 提交确认 59 | canalConnector.ack(batchId); 60 | // 处理失败, 回滚数据 61 | // connector.rollback(batchId); 62 | } 63 | } catch (Exception e) { 64 | logger.warn("canal process error", e); 65 | } finally { 66 | canalConnector.disconnect(); 67 | } 68 | } 69 | 70 | private void processEntry(List entries) { 71 | List msgList = convertToCanalMsgList(entries); 72 | for (CanalMsg msg : msgList) { 73 | canalMsgHandler.handle(msg); 74 | } 75 | } 76 | 77 | private List convertToCanalMsgList(List entries) { 78 | List msgList = new ArrayList(); 79 | CanalMsgContent canalMsgContent = null; 80 | for (CanalEntry.Entry entry : entries) { 81 | if (entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONBEGIN || entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONEND) { 82 | continue; 83 | } 84 | 85 | CanalEntry.RowChange rowChange = null; 86 | try { 87 | rowChange = CanalEntry.RowChange.parseFrom(entry.getStoreValue()); 88 | } catch (Exception e) { 89 | throw new RuntimeException("ERROR ## parse error, data:" + entry.toString(), e); 90 | } 91 | 92 | CanalEntry.EventType eventType = rowChange.getEventType(); 93 | canalMsgContent = new CanalMsgContent(); 94 | canalMsgContent.setBinLogFile(entry.getHeader().getLogfileName()); 95 | canalMsgContent.setBinlogOffset(entry.getHeader().getLogfileOffset()); 96 | canalMsgContent.setDbName(entry.getHeader().getSchemaName()); 97 | canalMsgContent.setTableName(entry.getHeader().getTableName()); 98 | canalMsgContent.setEventType(eventType.toString().toLowerCase()); 99 | 100 | for (CanalEntry.RowData rowData : rowChange.getRowDatasList()) { 101 | canalMsgContent.setDataBefore(convertToCanalChangeInfoList(rowData.getBeforeColumnsList())); 102 | canalMsgContent.setDataAfter(convertToCanalChangeInfoList(rowData.getAfterColumnsList())); 103 | CanalMsg canalMsg = new CanalMsg(canalMsgContent); 104 | msgList.add(canalMsg); 105 | } 106 | } 107 | 108 | return msgList; 109 | } 110 | 111 | private List convertToCanalChangeInfoList(List columnList) { 112 | List canalChangeInfoList = new ArrayList(); 113 | for (CanalEntry.Column column : columnList) { 114 | CanalChangeInfo canalChangeInfo = new CanalChangeInfo(); 115 | canalChangeInfo.setName(column.getName()); 116 | canalChangeInfo.setValue(column.getValue()); 117 | canalChangeInfo.setUpdate(column.getUpdated()); 118 | canalChangeInfoList.add(canalChangeInfo); 119 | } 120 | 121 | return canalChangeInfoList; 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/consts/CommonConstant.java: -------------------------------------------------------------------------------- 1 | package consts; 2 | 3 | /** 4 | * 5 | * @author bug1024 6 | * @date 2017-09-10 7 | */ 8 | public class CommonConstant { 9 | public final static String CANAL_MSG_KEY_PREFIX = "canal"; 10 | 11 | public final static String KEY_SEPARATOR = "."; 12 | 13 | public final static int CANAL_TOTAL_EMPTY_COUNT = 300; 14 | 15 | public final static int CANAL_PORT = 11111; 16 | public final static String CANAL_DEST = "example"; 17 | 18 | public final static int BATCH_SIZE = 1000; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/elasticsearch/User.java: -------------------------------------------------------------------------------- 1 | package elasticsearch; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.Data; 5 | import org.springframework.data.annotation.Id; 6 | import org.springframework.data.elasticsearch.annotations.Document; 7 | 8 | import java.io.Serializable; 9 | import java.sql.Timestamp; 10 | 11 | /** 12 | * user实体类 13 | * 14 | * @author bug1024 15 | * @date 2017-04-02 16 | */ 17 | @Data 18 | @Document(indexName="jeet-search", type="user", refreshInterval="-1") 19 | public class User implements Serializable { 20 | 21 | private static final long serialVersionUID = -2312110729335920029L; 22 | 23 | @Id 24 | private Integer id; 25 | 26 | private Integer username; 27 | 28 | @JsonProperty("real_name") 29 | private String realName; 30 | 31 | private Integer status; 32 | 33 | @JsonProperty("create_time") 34 | private Timestamp createTime; 35 | 36 | @JsonProperty("update_time") 37 | private Timestamp updateTime; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/elasticsearch/UserRepository.java: -------------------------------------------------------------------------------- 1 | package elasticsearch; 2 | 3 | import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * user仓库 9 | * 10 | * @author bug1024 11 | * @date 2017-04-02 12 | */ 13 | public interface UserRepository extends ElasticsearchRepository { 14 | 15 | List findByUsername(String username); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/rabbitmq/MessageReceiver.java: -------------------------------------------------------------------------------- 1 | package rabbitmq; 2 | 3 | import canal.CanalChangeInfo; 4 | import canal.CanalMsgContent; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import com.rabbitmq.client.Channel; 7 | import elasticsearch.User; 8 | import elasticsearch.UserRepository; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.amqp.core.Message; 12 | import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener; 13 | import org.springframework.stereotype.Service; 14 | 15 | import javax.annotation.Resource; 16 | import java.sql.Timestamp; 17 | import java.util.HashMap; 18 | import java.util.List; 19 | import java.util.Map; 20 | 21 | /** 22 | * 接收消息 23 | * 24 | * @author bug1024 25 | * @date 2017-03-26 26 | */ 27 | @Service 28 | public class MessageReceiver implements ChannelAwareMessageListener { 29 | 30 | private static Logger logger = LoggerFactory.getLogger(MessageReceiver.class); 31 | 32 | private static final ObjectMapper MAPPER = new ObjectMapper(); 33 | 34 | @Resource 35 | private UserRepository repository; 36 | 37 | @Override 38 | public void onMessage(Message message, Channel channel) throws Exception { 39 | try { 40 | String jsonString = new String(message.getBody()); 41 | 42 | User user = convertJsonToUser(jsonString); 43 | 44 | repository.save(user); 45 | 46 | // false只确认当前一个消息收到,true确认所有consumer获得的消息 47 | channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); 48 | } catch (Exception e) { 49 | logger.warn("message consume failed: " + e.getMessage()); 50 | // ack返回false,并重新回到队列 51 | channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true); 52 | } 53 | // 拒绝消息 54 | //channel.basicReject(message.getMessageProperties().getDeliveryTag(), true); 55 | } 56 | 57 | private User convertJsonToUser(String jsonString) throws Exception { 58 | CanalMsgContent content = null; 59 | try { 60 | content = MAPPER.readValue(jsonString, CanalMsgContent.class); 61 | } catch (Exception e) { 62 | logger.warn("json decode failed", e); 63 | throw e; 64 | } 65 | 66 | List afterList = content.getDataAfter(); 67 | Map map = new HashMap<>(); 68 | for (CanalChangeInfo changeInfo : afterList) { 69 | map.put(changeInfo.getName(), changeInfo.getValue()); 70 | } 71 | 72 | User user = new User(); 73 | user.setId(Integer.valueOf(map.get("id"))); 74 | user.setStatus(Integer.valueOf(map.get("status"))); 75 | user.setRealName(map.get("real_name")); 76 | user.setCreateTime((Timestamp.valueOf(map.get("create_time")))); 77 | user.setUpdateTime(Timestamp.valueOf(map.get("update_time"))); 78 | 79 | return user; 80 | } 81 | 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/rabbitmq/MessageSender.java: -------------------------------------------------------------------------------- 1 | package rabbitmq; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.amqp.core.AmqpTemplate; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | /** 12 | * 发送消息 13 | * 14 | * @author bug1024 15 | * @date 2017-03-26 16 | */ 17 | @Service 18 | public class MessageSender { 19 | 20 | private static Logger logger = LoggerFactory.getLogger(MessageSender.class); 21 | 22 | private static final ObjectMapper MAPPER = new ObjectMapper(); 23 | 24 | @Autowired 25 | private AmqpTemplate amqpTemplate; 26 | 27 | public Boolean sendMessage(String routingKey, Object message){ 28 | try { 29 | String msg = MAPPER.writeValueAsString(message); 30 | amqpTemplate.convertAndSend(routingKey, msg); 31 | return true; 32 | } catch (JsonProcessingException e) { 33 | logger.warn("json encode failed", e); 34 | return false; 35 | } catch (Exception e) { 36 | logger.warn("send to mq failed", e); 37 | return false; 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/resources/canal/example.properties: -------------------------------------------------------------------------------- 1 | host = 127.0.0.1 2 | port = 11111 3 | destination = example -------------------------------------------------------------------------------- /src/main/resources/elasticsearch/elasticsearch.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main/resources/rabbitmq/rabbitmq.properties: -------------------------------------------------------------------------------- 1 | mq.host = localhost 2 | mq.port = 5672 3 | mq.username = guest 4 | mq.password = guest 5 | mq.vhost = / 6 | -------------------------------------------------------------------------------- /src/main/resources/rabbitmq/rabbitmq.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/main/resources/spring/applicationContext.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | --------------------------------------------------------------------------------