Chọn giao thức thích hợp cho Ứng dụng IoT


12

Chúng tôi đang thực hiện một kịch bản IoT trong đó Thiết bị Thing / Constrained gửi vị trí GPS của nó trong một khoảng thời gian thường xuyên đến một máy chủ nhất định. Thiết bị bị hạn chế là một bo mạch giống như Arduino chạy bằng pin và sử dụng tấm chắn GSM / SIM để kết nối. Đó là những mục tiêu thiết kế của chúng tôi:

  • Tối đa hóa tuổi thọ pin
  • Giảm thiểu truyền dữ liệu

Đối với mục đích thử nghiệm, chúng tôi đã sử dụng HTTP dẫn đến các thông báo khoảng 500 byte, nhưng đã đến lúc sử dụng một giao thức phù hợp hơn để truyền dữ liệu. Một số đặc điểm của việc truyền dữ liệu là:

  • Các tải trọng là khá nhỏ, thường ít hơn 50 byte (khá xa MTUs điển hình, tức là tất cả mọi thứ nên phù hợp trong một gói IP)
  • Dữ liệu nên được gửi khoảng một lần một phút . Một số phương sai không quan trọng.
  • Bạn có thể mất một số tin nhắn
  • Ngay bây giờ, thiết bị không cần bất kỳ loại phản hồi nào từ phục vụ r (tuy nhiên, điều này có thể thay đổi trong tương lai). Máy chủ cũng không phải bắt đầu bất kỳ cuộc trò chuyện nào với các thiết bị.

Cho đến nay chúng tôi đã nghĩ về những khả năng này:

  • Giao thức tùy chỉnh qua TCP . Điều này sẽ loại bỏ các tiêu đề HTTP làm cho thông điệp nhỏ hơn 10 lần. Đây là cách tiếp cận đáng tin cậy / bảo thủ của chúng tôi.
  • Giao thức tùy chỉnh qua UDP . Vì UDP có các tiêu đề nhỏ hơn và không có chi phí cho độ tin cậy, chúng tôi hy vọng sẽ khá hiệu quả. Như đã nhận xét, mất một tin nhắn ở đây hoặc không có gì đáng lo ngại ... tuy nhiên, có thể có các vấn đề khác với độ không tin cậy mà chúng tôi không biết.
  • MQTT (chuẩn qua TCP): Hầu như không có chi phí hoạt động so với TCP, đây cũng có thể là một tùy chọn ... tuy nhiên, chúng tôi không có quá nhiều kinh nghiệm với công nghệ GSM / SIM và không biết làm thế nào một kết nối MQTT liên tục sẽ hoạt động theo cách này và liệu băng tần nhịp tim kết nối có đáng để truyền dữ liệu tần số thấp như vậy hay không.
  • CoAP (tiêu chuẩn trên UDP): Có vẻ đầy hứa hẹn. Chỉ cần 4 byte trên đầu cho các tiêu đề và làm việc trên UDP. Tuy nhiên, rủi ro chưa biết của UDP là có.

Bất cứ ai có thể cho bất kỳ gợi ý? Cảm ơn trước.


1
@RichardChambers trong kịch bản này, độ tin cậy không quan trọng. Chúng tôi có thể đủ khả năng mất một số gói ở đây hoặc ở đó. Acking là không cần thiết. Tôi nghĩ rằng làm việc với độ tin cậy trên UDP không có ý nghĩa quá nhiều, đó là những gì TCP dành cho.
bgusach

1
Tôi sẽ không phát minh lại bánh xe bằng cách thiết kế một giao thức tùy chỉnh. Google của CoAP so với MQTT sẽ giúp bạn cân nhắc nhiều hơn. Bạn có cần phải chứng minh tương lai giải pháp của bạn, tức là. xử lý các yêu cầu khắt khe hơn trong tương lai (đảm bảo mất mát, thời gian đáp ứng, khả năng tương tác, v.v.)? Các thiết bị có phải là NAT không? Có nhóm các thiết bị đằng sau cổng? Nhiều ẩn số ...
Hỗ trợ Gambit

Câu trả lời:


6

Một vài suy nghĩ về trải nghiệm của tôi với TCP, UDP và MQTT cũng như một số tài nguyên bổ sung để xem xét.

