【问题标题】:How to automate API get data request? when using web sockets如何自动化 API 获取数据请求?使用网络套接字时
【发布时间】:2018-02-02 20:36:55
【问题描述】:

据我所知,Web Sockets 允许双向通信。和 Web 套接字(例如:Socket.io)连接始终处于打开状态。因此,每当有新数据到达时,数据应通过套接字自动推送到视图。

但在下面的代码中,我使用 set_interval 进行 http.get 调用。每 1 秒调用一次 set_interval。

现在,这样做并没有给人一种实时的感觉,即每 1 秒拉一次新数据。这是静态定义的。

简而言之,我想自动化 set_interval 在下面的代码中所做的事情。我不想要静态获取间隔值。这是因为有时股价会在 100 毫秒内变化,有时会在几秒钟内变化一次

现在,如果我将间隔设置为 1 秒,即每 1 秒拨打一次电话。不会看到市场波动的真实感觉。

我不确定开发人员通常如何在 IOT 应用程序中获取数据。例如,实时监控汽车,假设实时获取汽车的速度并在网络或移动应用程序上绘制图表。

我如何在 Stock Ticker 中实现类似的功能? 我想简单地将应用程序插入 API,并在新数据到达时立即将其实时推送给所有查看者(订阅者)-时间。

代码如下

////
// CONFIGURATION SETTINGS
////
var FETCH_INTERVAL = 1000;
var PRETTY_PRINT_JSON = true;

////
// START
////
var express = require('express');
var http = require('http');
var https = require('https');
var io = require('socket.io');
var cors = require('cors');

function getQuote(socket, ticker) {
    https.get({
        port: 443,
        method: 'GET',
        hostname: 'www.google.com',
        path: '/finance/info?client=ig&q=' + ticker,
        timeout: 1000
    }, function(response) {
        response.setEncoding('utf8');
        var data = '';

        response.on('data', function(chunk) {
            data += chunk;
        });

        response.on('end', function() {
            if(data.length > 0) {
                var dataObj;

                try {
                    dataObj = JSON.parse(data.substring(3));
                } catch(e) {
                    return false;
                }

                socket.emit(ticker, dataObj[0].l_cur);
            }
        });
    });
}

我正在根据上面设置的 FETCH_INTERVAL 调用方法 getQuote

function trackTicker(socket, ticker) {
    // run the first time immediately
    getQuote(socket, ticker);

    // every N seconds
    var timer = setInterval(function() {
        getQuote(socket, ticker);
    }, FETCH_INTERVAL);

    socket.on('disconnect', function () {
        clearInterval(timer);
    });
}

var app = express();
app.use(cors());
var server = http.createServer(app);

var io = io.listen(server);
io.set('origins', '*:*');

app.get('/', function(req, res) {
    res.sendfile(__dirname + '/index.html');
});

io.sockets.on('connection', function(socket) {
    socket.on('ticker', function(ticker) {
        trackTicker(socket, ticker);
    });
});

server.listen(process.env.PORT || 4000);

编辑 - 更新

好的,所以我需要实时提要。 (此位已排序)

据我所知,实时提要非常昂贵,为每个在线客户购买 10,000 多个端点非常昂贵。

1) 我如何利用实时 Feed 为 1000 多个最终用户提供服务?我可以使用网络套接字、Redis、发布/订阅、广播或一些将实时信息复制给大量用户的技术吗?我想要一个高效的解决方案,因为我希望尽可能降低实时数据馈送的费用。

我该如何解决这个问题?

2) 是的,我知道轮询需要在服务器端而不是在客户端进行(以避免为每个客户端进行轮询)。但是我需要使用什么技术? websockets、redis、pub/sub 等。

我有 API URL 和访问 API 的令牌。

3) 我不仅需要获取数据并将其推送给最终用户。但是我需要对获取的数据进行一些计算,还需要从 Redis 或数据库中提取数据并对其进行计算,然后将其推送到视图。

例如:

