Netty+WebSocket 获取火币交易所时时数据项目

先附上项目项目GitHub地址 spring-boot-netty-websocket-huobi

项目简介

本项目使用 SpringBoot+Netty来开发WebSocket服务器,与火币交易所Websocket建立连接,时时获取火币网交易所推送过来的交易对最新数据

该项目可以直接运用于实际开发中,做为获取各大交易所最新交易对相关数据的项目。

项目本身也是我在之前公司为了获取各大交易所数据所开发的项目,现在只是重新整理了下代码,现在它更像一个脚手架项目,可以在此基础上很方便的添加其它交易所。

技术架构

SpringBoot2.1.5 +Netty4.1.25 + Maven3.5.4 + lombok(插件)

项目测试

直接启动Springboot启动类Application.java,就可以时时获取火币网推送过来交易对的数据了。

如图

一、项目概述

1、项目启动入口

在项目启动的时候就开始去连接火币交易所Websocket订阅数据。

   /**
* 首次启动并订阅火币websocket数据
*/
@PostConstruct
public void firstSub() {
try {
huobiProMainService.start();
} catch (Exception e) {
log.error("huobi 首次启动订阅异常", e);
}
}

2、获取交易对数据

我们是先要获取火币交易所所有的交易对数据,然后告诉火币交易所我需要订阅哪些交易对数据。

是订阅所有交易对数据还是订阅部分交易对数据。

    @Override
public synchronized List<String> getChannelCache() {
// 假设这里是从远处拉取交易对数据
List<String> list = Lists.newArrayList("btcusdt");
return list;
}

3、连接火币交易所Websocket,并订阅指定的交易对。

先与火币网WebSocket建立连接,连接成功后再告诉它我要订阅哪些交易对,哪种主题,成功后,火币交易所就会根据我们所订阅的主题和交易对,给我们时时推送消息。

 /**
* 首次订阅交易对数据
*
* @param channelList 交易对列表
* @param topicFormat 交易对订阅主题格式
*/
private void firstSub(List<String> channelList, String topicFormat) {
//封装huoBiProWebSocketService对象
klineClient = new HuoBiProWebSocketClient(huoBiProWebSocketService);
//启动连接火币网websocket
klineClient.start();
for (String channel : channelList) {
//订阅具体交易对
klineClient.addSub(formatChannel(topicFormat, channel));
}
}

启动连接火币网websocket核心代码

很明显我们我们是作为客户端去获取服务端的数据,所以这里的Bootstrap来与服务端进行数据交互,而不是用ServerBootstrap

还有一点就是作为客户端,我们是要获取服务端所推送来的消息,所以我们自定义的handler是入站Handler,所以这里选择的是SimpleChannelInboundHandler

   /**
* 连接WebSocket,
*
* @param uri url构造出URI
* @param handler 处理消息
*/
protected void connectWebSocket(final URI uri, SimpleChannelInboundHandler handler) {
try {
String scheme = uri.getScheme() == null ? "http" : uri.getScheme();
final String host = uri.getHost() == null ? "127.0.0.1" : uri.getHost();
final int port; if (uri.getPort() == -1) {
if ("http".equalsIgnoreCase(scheme) || "ws".equalsIgnoreCase(scheme)) {
port = 80;
} else if ("wss".equalsIgnoreCase(scheme)) {
port = 443;
} else {
port = -1;
}
} else {
port = uri.getPort();
} if (!"ws".equalsIgnoreCase(scheme) && !"wss".equalsIgnoreCase(scheme)) {
System.out.println("Only WS(S) is supported");
throw new UnsupportedAddressTypeException();
}
final boolean ssl = "wss".equalsIgnoreCase(scheme);
final SslContext sslCtx;
if (ssl) {
sslCtx = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
} else {
sslCtx = null;
} group = new NioEventLoopGroup(2);
//构建客户端Bootstrap
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
if (sslCtx != null) {
pipeline.addLast(sslCtx.newHandler(ch.alloc(), host, port));
}
//pipeline可以同时放入多个handler,最后一个为自定义hanler
pipeline.addLast(new HttpClientCodec(), new HttpObjectAggregator(8192), handler);
}
});
channel = bootstrap.connect(host, port).sync().channel();
} catch (Exception e) {
log.error(" webSocketClient start error.", e);
if (group != null) {
group.shutdownGracefully();
}
}
}

4、自定义handler

