VICA 架构设计
本文记录最近完成的一个通用实时通信客户端的架构。
背景
我们公司是做税务相关的软件,有针对大客户 MIS 系统,也有针对中小客户的 SaaS 平台。这些系统虽然都是 B/S 的,但是也需要使用 ActiveX 控件来调用本地的硬件设备打印相关的发票。
由于 ActiveX 控件只能在 IE 下使用,而且在为客户部署时,经常会出现各种各样的问题。所以 SaaS 平台在推广时,不能不配备一个相应的实施团队,为每一家客户解决这些问题。
为了更好地控制本地硬件资源,对接税控设备。我们决定开发一个统一的独立的客户端软件。这样,客户在使用我们的 SaaS 服务或 MIS 系统时,只需要在开票机中下载一个轻量级的客户端,安装后,该客户端会与服务端保持实时的连接,并以托盘的形式静默地在开票机器的后台长期运行。这样,其他的使用者就可以继续使用浏览器中的网页,远程控制这些开票机进行开票了。
客户端产品在公司的名称为 VICA(VAT Intelligent Client Assistant - 增值税智能客户端助手)。以下将使用该名称。
架构目标
- 通用性
VICA 需要同时适配公司的所有 B/S 产品。接口方面要比较通用。
一切需要调用本地资源的功能,都可以通过 VICA 来完成。 - 平台化
由于公司的产品种类较多,需要调用本地资源的功能也比较多,有打印纸质发票、开具电子发票、抓取本地数据、调用局域网服务等……
所以要求 VICA 实现平台化、插件化。VICA 本身只专注于更加底层的功能,如插件框架、长连接、自动重连、自动升级、通用提示、命令框架。而业务功能则都实现为相应的插件。这样,在不同产品的应用场景中,开发者可以选配不同的功能插件即可完成基础功能的搭建。另外,开发者还可以基于统一的开发规范,编写出更多适合自己业务的功能插件。 - 三高
VICA 是需要作为 SaaS 平台的客户端的。而 SaaS 平台作为互联网应用,其用户数是非常多的。所以 VICA 也需要支持“三高”:高并发、高可用、高性能。 - 接口要求
VICA 是一个内部产品,不直接对外。它的直接使用者,其实是各产品线中的开发人员。所以我们需要一个可以适配各产品线的接口。
目前公司的产品基本都是 .NET 来进行研发的,而且 MIS 产品也不需要部署过多的服务或应用,所以 VICA 在服务端需要能提供 .NET SDK。 - 部署要求
VICA 的服务端程序有一定的部署要求:
在 SaaS 中需要可以独立部署、独立扩展;
在 MIS 中需要可以独立部署,也需要能够和 MIS 集成在一起部署。 - 简单
VICA 对于客户而言,一定要保持其简单性。理论上,使用者只需要下载安装运行后,就很快隐藏到托盘,没有过多功能。这样,一是越是简单的功能,越不容易出错,需要更新的频率也就大大降低了。二是对于客户来说功能越少越好,这样不但易用,而且客户更加不易感知客户端的存在,这样他们更加注重浏览器端的配套的功能。 - 静默
由于在一些场景下,VICA 是运行在长期无人值守的开票机上,所以 VICA 中的所有功能,都应该是尽量不需要与用户交互的。 - 自动升级
作为一个客户端,自动升级的功能是必不可少的。这是该软件能逐渐成长的基础。
对于自动升级,我们要求在服务端能控制所有客户端是否需要强制升级,并支持静默升级。
技术选型
- 客户端技术选型
客户端选型比较简单,当前我们的队伍中只有 .NET 和 JAVA 人员。而在客户端开发方面,.NET 要更加方便一些。另外,我们需要支持 XP 以上的系统,所以我们选择了 .NET 4.0 版本,该版本可以支持 XP SP3 以上的系统。另外,为了方便后期做出更加美观的界面,所以我们选择了 WPF 界面技术。
- 服务端技术选型
服务端实现实时通信的框架中,Node 以高性能著称,我及团队内部一些同事也都有 Node 的开发经验。但是最终我们还是决定使用 .NET 平台以及一些开源组件来开发一套自己的高性能实时通信框架。原因如下:
- 我们需要将 VICA 服务端与 MIS 系统集成部署。
- 需要易用的 NET SDK。
- 我们的客户端是基于 Socket 连接,而非 WebSocket。所以二者皆可。
- Node 的高性能 主要依赖于其单线程、异步非阻塞模式:“为了能适应高并发的情况(成千上万的连接),你的服务器需要采用异步非阻塞模式。你可能已经在IO操作中实现了这种方式。但问题是,如果你的服务器代码的任何部分可能产生阻塞,你都需要开启一个线程。在这种级别的并发下,你不能去为每个连接创建线程。所以整个代码路径都需要异步非阻塞式的, 不仅仅在输入输出层。”。所以,我们需要在 VICA 服务端代码中,所有会造成线程阻塞的代码,都需要使用异步接口(如 IO 操作、MQ 的访问、远程服务的调用等)。
物理视图
上图以 VICA 在电子票应用中集成部署的场景,示例了物理部署后的重要组件:
浅黄色的两个组件,就是 VICA 平台。
浅绿色的组件,是基于 VICA 平台编写的插件。上图中,该插件完成了电子票的开票功能。
橙色部分,是电子票应用的业务相关组件。
逻辑视图
上图是 VICA 中的逻辑视图,描述 VICA 平台所提供的功能,以及客户端、服务端集成 VICA 时的调用关系。
- Server:服务端;
- DBEN.EI:电子票相关的业务组件。
- DBEN.VICA.Server:VICA 在服务器端的一些基础组件。以 SDK 的形式提供给开发者。
- WPFClient:WPF 客户端;
- DBEN.VICA.ClientUI:客户端 UI 壳。
- DBEN.VICA.Client:客户端一些通用功能类库。
- DBEN.VICA.InvPlugin.UI:开票相关的界面插件,与 DBEN.VICA.InvPlugin 是配套的,不过这个插件只在客户端使用。
- DBEN.VICA.InvPlugin:开票相关的业务插件,其中包含了发票相关的一些命令及逻辑。这个包会被客户端、服务端同时使用。
- DBEN.VICA.Platform:VICA 平台所提供的功能。含:插件框架、通信框架、IOC容器、命令框架等基础组件,以及一些通用的内置命令,如登录命令。
通信框架 UML 图
通信框架是 VICA 中最核心的功能。
类图:
序列图:
命令框架 UML 图
命令框架在通信框架的基础上,使用命令模式,将客户端与服务端的通信、行为封装为易用的单个的命令,方便上层开发者对业务逻辑的封装、以及对通信框架的使用。
类图:
序列图:
小结
本篇是 VICA 架构设计的第一篇,只简单介绍了 VICA 的内部静态、动态结构,以及核心/基本功能的实现。
下一篇将会介绍 VICA 如何实现“三高”。
VICA 架构设计的更多相关文章
- VICA 架构设计(1)
本文记录最近完成的一个通用实时通信客户端的架构. 背景 我们公司是做税务相关的软件,有针对大客户 MIS 系统,也有针对中小客户的 SaaS 平台.这些系统虽然都是 B/S 的,但是也需要使用 A ...
- VICA概述及架构设计
VICA全称VAT Invoice Client Platform(增值税发票客户端平台),顾名思义就是公司增值税发票业务相关处理的客户端集成平台.在VICA出现之前,公司发票开具的技术主要是依赖于A ...
- 浅谈 jQuery 核心架构设计
jQuery对于大家而言并不陌生,因此关于它是什么以及它的作用,在这里我就不多言了,而本篇文章的目的是想通过对源码简单的分析来讨论 jQuery 的核心架构设计,以及jQuery 是如何利用javas ...
- 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)
一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...
- 解构C#游戏框架uFrame兼谈游戏架构设计
1.概览 uFrame是提供给Unity3D开发者使用的一个框架插件,它本身模仿了MVVM这种架构模式(事实上并不包含Model部分,且多出了Controller部分).因为用于Unity3D,所以它 ...
- 一种简单的CQRS架构设计及其实现
一.为什么要实践领域驱动? 近一年时间我一直在思考一个问题:"如何设计一个松耦合.高伸缩性.易于维护的架构?".之所以有这样的想法是因为我接触的不少项目都是以数据库脚本来实现业务逻 ...
- 基于token的多平台身份认证架构设计
基于token的多平台身份认证架构设计 1 概述 在存在账号体系的信息系统中,对身份的鉴定是非常重要的事情. 随着移动互联网时代到来,客户端的类型越来越多, 逐渐出现了 一个服务器,N个客户端的格 ...
- 架构设计:一种远程调用服务的设计构思(zookeeper的一种应用实践)
在深入学习zookeeper我想先给大家介绍一个和zookeeper相关的应用实例,我把这个实例命名为远程调用服务.通过对这种应用实例的描述,我们会对zookeeper应用场景会有深入的了解. 远程调 ...
- ABP架构设计交流群-上海线下交流会的内容分享(有高清录像视频的链接)
点这里进入ABP系列文章总目录 ABP架构设计交流群-7月18日上海线下交流会内容分享 因为最近工作特别忙,很久没有更新博客了,真对不起关注我博客和ABP系列文章的朋友! 原计划在7月11日举行的AB ...
随机推荐
- U盘文件被隐藏
转自https://blog.csdn.net/zichen_ziqi/article/details/80171891 文章原地址:http://www.uqidong.com/help/1625. ...
- Starter pom
以下图片是引用书籍内容: 比如你在用boot写一个web项目,在maven中你会导入: <!-- 导入spring boot的web支持 --> <dependency> &l ...
- Linux取代ifconfig指令的ip指令
- codeforces733C
Epidemic in Monstropolis CodeForces - 733C 有n条鱼排成一列,第i条鱼大小为ai,根据自然界的生存法则,相邻的两只鱼中,较大的鱼可以吃掉较小的鱼,如果两条鱼大 ...
- kubernetes 将pod运行在某些特定的节点上,给节点打标签
给节点打上标签: kubectl label node <node_name> GPU=true #打上标签 GPU=true 在创建pod的yaml文件时: 添加 nodeSel ...
- java querydsl使用
1 POM文件 <?xml version="1.0"?> <project xsi:schemaLocation="http://maven.apa ...
- mongoDB 其他数据类型
时间 类型 获取当前时间 new Date() 自动生成当前时间(国际标准时间) db.class.insertOne({book:"数学",date:new Date()}) D ...
- Hdoj 1847.Good Luck in CET-4 Everybody! 题解
Problem Description 大学英语四级考试就要来临了,你是不是在紧张的复习?也许紧张得连短学期的ACM都没工夫练习了,反正我知道的Kiki和Cici都是如此.当然,作为在考场浸润了十几载 ...
- zabbix数据库分表的实现
前提条件是主从同步操作完成(主从同步的前提是两个数据库表结构必须一样) 先看一下mysql配置文件 vi /usr/local/mysql/my.cnf 配置内容:------------------ ...
- C# LINQ语法详解
1.简单的linq语法 var ss = from r in db.Am_recProScheme select r; var ss1 = db.Am_recProScheme; string sss ...