| 
					
				 | 
			
			
				@ -1,153 +1,3 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				# IM服务器 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				此项目是家庭医生的消息服务器,含医生端与患者端。医生端使用REST API收发消息,患者端使用Web Socket收发消息。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				## 代码管理 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				项目代码使用git管理,请安装git客户端并fork代码再下载修改。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				## 环境安装 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 开发工具: Node.js的代码可以使用文本编辑器开发,如:Sublime, vi, vim等。也可以使用IDE开发,推荐使用WebStorm,包含大量便捷功能,加速开发。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 数据库准备: IM服务器使用MySQL数据库,因此需要先安装MySQL数据库。然后执行resources/schema/im_schema.sql与resources/schema/talk_group_schema.sql脚本文件,创建数据模式。第一个创建消息存储所需要的模式,第二个创建业务讨论组数据模式,并包含演示数据。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 运行环境:Node.js使用社区6.X版本或Joyent的0.10.x版本开发,部署环境也需要使用相应的版本。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- ECMA Script版本:代码需要ECMA Script 6版本的支持,提供对class, arrow function的支持。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				## 数据库结构 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				数据库设计是将消息按通道分开:系统消息,个人消息及群消息。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- msg_system: 系统消息,通过系统端发出去的消息存储在此表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- msg_p2p: 私信,通过私信端发出去的消息存储在此表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- msg_group: 群消息,通过群消息端发出去的消息存储在此表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- msg_statistic: 消息统计,当有系统,个人或群消息的时候,除了在上述三个记录数据外,还会在表中插入相关的消息统计,如:接收人有多少条未读消息,最后消息时间,内容或群ID等 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- msg_push: 消息推送,当消息需要推送到设备的时候,先将消息记录在此表中,再用个推服务推送到目标设备 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				## 运行 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				对Windows环境,可以预先安装Node.js。对Linux环境,代码包中包含Node.js程序,第一次部署需要使用chmod为此增加执行权限: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    chmod +x node 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				之后通过以下命令启动消息服务器: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    node app.armour.js 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				启动成功将出现如下日志: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    [INFO] app.js(125,5): Starting IM server, version 1.0.5.20161107, running on port 3000, 2016-11-22 16:00:17 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    [INFO] app.js(126,5): Configuration profile: dev 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				## 测试 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				测试框架使用mocha。REST客户端使用supertest。should模块提供断言测试。测试用例位于test目录,并根据模块划分。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				## 部署 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				部署服务之前需要配置环境变量IM_PROFILE,Windows平台直接在系统中配置,Linux平台在profile中配置: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    export IM_PROFILE=prod 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				IM_PROFILE值将决定应用加载的配置文件,配置文件位于src/resources/config。IM_PROFILE值为prod, test, dev中的一个。若配置错误服务将无法运行。若未配置此参数则默认使用dev配置。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				为保证服务正常运行,当服务异常退出时自动重启服务,IM服务器使用app.armour.js脚本,对进程添加保护:进程异常退出时,自动重启。为实现此目标,部署时通过appArmour启动服务即可实现进程的守护功能。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				### 部署到Docker上 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				未完工 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				### 集群 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				未完工 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				## 开发SDK 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				IM提供了开发SDK,一个JS脚本。客户端可以通过引用此脚本或将此脚本打包到资源中。此外,脚本使用jQuery作为基础环境,因此客户端需要预先引用jQuery脚本。客户端通过以下链接引用SDK文件 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    <script src='http://host:port/sdk/im.client.js'></script> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				## 工程结构 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 消息流: 首先要明白即时消息的流程,有助于理解整个过程。医生端的IM仅关注医生部分,即下图中蓝色标注的内容。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				### MVC 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				应用根据MVC模式设计。但REST API只用到Model与Controller两部分,与页面相关的会使用到View层。Model层代码位于model,View层代码位于views,Controller层分两处存放: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- REST API相关的放在endpoints 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 与页面相关的放在controllers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				### 消息发送 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
					实时与延时 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				## 错误处理 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				Node.js支持同步与异步调用,也导致了异常错误处理与众不同。一个给定的函数,它处理异常的方式要么是同步(用 throw方式)要么是异步的(用 callback 或者 EventEmitter),不会两者兼具。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				用户可以在回调函数里处理错误,也可以使用 try/catch捕获异常 ,但是不能一起用。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				实际上,使用throw并且期望调用者使用 try/catch 是很罕见的,因为 NodeJS里的同步函数通常不会产生运行失败(主要的例外是类似于JSON.parse的用户输入验证函数)。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				## API 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				本节将简要描述服务所提供的API,包括消息收发,运行状态及成员维护等。API分为两种:REST与WebSocket。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				### REST API 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				REST API遵循REST最佳实践,规范命名URL中的每个部分。注意POST请求是将数据作为请求体发送。下文中的host:port分别表示服务所在的主机地址及端口。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				1 发送系统消息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    POST http://host:port/api/v1/chats/sm 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				参数格式 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        to: "Rose", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        title: "System Message", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        summary: "You have new job", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        contentType: "1", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        content: "The patient has been followed in the scheduler, please make new follow plan as soon as possible." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				2 发送P2P消息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    GET http://192.168.131.115:3000/api/v1/chats/pm 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				参数格式 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        from: 发送人ID, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        to: 接收人ID, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        contentType: 内容类型,1为普通文本,2为图片,3为语音,4为超链接, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        content: "消息内容" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				3 发送群消息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    POST http://192.168.131.115:3000/api/v1/chats/gm 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				参数格式 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        from: 发送人ID, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        at: at对象ID, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        group: 组ID, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        groupType: 组类别 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        contentType: 内容类型,1为普通文本,2为图片,3为语音,4为超链接, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        content: "消息内容" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				4 获取消息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    GET http://192.168.131.115:3000/api/v1/chats/pm?user_id=xxx 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				参数: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- user_id: 用户ID 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				### Web Socket 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				Web Socket提供页面内长连接,并且能够通过Web Socket收发消息。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				此分支代码仅为杨叔禹代夫使用,所有修改均不可合并至主版本中!!! 
			 |