Thứ Năm, 4 tháng 5, 2017

Một số điều cần biết về phương thức MQTT

MQTT (Message Queue Telemetry Transport) là một phương thức truyền nhận dữ liệu rất nhẹ dựa trên TCP/IP. Nó bắt đầu phổ biến theo sự phát triển của IoT devices, khi người ta cần một chuẩn kết nối không chiếm nhiều băng thông và không quan tâm nhiều đến độ trễ.

Pub-sub


Client sẽ subscribe một topic trên server (thường được gọi là broker), sau đó giữa client và broker sẽ mở một connection để bắt đầu gửi/nhận dữ liệu. Khi cần gửi, client (hoặc broker) sẽ publish một message trên connection đã mở, và broker (hoặc client) sẽ nhận được message đó.

Cần lưu ý là, sau khi server nhận message, broker rất có thể sẽ chuyển message này cho một broker (hoặc client) khác, trên một connection khác đã mở trước đó.

QoS


Quality of Service (QoS) có 3 level, cho biết mức độ đảm bảo của việc gửi message:

  • QoS 0 - at most once: client chỉ gửi message đi 1 lần, không cần quan tâm đến việc broker có thật sự nhận được chưa. Mức độ đảm bảo này tương đương với TCP.
  • QoS 1 - at least once: client gửi message đi nhiều lần, cho tới khi nhận được message phản hồi "đã nhận" từ broker.
  • QoS 2 - exactly once: client và broker sẽ gửi qua lại thông qua 4 bước, để đảm bảo message đã được gửi/nhận thành công:
    1. Client gửi nội dung message cho broker.
    2. Broker ack cho client (báo là "đã nhận, cần biết có bị duplicate không").
    3. Client ack tiếp cho broker (báo là "message đó là do chính mình gửi và chưa bị duplicate"). Sau bước này, broker mới thật sự xác nhận là message đúng và đúng 1 lần, và bắt đầu xử lý nội dung message.
    4. Broker báo hoàn tất cho client.

Last will and testament (LWT)


Dịch nghĩa thì nó là di chúc, và có 2 đặc tính:

  • Luôn tạo di chúc trước khi chết
  • Chỉ được sử dụng khi đã chết

Điều đó có nghĩa là: Ngay khi subscribe, nội dung LWT được thiết lập luôn. Và nó được dùng khi broker phát hiện thấy client đã bị offline.

Client và broker sử dụng KeepAlive của TCP để xác định xem client có bị offline hay không. (Cần lưu ý là LWT không gửi gì từ client lên broker, khi connection giữa chúng đã bị ngắt; mọi thông tin đều có từ khi thiết lập kết nối)

Một ví dụ cho việc sử dụng LWT là: Bạn có nhiều device IoT kết nối với server (broker), và nếu có device nào không kết nối được với broker, bạn sẽ nhận SMS thông báo ngay. Khi đó, trên broker sẽ giữ LWT của các device (client) và dùng gói tin KeepAlive để kiểm tra kết nối. Ngay khi không nhận được gói tin KeepAlive từ device, broker gửi gói tin thông báo đến dịch vụ SMS (mà bạn đã thiết lập trước đó) để thông báo bạn ngay.

Retain


Một message mà có RETAIN=1 thì broker sẽ lưu giữ nó, để khi bất kỳ một client nào kết nối vào đúng broker và topic đó thì sẽ nhận được message này. Nó khá là hữu dụng khi muốn thông báo một trạng thái đặc biệt nào đó, ví dụ topic này không còn được dùng nữa, hoặc cần phải force update phần mềm,...

Nhưng nguyên tắc là chỉ có 1 message duy nhất được RETAIN=1 trên broker với 1 topic. Tức là message có RETAIN=1 sau sẽ đè lên message trước. Và nếu RETAIN=1 mà QoS=0 thì mọi message RETAIN=1 đều bị xóa hết.

Xem thêm


Thứ Ba, 12 tháng 7, 2016

KafkaConsumer is not safe for multi-threaded access

I work on project with Play framework Scala, with Guice plugins. It's very nice!

Yesterday, I met the exception:

2016-07-11 08:56:22,936 [ERROR] from akka.actor.OneForOneStrategy in application-akka.actor.default-dispatcher-6 - KafkaConsumer is not safe for multi-threaded access
java.util.ConcurrentModificationException: KafkaConsumer is not safe for multi-threaded access
    at org.apache.kafka.clients.consumer.KafkaConsumer.acquire(KafkaConsumer.java:1324) ~[org.apache.kafka.kafka-clients-0.9.0.1.jar:na]
    at org.apache.kafka.clients.consumer.KafkaConsumer.subscribe(KafkaConsumer.java:713) ~[org.apache.kafka.kafka-clients-0.9.0.1.jar:na]
    at org.apache.kafka.clients.consumer.KafkaConsumer.subscribe(KafkaConsumer.java:747) ~[org.apache.kafka.kafka-clients-0.9.0.1.jar:na]
    at services.kafka.KafkaServiceImpl.consume(KafkaService.scala:73) ~[bb-api.bb-api-1.0-sans-externalized.jar:na]

Reason: I run 2 consumers (difference threads), but just one KafkaService. And I use singleton for it (with Google Guice module). So, when running consumer, it conflict each other.

How to solve? Use @Named annotation in binding.

For example, this is my module file:

class KafkaModule extends AbstractModule with ScalaModule with AkkaGuiceSupport {

  override def configure(): Unit = {
    bind[services.kafka.KafkaService[String, String]].annotatedWith(Names.named("kafka-Coccoc")).to[services.kafka.KafkaServiceImpl].in[Singleton]
    bind[services.kafka.KafkaService[String, String]].annotatedWith(Names.named("kafka-Report")).to[services.kafka.KafkaServiceImpl].in[Singleton]
  }
}

Then, I rewrite my consumer code. Example:

class ReportConsumerActor @Inject() (@Named("kafka-Report") val kafkaService: KafkaService[String, String])
                                    (implicit ec: ExecutionContext){

  def receive: Receive = {
    kafkaService.consume(__SOME_CODE_HERE__)
  }
}

That's all! Hope this help.

Thứ Hai, 1 tháng 2, 2016

TL;DR - Ý nghĩa của OpenGL và các thư viện glew, glu, glut,...

Bài này tổng hợp một số thư viện liên quan đến OpenGL mà hầu hết mọi người đều đụng phải nếu làm việc với OpenGL.

Tôi chỉ hướng tới khái niệm thôi, bạn tự tìm hiểu sâu hơn nếu cần.

OpenGL

