Node.js 动态创建通过Websocket发送数据的Kafka使用者

Node.js 动态创建通过Websocket发送数据的Kafka使用者,node.js,express,websocket,apache-kafka,kafka-consumer-api,Node.js,Express,Websocket,Apache Kafka,Kafka Consumer Api,我使用kafka节点读取流数据,并使用NodeJS通过web套接字将其传递给我的web应用程序。如果我能够定义kafka producer server和我感兴趣的主题,那么这很好,但是对于我的用例,最终用户将输入kafka producer server和主题,我的NodeJS后端将负责接收该请求并创建适当的kafka/websocket连接 我的想法如下: 创建web应用程序可以向其发送请求的rest API,以便创建新的kafka使用者/web套接字连接(/registerTopic) 创

我使用kafka节点读取流数据,并使用NodeJS通过web套接字将其传递给我的web应用程序。如果我能够定义kafka producer server和我感兴趣的主题,那么这很好,但是对于我的用例,最终用户将输入kafka producer server和主题,我的NodeJS后端将负责接收该请求并创建适当的kafka/websocket连接

我的想法如下:

  • 创建web应用程序可以向其发送请求的rest API,以便创建新的kafka使用者/web套接字连接(/registerTopic)

  • 创建新的kafka使用者时,将新的kafka使用者保存在全局数组中,以便以后可以使用另一个rest API调用(/pauseTopic和/resumeTopic)暂停或恢复流

  • 我在尝试将WebSocket代码移动到/registerTopic时遇到了问题……每当我这样做时,一切都非常奇怪,我突然一次收到1000条消息,然后每秒收到40-50条消息,尽管卡夫卡制作人每秒只发送1条消息。有什么办法可以让它工作吗

    const express = require("express");
    const app = express();
    const cors = require('cors');
    const bodyParser = require('body-parser');
    const fs = require('fs');
    
    
    app.use(cors());
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));
    
    var WebSocketServer = require('websocket').server;
    var http = require('http');
    var https = require('https');
    var kafka = require('kafka-node');
    var topics = [];
    var privateKey = fs.readFileSync('PATH', 'utf8');
    var certificate = fs.readFileSync('PATH', 'utf8');
    var credentials = { key: privateKey, cert: certificate };
    var consumers = new Set();
    
    // This was working without any issues before I tried to make this dynamic!
    /* var Consumer = kafka.Consumer,
      client = new kafka.KafkaClient('localhost:9092'),
      consumer = new Consumer(
        client, [{ topic: 'numtest', partition: 0 }], { autoCommit: false }); */
    
    var server = http.createServer(function (request, response) {
      console.log(' Request recieved : ' + request.url);
      response.writeHead(404);
      response.end();
    });
    server.listen(8080, function () {
      console.log('Listening on port : 8080');
    });
    
    webSocketServer = new WebSocketServer({
      httpServer: server,
      autoAcceptConnections: false
    });
    
    function iSOriginAllowed(origin) {
      return true;
    }
    
    // This was working without any issues before I tried to make this dynamic!
    /* webSocketServer.on('request', function (request) {
      if (!iSOriginAllowed(request.origin)) {
        request.reject();
        console.log(' Connection from : ' + request.origin + ' rejected.');
        return;
      }
    
      let connection = request.accept('echo-protocol', request.origin);
      console.log(' Connection accepted : ' + request.origin);
      connection.on('message', function (message) {
        if (message.type === 'utf8') {
          console.log('Received Message: ' + message.utf8Data);
        }
      });
      consumer.on('message', function (message) {
        console.log('msg');
        connection.sendUTF(message.value);
      });
      connection.on('close', function (reasonCode, description) {
        console.log('Connection ' + connection.remoteAddress + ' disconnected.');
      });
    }); */
    
    var httpsServer = http.createServer(credentials, app);
    
    httpsServer.listen(3000, () => {
      console.log("Server running on port 3000");
    });
    
    app.get("/getTopics", (req, res, next) => {
      res.json(topics);
    });
    
    app.post("/registerTopic", (req, res) => {
      try {
        var client = new kafka.KafkaClient(req.body.host);
        var Consumer = kafka.Consumer;
        consumer = new Consumer(
          client, [{ topic: req.body.topic, partition: 0 }], { autoCommit: false });
        let consumerExists = false;
        for (let c = 0; c < [...consumers].length; c++) {
          if ([...consumers][c].topic == req.body.topic && [...consumers][c].sessionId == req.body.sessionId) {
            consumerExists = true;
          }
        }
        if (!consumerExists) {
          consumers.add({ 'topic': req.body.topic, 'sessionId': req.body.sessionId, 'consumer': consumer });
        }
        client.loadMetadataForTopics([], function (error, results) {
          Object.keys(results[1].metadata).forEach(function (key) {
            var value = results[1].metadata[key];
            if (!value['0'].topic.includes('__') && !value['0'].topic.includes('offset')) {
              topics.push({ 'producer': req.body.host, 'topic': value['0'].topic });
            }
          });
        });
        webSocketServer.on('request', function (request) {
          if (!iSOriginAllowed(request.origin)) {
            request.reject();
            console.log(' Connection from : ' + request.origin + ' rejected.');
            return;
          }
    
          let connection = request.accept('echo-protocol', request.origin);
          console.log(' Connection accepted : ' + request.origin);
          connection.on('message', function (message) {
            if (message.type === 'utf8') {
              console.log('Received Message: ' + message.utf8Data);
            }
          });
          consumer.on('message', function (message) {
            console.log('msg');
            connection.sendUTF(message.value);
          });
          connection.on('close', function (reasonCode, description) {
            console.log('Connection ' + connection.remoteAddress + ' disconnected.');
          });
        });
        res.json("Working");
      } catch (error) {
        console.error(error);
        res.status(400).send('Unable to register new topic')
      }
    });
    
    app.post("/pauseTopic", (req, res) => {
      try {
        console.log(req.body);
        let filteredConsumer = [...consumers].filter(function (item) {
          console.log(req.body.topic, item.sessionId);
          if (item.topic == req.body.topic && item.sessionId == req.body.sessionId) {
            return c;
          }
        });
        console.log(filteredConsumer);
        //filteredConsumer[0].consumer.pause();
        res.json("Working");
      } catch (error) {
        console.error(error);
        res.status(400).send('Unable to register new topic')
      }
    });
    
    app.post("/resumeTopic", (req, res) => {
      try {
        let filteredConsumer = [...consumers].filter(function (item) {
          if (item.topic == req.body.topic && item.sessionId == req.body.sessionId) {
            return item;
          }
        });
        filteredConsumer[0].consumer.resume();
        res.json("Working");
      } catch (error) {
        console.error(error);
        res.status(400).send('Unable to register new topic')
      }
    });
    
    const express=require(“express”);
    常量app=express();
    const cors=需要(“cors”);
    const bodyParser=require('body-parser');
    常数fs=要求('fs');
    应用程序使用(cors());
    use(bodyParser.json());
    use(bodyParser.urlencoded({extended:true}));
    var WebSocketServer=require('websocket').server;
    var http=require('http');
    var https=require('https');
    var kafka=require('kafka-node');
    var主题=[];
    var privateKey=fs.readFileSync('PATH','utf8');
    var certificate=fs.readFileSync('PATH','utf8');
    var凭证={key:privateKey,cert:certificate};
    var consumers=newset();
    //这是工作没有任何问题之前,我试图使这个动态!
    /*var Consumer=kafka.Consumer,
    client=new kafka.KafkaClient('localhost:9092'),
    消费者=新消费者(
    客户端,[{topic:'numtest',分区:0}],{autoCommit:false})*/
    var server=http.createServer(函数(请求、响应){
    log('Request received:'+Request.url);
    书面答复(404);
    response.end();
    });
    监听(8080,函数(){
    log('监听端口:8080');
    });
    webSocketServer=新的webSocketServer({
    httpServer:server,
    自动接受连接:false
    });
    函数等原点(原点){
    返回true;
    }
    //这是工作没有任何问题之前,我试图使这个动态!
    /*webSocketServer.on('request',函数(request){
    如果(!iSOriginAllowed(request.origin)){
    request.reject();
    console.log('connectionfrom:'+request.origin+'rejected');
    返回;
    }
    let connection=request.accept('echo-protocol',request.origin);
    console.log('connectionaccepted:'+request.origin);
    connection.on('message',函数(message){
    如果(message.type==='utf8'){
    console.log('接收到的消息:'+消息.utf8Data);
    }
    });
    consumer.on('message',函数(message){
    console.log('msg');
    connection.sendUTF(message.value);
    });
    connection.on('close',函数(原因代码,描述){
    log('Connection'+Connection.remoteAddress+'disconnected');
    });
    }); */
    var httpsServer=http.createServer(凭证、应用程序);
    httpsServer.listen(3000,()=>{
    log(“在端口3000上运行的服务器”);
    });
    app.get(“/getTopics)”,(请求、恢复、下一步)=>{
    res.json(主题);
    });
    app.post(“/registerTopic)”,(请求、回复)=>{
    试一试{
    var client=new kafka.KafkaClient(req.body.host);
    var消费者=卡夫卡消费者;
    消费者=新消费者(
    客户端,[{topic:req.body.topic,分区:0}],{autoCommit:false});
    让消费者至上=虚假;
    for(设c=0;c<[…消费者]。长度;c++){
    if([…使用者][c].topic==req.body.topic&[…使用者][c].sessionId==req.body.sessionId){
    消费主义者=真;
    }
    }
    如果(!消费者主义者){
    添加({'topic':req.body.topic,'sessionId':req.body.sessionId,'consumer':consumer});
    }
    loadMetadataForTopics([],函数(错误,结果){
    Object.keys(结果[1]。元数据).forEach(函数(键){
    var value=results[1]。元数据[key];
    如果(!value['0'].topic.includes(''u'')&&!value['0'].topic.includes('offset')){
    topics.push({'producer':req.body.host,'topic':value['0'].topic});
    }
    });
    });
    webSocketServer.on('request',函数(request){
    如果(!iSOriginAllowed(request.origin)){
    request.reject();
    console.log('connectionfrom:'+request.origin+'rejected');
    返回;
    }
    let connection=request.accept('echo-protocol',request.origin);
    console.log('connectionaccepted:'+request.origin);
    connection.on('message',函数(message){
    如果(message.type==='utf8'){
    console.log('接收到的消息:'+消息.utf8Data);
    }
    });
    consumer.on('message',函数(message){
    console.log('msg');
    connection.sendUTF(message.value);
    });
    connection.on('close',函数(原因代码,描述){
    log('Connection'+Connection.remoteAddress+'disconnected');
    });
    });
    res.json(“工作”);
    }捕获(错误){
    控制台错误(error);
    res.status(400).send('无法注册新主题')
    }
    });
    应用程序发布(“/pauseTopic)”,(请求、回复)=>{
    试一试{
    控制台日志(请求主体);
    让filteredConsumer=[…使用者].filter(函数(项){
    console.log(req.body.topic,item.sessionId);
    if(item.topic==req.body.topic&&item.sessionId==req.body.sessionId){
    返回c;
    }
    });
    console.log(filteredConsumer);
    //filteredConsumer[0]。使用者。暂停();
    res.json(“工作”);
    }捕获(错误){
    控制台错误(error);
    res.status(400).send('无法注册新主题')
    }