1) data I get in real-time market feed {"a":10, "b":20}
2) get data from DB or Redis  {"x":2, "y":4} 
3) do computation : z = a * x + b * y
4) finally push value of z in the view. 

我如何同时将所有这些实时推送到多个客户端? 你能和我分享一个路线图吗?我得到了实时数据馈送的第一块拼图。

【问题讨论】:

  • 为了获得更多的实时性(而不是在服务器上轮询),您需要从您的股票价格源中获取某种实时信息,以便它告诉您您正在监控的给定股票价格何时发生变化。然后,您让您的服务器跟踪哪个客户正在观看哪些股票,然后您立即将给定股票价格的更新发送给正在观看该股票的任何客户。在服务器上轮询一次比在每个客户端轮询更有效,但它仍然是轮询并且受制于轮询的非实时方面。摆脱这种情况的唯一方法是从源头获取实时提要。
  • @jfriend00 哦,好吧,我明白你的意思了。因此,只有当提要是实时的时,我才能避免在每个 set_interval 进行检查。我们可以聊几分钟吗?关于同一主题,我还有几个问题。
  • 请将您的问题放入您的问题中(然后添加评论以指向编辑),而不是离线其他人看不到的地方。
  • 另外,如果有 100 位客户每个人都在看一只给定的股票,那么您不希望对该股票价格进行 100 次轮询。您希望对其进行一次轮询,然后将该报价转发给所有 100 个客户。所以,你也必须重新考虑你正在做的事情。
  • @jfriend00 我已经更新了我的问题,据我所知添加了 3 个问题。

标签: node.js ajax api sockets get


【解决方案1】:

1) 我如何利用实时 Feed 为 1000 多个最终用户提供服务?我可以使用网络套接字、Redis、发布/订阅、广播或一些将实时信息复制给大量用户的技术吗?我想要一个高效的解决方案,因为我希望尽可能降低实时数据馈送的费用。

我该如何解决这个问题?

要将数据“推送”到浏览器客户端,您需要使用 webSocket 或 socket.io(构建在 webSockets 之上)。然后,只要您的服务器知道有更新,它就可以立即将该更新发送到任何当前连接的对该信息感兴趣的客户端。基本思想是,客户端在网页加载后立即连接到您的服务器,并在网页打开时保持该连接打开。

2) 是的,我知道轮询需要在服务器端而不是在客户端进行(以避免为每个客户端进行轮询)。但是我需要使用什么技术? websockets、redis、pub/sub 等。

我不清楚你到底在问什么。您将使用提供商提供的任何最有效的技术获得最新价格。如果他们提供的只是 http 调用,那么您必须使用 http 请求定期轮询。如果他们提供了一个 webSocket 接口来获取更新,那就更好了。

对于如何跟踪哪些客户对哪些信息感兴趣以及如何分发更新有很多选择。对于单个服务器,您可以轻松构建自己的股票价格地图,其中股票代码是键,客户端标识符数组是地图中的值。然后,每当您获得给定股票的更新时,您只需获取对该股票感兴趣的客户 ID 列表并将更新发送给他们(通过他们的 webSocket/socket.io 连接)。

这也是一种自然的 pub/sub 类型的应用程序,因此任何支持 pub/sub 的后端都可以正常工作。您甚至可以在 .emit(stock, price) 的位置使用 EventEmitter,每个单独的连接都会为他们感兴趣的股票代码添加一个侦听器。

对于大规模的多台服务器,您可能希望使用一些管理发布/订阅流程的外部流程。 Redis 就是一个候选者。

3) 我不仅需要获取数据并将其推送给最终用户。但是我需要对获取的数据进行一些计算,还需要从 Redis 或数据库中提取数据并对其进行计算,然后将其推送到视图。

我真的不明白这里有什么问题。选择您最喜欢的数据库来存储您需要获取的信息,以便您可以按需获取。

