这一篇,主要分析下,client 是怎么 connect server的,以及成功connect server 之后,会做哪些事情,session是怎么 start的。

由protocol 开始

之前分析过message 流向,接受到TCP 数据之后,经过parser 的解析,会交由protocol 进行packet 级别的数据处理,并根据不同的packet type 进行不同的后续处理。

connect 类型的packet 的处理是这样开始的:

 process(Packet = ?CONNECT_PACKET(Var), State0) ->
%% 参数提取
...
%% check proto 以及clientid
case validate_connect(Var, State1) of
?CONNACK_ACCEPT ->
%% auth
...
case mqttd_sm:start_session(CleanSess, clientid(State2)) of
ok ->
%% 把client 相关信息,写到一张ets table 里
...
%% 开始keepalive,后续再分析
start_keepalive(KeepAlive)
_ ->
error
end;
_ ->
error
end,
%% connack

1、提取必要的参数,并进行参数验证

参数验证会检查proto 的version 以及name,并且进行必要的auth check,都通过验证之后,才会继续处理。否则,只好error了。

2、创建session

这个是connect 流程处理的重头戏。

3、记录额外信息,并开始keepalive

记录额外信息,能够进行额外的stat look,dashboard 会用到的。keepalive 就是一个心跳检查。

P1

创建session

0、准备一下

从上一个小节,可以看到,其实connect 流程的处理,主要就是『创建session』。

client 的session 是由session manager 进程创建的,session manager 进程是一个pool,pool size 和scheduler 的数量相关。而这些session managers 是在application start 的时候start的,挂在emqttd_sm_sup supervisor 进程下面(该进程挂在主sup 进程下面)。

而,session 的存储,主要用到的是 『session』mnesia table,其table 字段如下:

-record(mqtt_session,
{client_id :: binary(),
sess_pid :: pid(),
persistent :: boolean()
}).

表为set 类型的表,client_id的key,sess_pid 是client_id 对应的session process id .

1、start_seesion

%% @doc Start a session
-spec(start_session(boolean(), binary()) -> {ok, pid(), boolean()} | {error, any()}).
start_session(CleanSess, ClientId) ->
SM = gproc_pool:pick_worker(?POOL, ClientId),
call(SM, {start_session, {CleanSess, ClientId, self()}}).

start_session/2 是一个接口函数,其实现部分,是在某一个session manager process 的handle_call callback 实现的。start_session/2 的第一个参数表示是否要清理掉旧的session,第二个参数就是clientid,从pool 里面选取一个session manager process,就是根据clientid(类似于hash)。

1.1 callback 的整体逻辑

 handle_call({start_session, Client = {false, ClientId, ClientPid}}, _From, State) ->
%% 查 session
case lookup_session(ClientId) of
undefined ->
%% Create session locally
%% 增 session
create_session(Client, State);
Session ->
%% 恢复 session
case resume_session(Session, ClientPid) of
{ok, SessPid} ->
{reply, {ok, SessPid, true}, State};
{error, Erorr} ->
{reply, {error, Erorr}, State}
end
end;
%% Transient Session
handle_call({start_session, Client = {true, ClientId, _ClientPid}}, _From, State) ->
case lookup_session(ClientId) of
undefined ->
create_session(Client, State);
Session ->
%% 删 session
case destroy_session(Session) of
ok ->
create_session(Client, State);
{error, Error} ->
{reply, {error, Error}, State}
end
end;

在handle_call的callback 中,基本的逻辑是这样的

1、首先根据clientid 查找是否存在session

  2、如果不存在,那么就create 一个全新的session

  3、如果存在,则

    4、要么恢复session

    5、要么先销毁session 之后,再重新create 一个全新的session

P2

1.2 查 session

查找session,是根据『session mnesia table』的key(clientid)进行 dirty_read

1.3 create session

create session 的思路是:

  1. spawn 一个新的进程,并且挂在emqttd_session_sup supervisor进程下面,返回sessionpid
  2. 利用transaction 将{clientid, sessionpid, true|false} 写入到『session mnesia table』
  3. session manager process monitor 一下 sessionpid(崩了之后,清理session 信息)

1.4 恢复session

恢复session 会先根据旧的session记录,判断 old session pid 是否存活,如果存活,则进行恢复操作,否则,error。

1.5 销毁session

首先shutdown sessionpid,然后清理session table即可。

总结

好像也不需要?(resume session 的处理流程 后补)

