需求

​ 已有Kafka服务,通过kafka服务数据(GPS)落地到本地磁盘(以文本文件存储)。现要根据echarts实现一个实时车辆的地图。

分析

  1. 前端实时展现:使用websocket技术,实现服务器端数据推送到前端展现
  2. 通过Java的kafka client端获取数据,并且通过websock推送到前端。

websocket

简介

​ websocket是HTML5开始提供的一种在单位TCP连接上进行全双工通讯的协议。在websocket api中,浏览器和服务器只需要做一次握手的动作,然后浏览器和服务器之间就形成了一条快速通道。两者之间就可以数据互相传送。

开发

  • 服务器端
  package com.ykkj.weiyi.socket;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.server.standard.SpringConfigurator;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet; /**
* @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
* 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
*/
@ServerEndpoint(value = "/websocket")
public class CommodityServer {
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static int onlineCount = 0; //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
public static CopyOnWriteArraySet<CommodityServer> webSocketSet = new CopyOnWriteArraySet<CommodityServer>(); //与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session session; /**
* 连接建立成功调用的方法
*
* @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
@OnOpen
public void onOpen(Session session) {
this.session = session;
webSocketSet.add(this); //加入set中
addOnlineCount(); //在线数加1
System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
} /**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
webSocketSet.remove(this); //从set中删除
subOnlineCount(); //在线数减1
System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
} /**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息
* @param session 可选的参数
*/
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("来自客户端的消息:" + message);
//群发消息
for (CommodityServer item : webSocketSet) {
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
} /**
* 发生错误时调用
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
System.out.println("发生错误");
error.printStackTrace();
} /**
* 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
*
* @param message
* @throws IOException
*/
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
//this.session.getAsyncRemote().sendText(message);
} public static synchronized int getOnlineCount() {
return onlineCount;
} public static synchronized void addOnlineCount() {
CommodityServer.onlineCount++;
} public static synchronized void subOnlineCount() {
CommodityServer.onlineCount--;
}
}
复制代码

  • 前端

    <!DOCTYPE html>
    <html>
    <head>
    <title>Java后端WebSocket的Tomcat实现</title>
    </head>
    <body>
    Welcome<br/><input id="text" type="text"/>
    <button onclick="send()">发送消息</button>
    <hr/>
    <button onclick="closeWebSocket()">关闭WebSocket连接</button>
    <hr/>
    <div id="message"></div>
    </body> <script type="text/javascript">
    var websocket = null;
    //判断当前浏览器是否支持WebSocket
    if ('WebSocket' in window) {
    websocket = new WebSocket("ws://localhost:8081/onepic/websocket");
    }
    else {
    alert('当前浏览器 Not support websocket')
    } //连接发生错误的回调方法
    websocket.onerror = function () {
    setMessageInnerHTML("WebSocket连接发生错误");
    }; //连接成功建立的回调方法
    websocket.onopen = function () {
    setMessageInnerHTML("WebSocket连接成功");
    } //接收到消息的回调方法
    websocket.onmessage = function (event) {
    setMessageInnerHTML(event.data);
    } //连接关闭的回调方法
    websocket.onclose = function () {
    setMessageInnerHTML("WebSocket连接关闭");
    } //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function () {
    closeWebSocket();
    } //将消息显示在网页上
    function setMessageInnerHTML(innerHTML) {
    document.getElementById('message').innerHTML += innerHTML + '<br/>';
    } //关闭WebSocket连接
    function closeWebSocket() {
    websocket.close();
    } //发送消息
    function send() {
    var message = document.getElementById('text').value;
    websocket.send(message);
    }
    </script>
    </html>
    复制代码

测试

注意点

  1. webSocketSet设置为全局静态变量,为其他类提供调用

    public static CopyOnWriteArraySet<CommodityServer> webSocketSet = new CopyOnWriteArraySet<CommodityServer>();
    复制代码
  2. 服务端都是用注解实现的 @ServerEndpoint @OnOpen @OnClose @OnMessage @OnError

  3. Tomcat7.0.47以上版本支持websocket1.0

  4. pom中添加jar支持

    <dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>7.0</version>
    <scope>provided</scope>
    </dependency>
    复制代码