Với UDP, tôi đã gặp phải sự cố lỗi im lặng trong đó một ứng dụng trên một nút mạng, máy khách, chỉ thấy một số tin nhắn UDP được gửi. Có quá nhiều lý do tại sao lưu lượng truy cập mạng có thể bị sai lệch. Vấn đề với UDP là các gói có thể bị loại bỏ khá nhiều bất cứ khi nào bất kỳ nút nào trong đường dẫn mạng giữa nhà sản xuất gói và người tiêu dùng gói bảo đảm. Xem chủ đề Wikipedia Mất gói .

Câu hỏi là tỷ lệ mất mát của bạn trong bất kỳ bối cảnh mạng hiện tại là gì. Vì vậy, nếu đây là giao tiếp trong mạng LAN hoặc mạng con, tỷ lệ mất của bạn có thể thấp. Trên mạng LAN hoặc trên internet, tỷ lệ mất của bạn có thể khá cao. Các gói UDP bị loại bỏ vì một số lý do và được định tuyến tuy nhiên các điều kiện mạng cho phép với số giảm hop đó. Gửi các gói ra khoảng trống lớn mà không có trách nhiệm giải trình sẽ mở ra khả năng thất bại thầm lặng.

Có vẻ như trong trường hợp của bạn chỉ là một ack đơn giản với truyền lại sau khi hết thời gian mà không nhận được ack là đủ.

Tôi đã thực hiện các thông báo XML qua kết nối TCP được duy trì và nó hoạt động rất tốt. Tôi đã có một lớp phân phối các thông điệp đầy đủ trong mỗi bộ đệm đến lớp ứng dụng để xử lý. Tôi đã sử dụng XML để đóng gói thư với thẻ bắt đầu XML cho phần đầu của tin nhắn và thẻ kết thúc XML để biết khi nào toàn bộ tin nhắn đã được nhận.

TCP có một vài tính năng như thứ tự các gói liên tục, không lặp lại và là một cơ chế vận chuyển được kết nối có nghĩa là bạn biết liệu đầu kia có biến mất hay không mặc dù có thể mất một lúc để tìm hiểu. Kết nối và ngắt kết nối có thể gây ra sự chậm trễ nhưng không nặng nề trong các điều kiện thông thường mặc dù điều kiện mạng có thể khiến thông lượng TCP bị chậm lại.

MQTT là một giao thức được vận chuyển bởi một lớp vận chuyển mạng, thường là TCP. MQTT sử dụng mô hình xuất bản / đăng ký để không lưu trữ tin nhắn. Vì vậy, khi nhà xuất bản xuất bản một thông báo nếu thuê bao không được kết nối vào thời điểm đó thì khi nó kết nối, nó sẽ không nhìn thấy tin nhắn. MQTT là khá nhiều thời gian thực, tôi cho rằng đó là những gì từ xa của từ viết tắt là tất cả về. Tôi thích MQTT cho các thông báo nhỏ và đã thực hiện một số thử nghiệm với tải trọng JSON thông qua MQTT bằng Mosquitto. Xem bài viết này Gửi tin nhắn đáng tin cậy với Mosquitto (MQTT) với tổng quan về MQTT và chất lượng dịch vụ. Và xem bài viết ngắn gọn này với các liên kết đến các tài nguyên bao gồm một ứng dụng mẫu IoT - Mã xuất bản và đăng ký CQTT .

Các thử nghiệm của tôi với MQTT sử dụng văn bản JSON và cơ sở dữ liệu SQLite3 trong thuê bao để lưu trữ thư là tại https://github.com/RichardChambers/raspberrypi/tree/master/mqtt mặc dù nguồn ở dạng C và khá lộn xộn.

Dưới đây là video dài 13 phút # 144 Giao thức Internet: CoAP vs MQTT, Network Sniffing và chuẩn bị cho IKEA Tradfri Hacking . Đây là một bài viết thú vị về CoAP, Giao thức ứng dụng ràng buộc: CoAP là giao thức 'hiện đại' của IoT . Có bản tóm tắt CoAP này:

Những người dùng đầu tiên đồng ý rằng Giao thức ứng dụng ràng buộc hoạt động cực kỳ tốt đối với các mạng và thiết bị bị hạn chế. Một cái gì đó không được biết đến nhiều: "Trên một mạng không dây rất tắc nghẽn - Wi-Fi hoặc di động - CoAP có thể tiếp tục hoạt động khi giao thức dựa trên Giao thức điều khiển truyền (TCP) như MQTT thậm chí không thể quản lý để hoàn thành bắt tay, "Vermillard nói.