emqtt 2 (我要连服务器)的更多相关文章

  1. emqtt 试用(四)emq 的主题访问控制 acl.conf

    访问控制(ACL) EMQ 消息服务器通过 ACL(Access Control List) 实现 MQTT 客户端访问控制. ACL 访问控制规则定义: 允许(Allow)|拒绝(Deny) 谁(W ...

  2. mqtt服务器apollo的搭建和测试工具paho的使用

    (1)前言 MQTT协议是IBM开发的一个即时通讯协议; 基于发布/订阅的消息协议,近些年来被广泛应用于能源.电力.....等硬件性能低下的远程设备,此外国内很多企业使用MQTT作为android手机 ...

  3. 常见MQTT服务器搭建[转载]

    简介 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,它比较适合于在低带宽.不可靠的网络的进行远程传感器和控制设备通 ...

  4. 百万级开源MQTT消息服务器 搭建

    下载地址:http://emqtt.com/downloads 文档地址:http://emqtt.com/docs/v2/index.html 开始使用EMQ 2.0 消息服务器简介EMQ (Erl ...

  5. 使用EMQ搭建MQTT服务器

    前言寒假的时候开始搭建mqtt服务器,一开始使用的是RabbitMQ,基于Erlang语言.但是RabbitMQ的本职工作是AMQP,MQTT只是他的一个插件功能,似乎有些大材小用,很多MQTT的功能 ...

  6. 常见MQTT服务器搭建与试用

    常见MQTT服务器搭建与试用   简介 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,它比较适合于在低带宽.不可靠 ...

  7. EMQTT本地源码搭建填坑记录

    因业务需求需要本地搭建一个emqtt的消息队列服务器,根据官网提示搭建失败,具体如下 官方步骤: Erlang 安装: http://www.erlang.org/ MSYS2 安装: http:// ...

  8. emqtt在centos6下的安装

    1 emqtt下载地址 http://www.emqtt.com/downloads 右键 复制链接 http://www.emqtt.com/downloads/3011/centos6 2 打开服 ...

  9. (二 -0) 天猫精灵接入Home Assistant-安装MQTT服务器

    ubuntu 1604  阿里云 学生版轻型服务器 1 安装MQTT 进入官网 http://emqtt.com/ 点击下载 找到  ubuntu 1604  右键-复制链接 粘贴办理内容是下载链接第 ...

随机推荐

  1. 文件(2)--IO流

    IO流 输入流和输出流 Java中的IO流根据功能划分为:输入流和输出流.输入流:用于读取数据.输出流:用于写出数据.输入输出的参照方向是根据我们的程序的. 字节流和字符流 Java中的IO流根据处理 ...

  2. 编程练习赛11B 物品价值(装压dp)

    题意:每个物品有m(m<=10)种属性和一个价格,你有n种物品从中任意选择一些物品,让每种属性恰好有奇数个物品拥有,输出满足条件的最大价值和 题解:一看就是明显的01背包问题,但是价格乘以个数的 ...

  3. [WPF+Prism]WPF个人集成平台

    前段时间学习了一下Prism,感觉应该找个机会实践一下,而且前段时间,贱内(希望我老婆看不到这篇文章:))让我帮她做个定时提醒的小工具,做好之后感觉以前做了好多自己能用的小工具,如果能够整合到一起,该 ...

  4. 用Java编程计算兔子生兔子的问题

    题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 程序分析: 这是一个典型的Fibonacci数列问 ...

  5. Java多线程 - 控制线程

    join线程 在某个线程的执行流中调用其他线程的join()方法时,调用线程将被阻塞,直到被join()方法加入的线程完成为止. join()方法有三种重载形式: join():等待被join的线程执 ...

  6. 安装Charles报错

    去年用的是charles4.1.2版本,今年这个版本的安装包始终安装报错,不管公司电脑还是自己电脑........ 我的解决方案很Lower的.......... 登录Charles官网:https: ...

  7. 【总结】对异步处理的http接口进行性能测试

    以前对接口做性能测试,接口都是同步处理的,请求之后等待响应结果就知道处理结果了,这样只要看这个接口是否异常,如果无异常无报错记录这个接口的响应时间.TPS等性能指标进行分析就可以了,最近在工作中遇到了 ...

  8. LeetCode OJ:Recover Binary Search Tree(恢复二叉搜索树)

    Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...

  9. Android中轻松使用线程

     当你第一次启动一个Android程序的时候,一个被 称为"main"的线程就被自动创建了.它被称为主线程或者UI线程,它是非常重要的因为负责分发事件给对应的widget,还包含画 ...

  10. 假如数组接收到一个null,那么应该怎么循环输出。百度结果,都需要提前判断。否则出现空指针异常。。我还是想在数组中实现保存和输出null。

    假如数组接收到一个null,那么应该怎么循环输出.因为foreach与obj.length都会报错.null不是对象,foreach中不能赋值? sp页面forEach一个存放对象的集合,怎么判断其中 ...