自定义Handler才是核心,作为数据的入站这里选择继承SimpleChannelInboundHandler,继承它必须要实现一个方法就是channelRead0,通过该方法的msg,就可以获取火币交易所时时推送过来的消息了。

/**
* @Description: 火币网WebSocket 消息处理类
* 自定义入站的handler 这个也是核心类
*/
@Slf4j
public class HuoBiProWebSocketClientHandler extends SimpleChannelInboundHandler<Object> { private WebSocketClientHandshaker handshaker;
private HuoBiProWebSocketClient client; /**
* 该handel获取消息的方法
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
Channel channel = ctx.channel();
WebSocketFrame frame = (WebSocketFrame) msg;
if (frame instanceof BinaryWebSocketFrame) {
//火币网的数据是压缩过的,所以需要我们进行解压
BinaryWebSocketFrame binaryFrame = (BinaryWebSocketFrame) frame;
//获取数据、保存数据
client.onReceive(decodeByteBuf(binaryFrame.content()));
} else if (frame instanceof TextWebSocketFrame) {
TextWebSocketFrame textWebSocketFrame = (TextWebSocketFrame) frame;
client.onReceive(textWebSocketFrame.text());
}
}
}

二、项目注意点

1、服务器问题

一般交易所的服务器都在国外,所以我们本地是无法建立Websocket连接的,除非本地翻墙。

同样项目也不能部署到阿里云等国内服务器,你只能选择香港或者国外服务器部署项目。

这里是火币网专门为我们提供的国内测试地址,所以本地可以获取数据。

2、获取交易所最新交易对数据问题

我们在向交易所Websocket订阅交易对的时候,首先就是要知道该交易所有哪些交易对,这份数据是需要我们单独去获取的,而且不是一次获取就好了。

因为该交易所可能新增或者删除交易对。所以需要我们通过定时任务去获取更新最新的交易对数据。

我这边只是模拟了一个交易对btcusdt,并没有提供获取最新交易对数据的服务。

3、数据存储问题

这也是最值得思考的一个问题,数据我们是获取了,但如何保存!

正常合理的开发应该获取数据是一个微服务,处理获取的数据是一个微服务。那么只需要获取数据后去调处理数据微服务就可以保存数据了。

但在这里,如果只是这样是行不通的。

因为火币网向我们推送的消息的速度会比我们调其它服务保存的数据要快,这就会存在数据丢失的情况发生

这里仅仅是输出一个btcusdt交易对,并且只是订阅一个k线主题,而实际上交易所会有上百个交易对和几种订阅主题,

这样的消息推送速度是上面的几百倍。所以你会发现如果你不做任何改动,对于一些大的交易所而言,你的数据是来不及存储的。



补充

这边之前也写过有关 Netty 和 Websocket 相关的博客文章,可以做个参考

1、Netty专题(共9篇)

2、Websocket专题(共5篇)

 我相信,无论今后的道路多么坎坷,只要抓住今天,迟早会在奋斗中尝到人生的甘甜。抓住人生中的一分一秒,胜过虚度中的一月一年!(1)

Netty+WebSocket 获取火币交易所数据项目的更多相关文章

  1. 火币Huobi API Websocket

    本文介绍火币Huobi API Websocket WebSocket API简介 WebSocket协议是基于TCP的一种新的网络协议.它实现了客户端与服务器之间在单个 tcp 连接上的全双工通信, ...

  2. Python3实战系列之七(获取印度售后数据项目)

    问题:续接上一篇.说干咱就干呀,勤勤恳恳写程序呀! 目标:此篇开始进入正题了.为实现我们整个项目功能而开始实现各个子模块功能.首先实现第一篇列出的分步功能模块的第四步: 4.python读取excel ...

  3. 数字货币交易所(火币为例)如何使用二次验证码/虚拟MFA/两步验证/谷歌验证器?

    一般点账户名——设置——安全设置中开通虚拟MFA两步验证 具体步骤见链接  数字货币交易所(火币为例)如何使用二次验证码/虚拟MFA/两步验证/谷歌验证器? 二次验证码小程序于谷歌身份验证器APP的优 ...

  4. Python3实战系列之九(获取印度售后数据项目)

    项目现状:已经部署在服务器上并正常运行了. 1.服务器上的部署 2.下载到服务器的文件列表 3.转存在到数据库SQL Server中的数据 项目总结:这次项目采用python来实现,刚开始还是有点担忧 ...

  5. flink-----实时项目---day06-------1. 获取窗口迟到的数据 2.双流join(inner join和left join(有点小问题)) 3 订单Join案例(订单数据接入到kafka,订单数据的join实现,订单数据和迟到数据join的实现)

    1. 获取窗口迟到的数据 主要流程就是给迟到的数据打上标签,然后使用相应窗口流的实例调用sideOutputLateData(lateDataTag),从而获得窗口迟到的数据,进而进行相关的计算,具体 ...

  6. 直接拿来用!最火的Android开源项目(二)(转)

    GitHub上的开源项目不胜枚举,通过这些项目,也能让开发者在应用开发过程中事半功倍,作为开发者的你,在用这些开源项目吗?今天我们将介绍另外20个在GitHub上备受欢迎的Android开源项目,你准 ...

  7. 直接拿来用!最火的iOS开源项目

    1. AFNetworking 在众多iOS开源项目中,AFNetworking可以称得上是最受开发者欢迎的库项目.AFNetworking是一个轻量级的iOS.Mac OS X网络通信类库,现在是G ...

  8. 直接拿来用!最火的Android开源项目

    GitHub在中国的火爆程度无需多言,越来越多的开源项目迁移到GitHub平台上.更何况,基于不要重复造轮子的原则,了解当下比较流行的Android与iOS开源项目很是必要.利用这些项目,有时能够让你 ...

  9. 最火的Android开源项目(二)

    在<直接拿来用!最火的Android开源项目(一)>中,我们详细地介绍了GitHub上最受欢迎的TOP20 Android开源项目,引起了许多读者的热议,作为开发者,你最常用的是哪些开源项 ...

随机推荐

  1. springboot如何读取自定义配置项

    我们springboot项目有自己默认的配置文件,一般地由application.yml和bootstrap.yml组成,前者是模块的配置,后者是微服务的配置,后台比前者先被框架加载. 我们有时需要自 ...

  2. axios参考手册

      目录 搜索   使用说明   升级指南   生态系统 本文档使用 看云 构建     使用说明 ##Axios Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node ...

  3. Java 添加、修改PPT幻灯片中的表格

    本文将介绍通过Java编程在PPT操作表格的方法.包括添加表格到PPT幻灯片,并设置表格样式.单元格对齐方式.单元格背景色.边框样式.字体.字号.合并单元格等:同时,通过加载已有表格的幻灯片也可以对表 ...

  4. 网络学习笔记(三):HTTP缓存

      HTTP缓存是一种保存资源副本并在下次请求时直接使用该副本的技术,合理的使用缓存可以有效的提升web性能.   浏览器将js文件.css文件.图片等资源缓存,当下次请求这些资源时,可以不发送网络请 ...

  5. Codeforces Round #568 (Div. 2)B

    B. Email from Polycarp 题目链接:http://codeforces.com/contest/1185/problem/B 题目: Methodius received an e ...

  6. python 基本数据类型之整数和布尔值

    #1. 当前整数的二进制表示,以最少位数 # age = # print(age.bit_length()) #2. 获取当前数据的字节表示 # age = # v = age.to_bytes(,b ...

  7. GRPC与.net core

    系列章节 GRPC与.net core GRPC截止时间与元数据 GRPC与netcore Identity GRPC与netcore IdentityServer4 概述 GRPC的数据交互模式有: ...

  8. 曹工说Tomcat4:利用 Digester 手撸一个轻量的 Spring IOC容器

    一.前言 一共8个类,撸一个IOC容器.当然,我们是很轻量级的,但能够满足基本需求.想想典型的 Spring 项目,是不是就是各种Service/DAO/Controller,大家互相注入,就组装成了 ...

  9. Java日志脱敏框架 sensitive-v0.0.4 系统内置常见注解,支持自定义注解

    项目介绍 日志脱敏是常见的安全需求.普通的基于工具类方法的方式,对代码的入侵性太强.编写起来又特别麻烦. 本项目提供基于注解的方式,并且内置了常见的脱敏方式,便于开发. 特性 基于注解的日志脱敏. 可 ...

  10. 面试中常见的算法之Java中的递归

    1.方法定义中调用方法本身的现象2.递归注意实现 1) 要有出口,否则就是死递归 2) 次数不能太多,否则就内存溢出 3) 构造方法不能递归使用3.递归解决问题的思想和图解: 分解和合并[先分解后合并 ...