需求

​ 已有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. 杨晓峰-Java核心技术-6 动态代理 反射 MD

    目录 第6讲 | 动态代理是基于什么原理? 典型回答 考点分析 知识扩展 反射机制及其演进 动态代理 精选留言 Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAnd ...

  2. 漂亮的CSS3提交意见输入框样式

    做了个输入框样式,如图: CSS代码如下: <喎�"http://www.2cto.com/kf/ware/vc/" target="_blank" cl ...

  3. 绝对定位常见误区:position:absolute相对于谁定位、及当溢出时怎么隐藏

    1.绝对定位元素溢出父元素,怎么隐藏问题? 通常,为了让DIV子元素超出部分隐藏,都是在父元素设置overflow:hidden,这样即可防止子元素撑开父元素,使子元素能够溢出隐藏! 但是,对于pos ...

  4. Java奇淫巧技之Lombok

    http://blog.csdn.net/ghsau/article/details/52334762

  5. 【Spark】Spark-Redis连接池

    Spark-Redis连接池 jedispool returnresource 遭废弃 用 什么替代_百度知道 spark-stream 访问 Redis数据库示例 - 阿里云 [Redis]Java ...

  6. 机器学习中的损失函数 (着重比较:hinge loss vs softmax loss)

    https://blog.csdn.net/u010976453/article/details/78488279 1. 损失函数 损失函数(Loss function)是用来估量你模型的预测值 f( ...

  7. 转:从头开始编写基于隐含马尔可夫模型HMM的中文分词器

    http://blog.csdn.net/guixunlong/article/details/8925990 从头开始编写基于隐含马尔可夫模型HMM的中文分词器之一 - 资源篇 首先感谢52nlp的 ...

  8. Spring(十二):IOC容器中Bean的生命周期方法

    IOC容器中Bean的生命周期方法 1)Spring IOC容器可以管理Bean的声明周期,Spring允许在Bean生命周期的特定点执行定制的任务. 2)Spring IOC容器对Bean的生命周期 ...

  9. RAMPS1.4 3d打印控制板接线与测试1

    1.需要下载的软件 1.1 固件上传工具--Arduino IDE 这是上传固件的必备工具,有了这个软件让上传固件变的容易很多,插上USB,就可以轻松上传. 下载地址:windows版本:http:/ ...

  10. 如何通过 iframe 共享 jQuery $.data?

    index.html <div id="div1"> </div> <iframe src="ajax2.html" name=& ...