OpenGL (Open Graphics Library - http://en.wikipedia.org/wiki/OpenGL)
  • Thư viện render đồ hoạ 2D và 3D
  • Cross-platform, viết bằng C
  • Tập trung vào việc tương tác với GPU

OpenGL-ES

OpenGL-ES (OpenGL for Embedded System - http://en.wikipedia.org/wiki/OpenGL_ES), thường được viết là GLES:
  • Tập con của OpenGL
  • Sử dụng cho các hệ thống nhúng như smartphone, tablet, game console,...

WebGL

WebGL (Web Graphics Library - http://en.wikipedia.org/wiki/WebGL):
  • Thư viện render đồ hoạ 2D và 3D cho trình duyệt
  • API cho JavaScript
  • Được viết dựa trên OpenGL-ES
  • Tương tác với GPU thông qua trình duyệt

GLU

  • Chứa các hàm tiện ích cho OpenGL
  • Tập trung vào mapping giữa các hệ trục toạ độ và các loại kích thước màn hình

GLEW

GLEW (OpenGL Extension Wrangler Library - http://en.wikipedia.org/wiki/OpenGL_Extension_Wrangler_Library):
  • Chứa các hàm tiện ích cho OpenGL
  • Tập trung vào việc load các OpenGL Extension

GLUT

GLUT (OpenGL Utility Toolkit - http://en.wikipedia.org/wiki/OpenGL_Utility_Toolkit):
  • Chứa các hàm tiện ích cho OpenGL
  • Tập trung vào việc dựng và quản lý cửa sổ, các sự kiện bàn phím và chuột

SDL

SDL (Simple DirectMedia Library - http://en.wikipedia.org/wiki/Simple_DirectMedia_Layer):
  • Thư viện phát triển cho OpenGL
  • Tương tác với phần cứng hoặc low-level
  • Làm việc với audio, keyboard, mouse, joystick, graphic hardware,...
  • Có thể được dùng ở các thư viện đồ hoạ khác như DirectX

QT

  • Là framework dùng để thiết kế GUI
  • Chứa khá nhiều widget
  • Được sử dụng khá nhiều trong giới làm OpenGL

Thứ Bảy, 5 tháng 12, 2015

Free SSL cho Google App Engine

Let’s Encrypt (https://letsencrypt.org/) cung cấp một công cụ để mọi người có thể tạo SSL Certificate hoàn toàn miễn phí. Còn Google App Engine lại cung cấp một dạng hosting miễn phí cho các ứng dụng. Kết hợp lại chúng ta sẽ có một server hỗ trợ SSL.

Bài này hướng dẫn vài bước đơn giản để đưa SSL vào domain của bạn trên AppEngine.

Note: bạn phải sử dụng máy Mac hoặc Linux để chạy command line.

Trước hết, download client tool

git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt

Tạo free certificate

sudo ./letsencrypt-auto -a manual certonly

Lúc này, nó sẽ yêu cầu bạn xác nhận domain bằng một thông báo đại loại thế này:

Make sure your web server displays the following content at 
http://www.example.com/.well-known/acme-challenge/{challenge 1} before continuing:
{response 1}
Content-Type header MUST be set to text/plain.
...
Press ENTER to continue

Bạn cần phải đưa vài dòng source code lên server AppEngine của mình. Lưu ý là không nhấn [ENTER] trước khi bạn đưa những dòng code xử lý request lên server của mình.

Đây là mẫu viết bằng Python, và bạn cần copy {challenge} và {response} vào đúng chỗ, để nó có thể xác nhận chính xác:

class LetsEncryptHandler(RequestHandler):

    def get(self, challenge):
        self.response.headers['Content-Type'] = 'text/plain'
        responses = {
                    '{challenge 1}': '{response 1}'
                    '{challenge 2}': '{response 2}'
                }
        self.response.write(responses.get(challenge, ''))

application = WSGIApplication([
    ('/.well-known/acme-challenge/([\w-]+)', LetsEncryptHandler),
])

Tiếp theo là trở lại command line và nhấn [ENTER]. Kết quả là bạn đã có certificate, nhưng nếu bạn mở file private key ra sẽ thấy dòng này -----BEGIN PRIVATE KEY-----. Và chia buồn với bạn là Google App Engine không support SSL theo phương thức này.

Bạn cần phải đổi sang RSA, với câu lệnh:

sudo openssl rsa -in /etc/letsencrypt/live/www.example.com/privkey.pem | less

Giờ thì bạn chỉ cần copy, và vào App Engine > Settings > SSL Certificates, tạo một Certificate và dán private key và public key (file /etc/letsencrypt/live/www.example.com/fullchain.pem) tương ứng vào.

Nhớ đặt cái tên để còn biết. Hihi.

40 cách giúp bạn giữ lửa sáng tạo

Thông tin này khá thú vị, mọi người xem hình infography bên dưới nhé:


Thứ Hai, 4 tháng 5, 2015

Làm sao để thẻ DIV trở thành unselectable?

Đôi khi vì nhu cầu, chúng ta cần làm cho các thẻ DIV trên trang web của mình không thể bôi đen hoặc chọn được. Nhiều người tò mò về việc làm thế nào làm được chuyện này. Thực ra phương pháp rất đơn giản, nhưng trước hết, tôi xin đề cập đến chuyện "Tại sao chúng ta cần việc này?"

Có 2 lý do chính:
  1. Vì ứng dụng cần như thế. Ví dụ bạn viết một cái game, và không muốn trình duyệt bôi đen khi người dùng nhấp đôi chuột hoặc Ctrl-A.
  2. Vì không muốn để người khác dễ dàng copy.

Thứ Bảy, 25 tháng 4, 2015

HTTP/2 là gì?

Nói ngắn gọn, HTTP/2 là phiên bản tiếp theo của chuẩn HTTP. Chuẩn HTTP là chuẩn định nghĩa truyền nhận dữ liệu trên internet, là cái mà bạn luôn thấy ở các địa chỉ trang web.

Chuẩn HTTP/2 này đang gần hoàn thành, nếu không có gì thay đổi thì khoảng tháng 8 năm 2015 sẽ hoàn tất, và việc tiếp theo là triển khai và viết tài liệu hướng dẫn.

Kể từ khi phát hành HTTP/1.1 tới nay đã hơn 15 năm, nhưng chưa có một cải tiến nào đáng kể trong thế giới internet thay đổi không ngừng. Nay, IETF HTTP Working Group đề xuất phiên bản tiếp theo của HTTP với nhiều cải tiến lớn. Rất nhiều cải tiến được lấy cảm hứng từ SPDY của Google. Tôi sẽ điểm qua một số điểm nhấn chính đáng mong đợi.

Biểu mẫu liên hệ

Tên

Email *

Thông báo *