Điều này là do không giống như hầu hết các giao thức IoT khác, CoAP được xây dựng dựa trên UDP. Nói cách khác, điều đó có nghĩa là không có bắt tay giao thức hoặc sửa lỗi như gặp phải với TCP. "CoAP có thể không đáng tin cậy như HTTP hoặc đảm bảo việc gửi tin nhắn như MQTT, nhưng nó cực kỳ nhanh", Matthieu lưu ý. "Nếu bạn ổn với một số tin nhắn không được nhận, bạn có thể gửi thêm nhiều tin nhắn trong cùng một khung thời gian."

Có một vài thứ khác như AMQP, STOMP và CBOR mà bạn có thể nhìn vào là tốt. Xem trang web tiêu chuẩn CBOR cũng như luận án này, Triển khai và đánh giá giao thức CBOR . Xem bài viết này, Chọn Giao thức nhắn tin của bạn: AMQP, MQTT hoặc STOMP để so sánh và đối chiếu AMQP, MQTT và STOMP và kết thúc bằng một ghi chú về nhà môi giới RabitMQ:

Hy vọng, điều này có thể giúp nhiều người bắt đầu điều hướng súp giao thức ra khỏi đó cho từng trường hợp sử dụng của bạn. Vì thông thường các công ty có nhiều ứng dụng với các nhu cầu khác nhau, nên chắc chắn bạn có thể cần cả ba nhà môi giới trên các ứng dụng khác nhau. Đó là nơi mà một nhà môi giới đa chủng tộc, polyglot vững chắc như RabbitMQ đến ở vì họ có thể gửi STOMP, MQTT hoặc AMQP và đưa một trong những người khác ra ngoài. Bạn không cần phải bị khóa bởi một trong các giao thức này. Cả ba đều được nhà môi giới RabbitMQ hỗ trợ, làm cho nó trở thành một lựa chọn lý tưởng cho khả năng tương tác giữa các ứng dụng. Kiến trúc plugin cũng cho phép RabbitMQ phát triển để hỗ trợ các phiên bản bổ sung hoặc cập nhật của các giao thức này trong tương lai.

Gói chia sẻ slide này gồm khoảng 60 slide thực hiện so sánh và tương phản giữa bốn giao thức IoT khác nhau, xem xét nhu cầu của hai nhóm IoT khác nhau, Người tiêu dùng và Công nghiệp, có nhu cầu khác nhau về độ tin cậy và độ mạnh. Tiêu chuẩn nhắn tin phù hợp cho IoT là gì? .


4

Nghe có vẻ như là một ứng dụng hoàn hảo cho UDP: cấu trúc liên kết máy khách-máy chủ (không yêu cầu pub / sub), chịu được mất gói và khoảng cách lớn giữa các lần truyền gói đơn có nghĩa là việc không đến đơn hàng không phải là vấn đề.

Tiết kiệm trong thiết lập kết nối và chi phí chung sẽ hoạt động tốt trong lợi của bạn.

Bạn chỉ cần giảm nhẹ chống lại vấn đề thất bại im lặng. Có rất nhiều cách để làm điều này, nhưng gợi ý của tôi là để máy chủ phản hồi mỗi khi nhận được gói x (ví dụ 10). Bằng cách đó, khách hàng biết có bao nhiêu gói tin của mình đang vượt qua và nếu dưới ngưỡng, nó có thể tăng tần số truyền đến mất gói tin phản tác dụng. Nếu không có gì được giải quyết thì TCP sẽ không giúp được gì, vì vậy tốt hơn hết bạn chỉ nên đặt máy khách ở chế độ gặp sự cố cho đến khi điều kiện xóa.

Mất gói tin UDP qua internet thường không cao và nếu đó thường là hiện tượng nhất thời. GSM cung cấp một số đánh giá bộ đệm và tín hiệu vô tuyến để cung cấp một số dung sai cho nhiễu giả.


4

Bạn có bị hạn chế bên ngoài để sử dụng GSM / SIM không?

Một cách khác có thể là sử dụng mạng LoRa:

  • được tối ưu hóa cao cho tải trọng nhỏ
  • được thiết kế để sử dụng năng lượng tối thiểu (và do đó tuổi thọ pin tối đa)
  • là tầm xa theo thiết kế
  • có các lớp kết nối (luôn luôn bật, thừa nhận, không được chấp nhận)
  • đã lên lịch tải xuống các cửa sổ (ví dụ: để cập nhật chương trình cơ sở hoặc RX ACK)

