2011-07-04 29 views
5

Tôi đang phát triển một ứng dụng đa quy trình bằng cách sử dụng Node.js. Trong ứng dụng này, một tiến trình cha mẹ sẽ sinh ra một tiến trình con và giao tiếp với nó bằng cách sử dụng một giao thức nhắn tin dựa trên JSON trên một đường ống. Tôi đã tìm thấy rằng các thư JSON lớn có thể bị "cắt", sao cho một "đoạn" duy nhất được phát ra cho trình lắng nghe dữ liệu trên đường ống không chứa thông báo JSON đầy đủ. Hơn nữa, các tin nhắn JSON nhỏ có thể được nhóm lại trong cùng một đoạn. Mỗi thông điệp JSON sẽ được giới hạn bởi một ký tự dòng mới, và vì vậy tôi tự hỏi liệu đã có một tiện ích nào sẽ đệm luồng đọc của đường ống sao cho nó phát ra một dòng tại một thời điểm (và vì thế, đối với ứng dụng của tôi, một tài liệu JSON tại một thời điểm). Điều này có vẻ như nó sẽ là một trường hợp sử dụng khá phổ biến, vì vậy tôi tự hỏi nếu nó đã được thực hiện.Luồng dòng hướng trong Node.js

Tôi đánh giá cao bất kỳ hướng dẫn nào mà bất kỳ ai cũng có thể cung cấp. Cảm ơn.

+0

Bạn đã nghĩ đến việc chỉ sử dụng tốt HTTP cũ ? Tại sao bạn phát minh ra một giao thức IPC mới? Gửi tin nhắn JSON qua HTTP là một vấn đề được giải quyết, và nút là tuyệt vời tại HTTP. –

+0

Bạn có thể mô tả cách bạn sẽ làm điều đó với HTTP không?Ngay bây giờ, tôi không thấy làm thế nào điều này sẽ thay đổi bản chất của vấn đề, như tôi tin rằng bạn vẫn sẽ được đọc khối từ một dòng. – jbeard4

+0

Bạn mã hóa quy trình con của bạn như một máy chủ HTTP node.js thông thường. Khả năng chấp nhận và gửi tin nhắn JSON được cung cấp bởi phần mềm trung gian bodyParser express.js/connect.js. https://github.com/senchalabs/connect/blob/master/lib/middleware/bodyParser.js. Điều này xử lý các khối trong sự kiện tiêu chuẩn node.js được định hướng. Không cần phải tái phát minh ra cơ chế này. –

Trả lời

4

Có lẽ Pedro's carrier có thể giúp bạn?

Nhà cung cấp dịch vụ giúp bạn triển khai các giao thức mới đã chấm dứt giao thức qua node.js.

Khách hàng có thể gửi cho bạn các khối đường dây và nhà cung cấp dịch vụ sẽ chỉ thông báo cho bạn trên mỗi dòng đã hoàn thành.

1

Giải pháp đơn giản nhất là gửi chiều dài dữ liệu json trước mỗi thư dưới dạng tiền tố có độ dài cố định (4 byte?) Và có trình phân tích cú pháp không khung đơn giản.

Bạn có thể thử node-binary để tránh viết trình phân tích cú pháp theo cách thủ công. Xem ví dụ về tài liệu scan(key, buffer) - nó thực hiện đọc chính xác từng dòng.

2

Giải pháp của tôi cho vấn đề này là gửi tin nhắn JSON từng chấm dứt với một số ký tự unicode đặc biệt. Một ký tự mà bạn sẽ không bao giờ nhận được trong chuỗi JSON. Gọi nó là TERM.

Vì vậy, người gửi chỉ cần thực hiện "JSON.stringify (message) + TERM;" và viết nó. Người nhận sẽ chia nhỏ dữ liệu trong TERM và phân tích cú pháp các phần bằng JSON.parse() khá nhanh. Bí quyết là thông điệp cuối cùng có thể không phân tích cú pháp, vì vậy chúng tôi chỉ cần lưu đoạn đó và thêm nó vào đầu thư tiếp theo khi nó đến. Đang nhận mã như sau:

 s.on("data", function (data) { 
     var info = data.toString().split(TERM); 
     info[0] = fragment + info[0]; 
     fragment = ''; 

     for (var index = 0; index < info.length; index++) { 
      if (info[index]) { 
       try { 
        var message = JSON.parse(info[index]); 
        self.emit('message', message); 
       } catch (error) { 
        fragment = info[index]; 
        continue; 
       } 
      } 
     } 
    }); 

Nơi "mảnh" được xác định ở đâu đó sẽ tồn tại giữa các khối dữ liệu.

Nhưng TERM là gì? Tôi đã sử dụng ký tự thay thế unicode '\ uFFFD'. Người ta cũng có thể sử dụng kỹ thuật được sử dụng bởi twitter nơi thư được phân tách bằng '\ r \ n' và các tweet sử dụng '\ n' cho các dòng mới và không bao giờ chứa '\ r \ n'

Tôi thấy điều này rất nhiều đơn giản hơn là rối tung với độ dài bao gồm và như vậy.

0

Chừng nào dòng mới (hoặc bất kỳ dấu phân cách bạn sử dụng) sẽ chỉ phân định các thông điệp JSON và không được nhúng trong đó, bạn có thể sử dụng mẫu sau:

const buf = '' 
s.on('data', data => { 
    buf += data.toString() 
    const idx = buf.indexOf('\n') 
    if (idx < 0) { return } // No '\n', no full message 
    let lines = buf.split('\n') 
    buf = lines.pop() // if ends in '\n' then buf will be empty 
    for (let line of lines) { 
    // Handle the line 
    } 
}) 
Các vấn đề liên quan