我如何同时将所有这些实时推送到多个客户端?你能和我分享一个路线图吗?我得到了实时数据馈送的第一个难题。

  1. 实时数据馈送。
  2. 用于存储用于计算的元数据的数据库。
  3. 一些 pub/sub 系统,可以是自制的,也可以是预构建的包。

然后,按照这一系列事件进行。

  1. 客户端登录,连接 webSocket 或 socket.io 连接。
  2. 服务器接受客户端连接并分配一个clientID,并在clientID和webSocket/socket.io连接之间的某种映射中跟踪连接。仅供参考,socket.io 会自动为您执行此操作。
  3. 客户端告诉服务器它想要监控哪些项目(可能是通过 webSocket/socket.io 连接发送的消息。
  4. 服务器在发布/订阅系统中注册感兴趣的内容(本质上是为客户端订阅它想要监控的每个项目。
  5. 其他客户端做同样的事情。
  6. 每次客户端请求特定项目的数据时,服务器都会确保它正在获取该项目的更新(但服务器会获取其更新)。
  7. 服务器获取一个或多个客户感兴趣的某些项目的新信息。
  8. 新数据被发送到发布/订阅系统,发布/订阅系统将该信息广播给那些对该特定项目的信息感兴趣的客户。具体如何工作取决于您选择的发布/订阅系统以及它如何通知订阅者更改,但最终会通过 webSocket/socket.io 为已更改的项目发送一条消息。
  9. 当客户端断开连接时,他们的 pub/sub 订阅将被“取消订阅”。

【讨论】:

  • 好的,我得到了第二个问题的答案。也就是说,最好使用 ws(websocket 非安全协议)或 wss(websocket 安全协议)而不是 http 来获取实时数据,因为 websockets 协议是全双工通信通道,它可以实现浏览器和 Web 服务器之间的交互开销,促进与服务器之间的实时数据传输
  • 在第三季度,我询问数据库的原因是:如果我使用 mongoDB,假设作为数据库。那么我的想法是,每秒打开和关闭mongodb连接以获取数据不是很糟糕吗?这就是为什么我认为 redis 内存缓存会更好,我可以每隔一段时间而不是每秒缓存一次数据库中的新值,不是吗?我认为数据库操作繁重且耗时。我不知道存储一些由管理员更新并且也经常用于计算的数据的最佳方式是什么
  • @MurlidharFichadia - 选择什么数据库取决于您的具体要求,这是一项非常重要的研究任务并得出正确的结论。如果您不需要定期将数据持久化到磁盘并且数据集很容易放入内存中,那么 redis 是一个常见的选择。对于 mongoDB,不需要一直打开和关闭连接。您可以打开一个连接并使其保持打开状态,然后通过该连接进行多个查询。根据操作、数据库类型和查询的优化程度,数据库操作可以是繁重的,也可以是轻量的。
  • 最后一个问题。如果我没记错的话,我在这里看到了 2 种不同类型的 pub/sub 系统。一个发布/订阅系统(例如:redis 发布/订阅)会注册哪些客户 (X) 对哪些产品 (Y) 感兴趣,以便提供正确的信息。我看到的另一种 pub/sub 是 socket.io 使用的。例如:如果有 10 个用户访问 localhost:8000/live 页面,那么所有 10 个用户都会自动订阅该页面,如果任何用户离开该页面,他们将被取消订阅。例如:在服务器上:var nsp = io.of('/ch1'); nsp.emit('live', array);在客户端:socket.on('live', function(msg) {//data}
  • @MurlidharFichadia - 在您的第二个示例中,您只是使用页面的 URL 来自动指定用户有兴趣观看的资源(每页的固定资源集)。底层的 pub/sub 确实没有什么不同。您的第一个示例更加灵活。
猜你喜欢
  • 2023-03-11
  • 2015-11-25
  • 1970-01-01
  • 2022-01-26
  • 2021-08-07
  • 1970-01-01
  • 2017-04-09
  • 2017-01-15
  • 1970-01-01
相关资源
最近更新 更多