Bạn có thể cắm vào cơ sở hạ tầng LoRa cộng đồng hoặc thương mại hiện có ở hầu hết các quốc gia hoặc bạn có thể triển khai các trung tâm LoRa của riêng mình nếu điều đó phù hợp hơn.

Có sự phát triển tích cực trên toàn cầu và dễ dàng có sẵn các lá chắn tạo mẫu (ví dụ cho Arduino).


1
Mỗi phút một lần như đã đề cập trong câu hỏi là quá thường xuyên để phù hợp với các khoảng thời gian truyền nút LoRa được đề xuất.
Chris Stratton

1
Đồng ý 1 phút là quá thường xuyên. Mặc dù @bgusach không đề cập đến ứng dụng. Nếu tải trọng có thể được mã hóa nhị phân để giảm kích thước và nếu khoảng thời gian 3-5 phút (hoặc thậm chí 10 phút) có thể sử dụng được thì đó có thể là lý tưởng. Dù sao, chỉ là một gợi ý như tôi lưu ý rằng nó không được đề cập trước đây trong các câu trả lời.
BrendanMcL

1
Có, nếu tôi đọc đúng, khoảng 50 byte trong khoảng thời gian bốn phút có thể không phù hợp; nhưng điều đó cần xác minh, nó có thể dễ dàng bị tắt bởi ít nhất là một yếu tố hai.
Chris Stratton

1
Thú vị, nhưng chúng tôi bị hạn chế GSM / SIM (đây là mục đích của người tiêu dùng, thứ gì đó có thể được mua và sử dụng ở bất cứ đâu mà không cần bất kỳ cơ sở hạ tầng nào ngoài mạng điện thoại).
bgusach

3

Tôi muốn phản hồi HTTP tối thiểu với dữ liệu JSON ... phản hồi HTTP có thể thấp hơn nhiều so với chuyển HTTP 500 byte và bạn vẫn tương thích với nhiều máy khách cho các ứng dụng web RESTful.

Một thông điệp HTTP tối thiểu (ví dụ với kết quả JSON) với dữ liệu HTTP aprox 130 byte trông giống như:

HTTP/1.1 200 OK
Server: ProprietaryAndroid
Connection: close
Content-Type: application/json
{
  "lat": "42.00000",
  "long": "10.00000"
}

nếu bạn chỉ muốn GỬI dữ liệu từ ứng dụng của mình đến máy chủ, bạn chỉ cần sử dụng HTTP GET nơi bạn đặt lat / long làm tham số URL. Yêu cầu thậm chí còn ít dữ liệu hơn phản hồi.