Kafka

简介

​ Kafka是一个分布式的、可分区的、可复制的消息系统

开发

​ window系统搭建kafka环境,请参照我的《 kafka环境搭建(windows) 》笔记

  • kafka client for java
package com.ykkj.weiyi.socket;

import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer; import java.io.IOException;
import java.util.Arrays;
import java.util.Properties;
import static com.ykkj.weiyi.socket.CommodityServer.webSocketSet; public class ConsumerKafka extends Thread {
private KafkaConsumer<String, String> consumer;
private String topic = "test.topic";
public ConsumerKafka() {
} @Override
public void run() {
//加载kafka消费者参数
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("group.id", "ytna");
props.put("enable.auto.commit", "true");
props.put("auto.commit.interval.ms", "1000");
props.put("session.timeout.ms", "15000");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
//创建消费者对象
consumer = new KafkaConsumer<String, String>(props);
consumer.subscribe(Arrays.asList(this.topic));
//死循环,持续消费kafka
while (true) {
try {
//消费数据,并设置超时时间
ConsumerRecords<String, String> records = consumer.poll(100);
//Consumer message
for (ConsumerRecord<String, String> record : records) {
//Send message to every client
for (CommodityServer webSocket : webSocketSet) {
webSocket.sendMessage(record.value());
} }
} catch (IOException e) {
System.out.println(e.getMessage());
continue;
}
}
} public void close() {
try {
consumer.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
} //供测试用,若通过tomcat启动需通过其他方法启动线程
public static void main(String[] args) {
ConsumerKafka consumerKafka = new ConsumerKafka();
consumerKafka.start();
}
} 复制代码

注意topicbootstrap.servers配置

  • 调用类
  package com.ykkj.weiyi.socket;

  public class RunThread {
public RunThread() {
ConsumerKafka kafka = new ConsumerKafka();
kafka.start();
}
}
复制代码
  • web.xml 配置
 <listener>
<listener-class>com.ykkj.weiyi.socket.RunThread</listener-class>
</listener>
复制代码

测试

注意点

  • ConsumerKafka 需要在web.xml中配置监听,不然在ConsumerKafka 类中不能获取webSocketSet变量
  • 引用webSocketSet变量方式import static com.ykkj.weiyi.socket.CommodityServer.webSocketSet;
  • 注意topicbootstrap.servers配置

结束语

这里只是做了技术验证,还没有真正实现。真实场景下,kafka获取到的数据需要进行数据清洗,把不符合当前规范的数据清洗掉,并且按照前端展示需要的格式组装数据。

参考网上资料

https://blog.csdn.net/lw_ghy/article/details/73252904

https://blog.csdn.net/liu857279611/article/details/70157012

作者:jinshw
链接:https://juejin.im/post/5b20e2e16fb9a01e2c698c51
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

kafka和websocket实时数据推送的更多相关文章

  1. 实时数据推送webSocket

    实时数据推送 在Web或移动项目中,服务器向客户端实时推送消息是一种常见的业务需求. 实现方式 Polling:轮询(俗称“拉”),即定期重新请求数据. Long-Polling:长轮询,是 Poll ...

  2. C# ASP.NET MVC 之 SignalR 学习 实时数据推送显示 配合 Echarts 推送实时图表

    本文主要是我在刚开始学习 SignalR 的技术总结,网上找的学习方法和例子大多只是翻译了官方给的一个例子,并没有给出其他一些经典情况的示例,所以才有了本文总结,我在实现推送简单的数据后,就想到了如何 ...

  3. C# 数据推送 实时数据推送 轻量级消息订阅发布 多级消息推送 分布式推送

    前言 本文将使用一个NuGet公开的组件技术来实现数据订阅推送功能,由服务器进行推送数据,客户端订阅指定的数据后,即可以接收服务器推送过来的数据,包含了自动重连功能,使用非常方便 nuget地址:ht ...

  4. websocket后台数据推送

    Websocket定义: 说明: 作为下一代的 Web 标准,HTML5 拥有许多引人注目的新特性,如 Canvas.本地存储.多媒体编程接口.WebSocket 等等.这其中有“Web 的 TCP ...

  5. 用图解&&实例讲解php是如何实现websocket实时消息推送的

    WebSocket是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议. 以前的推送技术使用 Ajax 轮询,浏览器需要不断地向服务器发送http请求来获取最新的数据,浪费很多的带 ...

  6. swoole+Redis实现实时数据推送

    <?php /** * *************************************** * 单进程保护 * * ********************************* ...

  7. html5 websocket 实时日志推送

    http://blog.csdn.net/neutrojan/article/details/46119645

  8. 我有 7种 实现web实时消息推送的方案,7种!

    技术交流,公众号:程序员小富 大家好,我是小富- 我有一个朋友- 做了一个小破站,现在要实现一个站内信web消息推送的功能,对,就是下图这个小红点,一个很常用的功能. 不过他还没想好用什么方式做,这里 ...

  9. WebSocket与消息推送

    B/S结构的软件项目中有时客户端需要实时的获得服务器消息,但默认HTTP协议只支持请求响应模式,这样做可以简化Web服务器,减少服务器的负担,加快响应速度,因为服务器不需要与客户端长时间建立一个通信链 ...

随机推荐

  1. iOS开发-UILabel和UIButton添加下划线

    关于UILabel和UIButton有的时候需要添加下划线,一般有两种方式通过默认的NSMutableAttributedString设置,第二种就是在drawRect中画一条下划线,本文就简单的选择 ...

  2. Minimum Path Sum leetcode java

    题目: Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right w ...

  3. javaScript:让文本框内的最后一个文字的后面获得焦点

    //当失去交点以后 让文本框内的文字获得焦点 并且光标移到最后一个字后面 function myfocus(myid) { if(isNav){ document.getElementById(myi ...

  4. vc2008中mfc菜单、控件等汉字显示为问号或乱码的解决方法

    在vc2008中建立基于mfc的project.在向导的Application type页面中如果在resource language选项中选择"英语(美国)"(图一),那么在pr ...

  5. express统一输出404页面

    不玩不知道,一玩吓一跳,还真是,nodejs全局404怎么搞? 直接,res.render("404.html")有可能会报错:Node.js : Cannot find modu ...

  6. Ajax:HyperText/URI, HTML, Javascript, frame, frameset, DHTML/DOM, iframe, XMLHttp, XMLHttpRequest

    本文内容 Ajax 诞生 促使 Ajax 产生的 Web 技术演化 真正 Ajax Ajax 与 Web 2.0 Ajax 背后的技术 2008 年毕业,2011 年看了<Ajax 高级程序设计 ...

  7. java class 文件

    class 文件是什么 1).是对一个java类或一个java接口的全面描述:2).是对java程序二进制文件格式的精确定义:3).一个class文件中只能包含一个类或接口:4).作为程序传给jvm的 ...

  8. iOS运用keychain 把identifierForVendor当成唯一标识。替换advertisingIdentifier

    iOS运用keychain 结合[[[UIDevice currentDevice] identifierForVendor] UUIDString] 取得设备唯一标识 NSString *ident ...

  9. VS2015 之 常用快捷键

    调试执行 F5,终止调试执行 Shift+F5 启动执行 Ctrl+F5 查找下一个 F3,查找上一个 Shift+F3 附加到进程 Ctrl+Alt+P,逐过程 F10,逐语句执行 F11 切换断点 ...

  10. NetCore的控制台应用中搭建WebServer的方法

    一.新建NetCore控制台项目,并引入下列Nuget包: Microsoft.AspNetCore.StaticFiles.Microsoft.AspNetCore.Http.Microsoft.A ...