GET /?lat=42.00000&long=10.0000 HTTP/1.1
Host: 192.168.0.2 
User-Agent: Proprietary
Accept: */* 
Connection: close

7
Cảm ơn câu trả lời của bạn, nhưng tôi không thấy quan điểm của bạn với Phản hồi HTTP. Chúng tôi muốn thoát khỏi toàn bộ Giao thức HTTP để lưu truyền dữ liệu. Và trên hết, sử dụng GETđể sửa đổi tài nguyên là việc Wrong Thing™cần làm
bgusach

Đồng ý với bạn từ phía kiến ​​trúc sư rằng các động từ khác như POST (dưới dạng động từ phổ quát) trong khi đó phổ biến hơn trong API REST. Phụ thuộc vào mức độ trưởng thành mà bạn đang phát triển API REST. Chỉ muốn cho thấy cách HTTP có thể được giảm thiểu, trong khi vẫn giữ được lợi ích dễ dàng và khả năng tương thích với các khung hiện có (máy khách và máy chủ), đồng thời giữ cho con người dễ đọc. Trả lời bằng một mẫu phản hồi thật khó hiểu ... Nếu bạn muốn GỬI dữ liệu, tất nhiên bạn sẽ sử dụng tin nhắn POST hoặc GET - trong trường hợp POST, với nội dung json mà tôi đã hiển thị trong mẫu đầu tiên của mình.
Christoph Binkleer

3

Không có giao thức "tốt nhất". Chỉ cần cân nhắc nhiều đánh đổi:

  • Thiết bị của bạn sẽ nằm trên các mạng ngẫu nhiên với các cổng ngẫu nhiên bị chặn? Nếu vậy, có thể tốt hơn để sử dụng HTTPS.

  • Nếu bạn gửi UDP, bạn luôn có thể gửi các phép đo N cuối cùng mỗi lần, để mất gói nhỏ bị bỏ qua. Bạn cũng có thể gửi một gói ACK, biến UDP thành một giao thức đáng tin cậy. (Hầu hết các giao thức trên UDP đều làm điều này.)

  • Khách hàng của bạn sẽ quan tâm nếu dữ liệu của họ bị lộ không được mã hóa? Khách hàng của bạn có quan tâm nếu tin tặc có thể tiêm dữ liệu xấu vào các kết nối không được mã hóa đó không? (Nếu vậy, bạn có thể muốn mã hóa.)

  • Điều gì xảy ra nếu ai đó đánh hơi giao thức của bạn và thao tác dữ liệu? Bạn có thể ngăn một thiết bị ghi đè dữ liệu cho người khác không?

  • Bạn sẽ có bao nhiêu thiết bị? Làm thế nào bạn sẽ đối phó với tất cả các thiết bị? Làm thế nào bạn sẽ định tuyến dữ liệu đến nơi cần đến? Làm thế nào để bạn đối phó với bảo trì và nâng cấp cơ sở hạ tầng máy chủ của bạn? Nếu bạn không có kinh nghiệm, có lẽ bạn đang ước tính quá mức khả năng xử lý nhiều kết nối đồng thời. Có thể tốt nhất là thuê ngoài cho một nhà cung cấp (và sử dụng các giao thức của họ, chẳng hạn như AWS IoT).


3

Chúng tôi đã kiểm tra chính xác so sánh tốc độ truyền HTTP và MQTT, xem test2 , trong kịch bản hiện tại của bạn, MQTT sẽ mang lại cho bạn lưu lượng truy cập (và pin) ít hơn 50 lần so với HTTP.

Về cơ bản không có sự khác biệt giữa MQTT và TCP đơn giản (về kích thước thư). Tôi thậm chí sẽ nói rằng về cơ bản không có sự khác biệt giữa TCP thông thường và thông điệp nhị phân và JSON trong tải trọng MQTT. Theo cách đó, sẽ thuận tiện hơn nhiều khi sử dụng MQTT + JSON và dựa vào công nghệ này để phân phối và biểu diễn dữ liệu. Chỉ cần đặt tên cho khóa của bạn nhiều hay ít.

Về UDP, nếu truyền là một lần mỗi phút, thì tốt hơn là sử dụng TCP. Nếu truyền một lần trong 10-20 phút trở lên, thì bạn có thể coi UDP là giải pháp hiệu quả hơn về lưu lượng / pin. Nếu bạn sẽ cố gắng phát triển giao thức riêng với ACK, tôi khuyên bạn nên sử dụng MQTT hoặc TCP và chỉ tập trung vào trường hợp kinh doanh của bạn.

Nói chung - đơn giản hơn bạn thực hiện nó kết quả tốt nhất bạn có thể đạt được trong thời gian ngắn nhất. Nếu tôi là bạn, trong trường hợp đó, tôi nên kiểm tra định dạng nhị phân của riêng UDP + và MQTT + JSON và chọn một trong số chúng. Hoặc thậm chí chỉ mới bắt đầu từ MQTT + JSON và sau đó suy nghĩ xem nó có ổn với trường hợp của tôi không.


1
Tôi sẽ đề cập ở đây một vài từ chống lại UDP. Chúng tôi duy trì hệ thống quản lý đội xe SaaS GPS lớn (hơn 1 triệu xe được kết nối) có khách hàng ở hơn 100 quốc gia trên toàn thế giới. Và gần đây chúng tôi đã phát hiện ra rằng các nhà cung cấp internet có trụ sở tại Hoa Kỳ đang chặn các gói UDP đi ra khỏi Hoa Kỳ vì một số lý do, ngay cả đối với các ứng dụng M2M. Nó đã bắt đầu vài tháng trước, nhưng nó rất đau đớn, vì vậy tôi khuyên bạn nên chọn giao thức dựa trên TCP (MQTT) và dựa trên các tiêu chuẩn toàn cầu. Một số ngày và ở một số quốc gia, bạn thậm chí sẽ buộc phải sử dụng MQTT qua websockets để duy trì kết nối. Chỉ cần một lời khuyên nhỏ.
shal
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.