升讯威微信营销系统开发实践:(2)功能设计与架构设计

在上一篇中,我们详细分析了微信订阅号和服务号的区别,在本篇中,将进入正题:升讯威微信营销系统的功能设计及架构设计。

 

一、功能设计

1)设计目标

◇ 为微信服务号提供运营及管理所需的各种功能,包括微官网、微会员、活动中心、营销辅助、微信支付。

◇ 提供简洁友好的功能画面,使非专业技术人员也能够轻易的使用。

◇ 提供可独立于系统之外的插件功能或接口,可轻易对接其它系统或功能模块。

 

2)详细设计

如图,功能的设计从业务上划分,分为五大块:

◇  微官网

         微主页提供若干预置的模版,可以通过上传自定义的主题图片形成自己的微主页,对于有一定开发能力的使用者,提供模版引擎功能,使用一个类似于轻量级CMS的功能,定制自己的微主页。

         电影排片需要写一个蜘蛛程序进行抓取。

◇  微会员

         需要实现一套积分系统,包括在后台对积分规则的设定。积分商城与大多数商城系统类似。

         卡券功能需要支持后台派发和前端在线下通过二维码核销,这一块与微信原生卡券有一个重要区别,在于领取的方式,微信原生卡券主要是自主领取,比如扫码、分享等,但是对于部分线下商户,卡券的派发是要严格管控的,比如电影院的兑换券、景点的门票等,这种场景目前微信自带卡券不能实现。

◇  活动中心

         必须将所有的活动全部模版化,使用户能够简单配置就发起活动,并在活动进行的过程中提供运营数据报表。

◇  微信支付

         除了打通微信支付以外,需要提供线下的充值和消费能力,比如会员直接在线下向服务人员现金充值,或线下购物时刷二维码消费自己预存的现金,这里实际上意味着需要实现一套比较完整的消费系统。

◇  营销辅助

         能够提供各种运营数据,并提供邮件通知、短信通知的能力。

 

二、架构设计

1)设计目标

◇  稳定可靠,低耦合高内聚,可维护性强。

         稳定可靠主要取决于设计及编码水平,这个无需多解释。低耦合高内聚应该也是大家都了解的原则,为了实现这个目标,项目会按功能模块进行拆分和抽象,具体拆分方式请见下文的详细设计。

◇  易水平扩展,易运维。

         将高频请求的部分和低频请求的部分分解,将内网请求与外网请求分解,可分布式部署,将内网请求部分完全隔离在防火墙之后或内网环境中,并使对外的高频请求的部分可通过增加服务器来增加承载能力。在设计之初就需要考虑负载均衡及CDN分发所带来的问题,在负载均衡方面,我们以负载均衡不开启会话保持为设计指标,此外,我们需要将所有用户上传的文件,或发送的文件,在独立的文件服务器存储,以便于CDN分发和控制流量及带宽,要知道服务器的流量及带宽费用是相当可观的,同时也避免文件传输对服务器带宽的占用而影响业务数据的处理能力。

◇  所选技术应用成熟,生产性(开发维护的效率)高,编码实施难度较低,后续开发容易。

         在具体的技术选型上,选择成熟稳定的技术方案,而不是“牛”的方案,这一点非常重要,因为我们不是在做研究,我们是在做项目。或者从另一个角度来说,你对技术“牛”和“不牛”是怎样理解的。在此项目中我们考量以下几个因素:

         a.是否成熟稳定,后续支持怎样。成熟稳定通常代表着问题较少,团队学习成本低,接纳度高,后续支持指的是是否有商业公司或开源社区积极的维护更新。

         b.生产性怎样,是否可以提供足够高的生产性。生产性指的是开发维护的效率,软件开发过程中最大的成本是人力成本,如何用更少的人做到更多的事,甚至说在市场竞争中你的速度快不快,都相当重要,对于商业项目,我不需要你知道回香豆的“回”有几种写法,我只要你又快又好的给我写一百遍“回”字即可。

         能解决我的问题,成熟稳定,生产性高,可以称之为“牛”的技术。

◇  数据库必须支持分库存储

         基于承载能力扩展性和业务方面的考量,必须要能够将不同的公众号数据存储到不同的数据库服务器上。

 

2)详细设计

         架构设计我想分为两个部分说明,一是开发架构,二是部署架构。这两个不同角度的设计互相影响或者互相制约,必须在设计期间就把握好大方向,做好这件事情需要设计者除了懂开发,还要懂运维,否则很容易造成前人挖坑后人填坑。

 

         1.开发架构

         注意图上的一个矩形模块并不一定就代表着一个程序集,一个逻辑上的“模块”可能由多个程序集共同构成。

         从上向下简单分析,首先是管理端的UI层和手机端的UI层,我习惯将之称为Shell。从图上可以看到管理端Shell和手机端Shell是分开的两个模块,在我们的解决方案中它们是两个不同的工程,我也看到过一些微信项目将管理端和手机端放在一个工程中,无论是从安全性、可维护性上说我都强烈不建议你这么做。完全分开的好处有很多,首先是部署成本,管理端一般情况下是不需要应对大量请求的,而手机端有这个需求,在部署时管理端甚至只需一台服务器即可,而手机端则需要更多的服务器和带宽支撑,另外在工程的前期运维阶段,管理端的版本发布频率可能高于手机端,完全隔离的开发和部署可以避免在发布管理端时影响到手机端的业务,第二是安全性的问题,手机端从工程上就是完全不包含任何管理功能的,可以在一定程序上提高安全性。

         接下来是若干辅助服务,报表服务、文件服务,这两个服务是独立的Web工程。和管理端或手机端并不是一一对应的关系,一个报表服务器或文件服务器可以为多台管理端或手机端Shell提供服务。

         报表服务器直接提供报表查询和显示的画面,嵌入在管理端中。

         文件服务器提供文件上传下载功能,这个服务有几个技术细节需要注意,聪明的你或许已经想到第一个问题:跨域上传的问题。管理端和手机端都是独立部署的,所使用的域名自然是不同的,那么在浏览器中上传就存在跨域的问题,不过这个问题并不难解决,我将的后续篇章中介绍,另一个就是对于(嵌入在微信中的)手机端来说,是不能直接上传文件的,必须先把文件发送到微信后台,获取媒体ID,再下载下来,这个过程需要文件服务器完成,最后是关注服务号的会员,发文件到服务号上,实际是发到了微信服务器,我们的文件服务器要能异步的把这些文件从微信后台下载下来。

         定时任务是一个或若干个Windows服务,用于定时执行一些业务。

         业务核心模块这里的介绍比较笼统,在项目中实际对应着实现不同功能的诸多程序集,限于篇幅和本章节的主旨,还是留到后文中详细说明业务核心的设计和实现。

         中控服务器主要的功能是维护调用微信API所需的AccessToken,与微信对接时,根据公众号的AppId和AppSecert,你可以获取到一个有效期为2个小时的AccessToken,调用几乎所有的微信接口都需要这个         AccessToken,当然你不能在每次请求API时都获取一个新的AccessToken,这是完全没有必要的,所以需要一个独立的服务来处理这件事,其它模块需要使用AccessToken时,从中控服务器获取。

         微信SDK并不是微信官方提供的,是项目里需要自己实现的部分,微信官方并没有提供完善的开发包,只有若干示例。网上有一些开源的微信SDK,但是或多或少存在一些问题,此处使用的是我们自己实现的SDK包。

         基础架构部分涉及到数据实体的定义、数据协议的定义等等,数据协议指的是各Web工程之间以前单个Web工程中前后端通信所使用的协议。此外还包括许多共通的功能实现也在这里。

         服务模块封装了项目中所需的许多服务,如:日志、缓存、统一异常处理等等。

         最后是数据层,数据层没有使用Entity Framework,使用的是我的另一个开源项目S-ORM,下文的技术选型部分有简略的说明和介绍。

 

         2. 部署架构

 

        如图所示,我们的部署目标是需要支持易于水平扩展的分布式部署。管理端Shell、手机端Shell、报表服务器、文件服务器都必须能够通过增加服务器快速扩充承载能力。

        在上文中提到,我们在开发环节必须以负载均衡不开启会话保持为一项技术指标,这意味着从浏览器中发起的请求每次都可能落在不同的服务器上,我们就不能使用服务器Session存储会话数据,需要在开发阶段就实现一套基于独立缓存的Session机制。

        数据库服务器、缓存集群、中控服务器、定时任务服务器都部署在内网中,其它项目通过内网IP与它们进行通信,对于中控服务器和定时任务服务器,存在需要外网交互的部分,我们通过一个代理服务器来实现。

 

3)技术选型

        对于这样的项目无论是商业平台还是开源平台,都是可以的,都不会有太多障碍。

        本项目基于微软平台开发,并使用了一些基于Linux平台的开源应用作为辅助。

        这里要指出一个关于跨平台的问题,有些开发人员认为微软平台不能够跨平台是一个问题,关于这一点我认为“跨平台”本身是一个伪命题和伪需求,我从没见过正经项目在运维过程中迁移技术平台的案例,一定是在设计时就确认了部署平台。微软平台的优点是技术方案成熟,可靠性较高,开发效率高,缺点是运维时的软硬件成本较高。开源平台的优点相反,运维期间的软硬件成本要低几个数量级,但是前期的综合开发成本较高,可靠性更多的依赖于人的因素。 

后台:

1)ASP.NET MVC5 (Razor)

2)Web API

3)S-ORM

4)Microsoft Enterprise Library

5)其它组件,在相关章节介绍

        ASP.NET MVC 没有悬念,视图部分使用 Razor,生产性和可维护性都极高。如果发现项目中存在非常高频请求的页面,可以对特定页面实行完全静态化的HTML代码和前端异步请求的方案处理。这样的情况可能出现的场景在手机端,但是没有必要整个项目都使用这种方式处理。

        此外关于数据访问层,没有使用 Entity Framework,有几个方面的考虑:a.开发运维时更新数据库表结构等比较麻烦;b.性能问题,关于执行效率我们可以通过许多开发技巧进行提升,但是对于团队开发来说,这个隐性成本太高了;c.灵活性问题,在许多较复杂的应用场景中,数据库表结构和实体对象的映射关系不一定是简单的一对一隐射,可能存在分解、组合、包含等多种情况。所以在ORM层面,使用了我的另外一个开源项目:S-ORM,严格来说它不是一个ORM,而是一个轻量级的内存数据映射模块,详细的介绍请移步:http://www.cnblogs.com/sheng_chao/p/4553832.html。

        项目的日志处理,统一异常处理使用了微软企业库(Microsoft Enterprise Library)。 

前端:

1)jQuery

2)其它组件,在相关章节介绍

        对于前端实现,要尽可能多的兼容更多的浏览器,包括现代的古代的,力所能及的都尽可能兼容。此外前端分为两个部分,PC端和手机端,在具体实现上略有不同。

        在前端技术选型中,考虑过AngularJS、Knockoutjs、Backbone等框架,毫无疑问都是牛的框架,但是在这个项目中我都没有使用,最主要的原因是出于生产性的考虑,我认为使用这些框架的生产性不够高,或许在单页面应用(Single Page Application)场景中它们更能大展身手,但是对于这个项目来说,没有SPA这样的需求,相对来说比较传统,这种场景下网页前端的每个页面都是独立的区域、与其它的页面完全没有任何依赖、引用的关系,这一点对于后台开发或者应用程序开发有很大区别,在(大多数页面并不那么复杂的)单个页面中实现MVC是否有必要?能够得到什么回报?不要把“学技术”放到考量因素中,这不是做项目需要考虑的问题,开发人员也不应该带着这种目的做项目,这是自私的。

        可能有开发人员认为使用优秀的开发框架可以提高代码可读性和代码品质,关于这一点我认为代码的品质和可读性与所使用的框架完完全全没有任何关系,完全取决于程序员的编码水平和态度。

        前端技术不是我的强项,关于这一块内容请前端技术的牛人斧正。 

缓存:

1)  Redis

        在本项目的开发中缓存的应用经历了从 memcached 到 Redis 的转变,转变的具体原因将在后续介绍缓存实现的篇幅中详细介绍。 

数据库:

1)  MS SQL Server

        在数据库层面,大量使用了存储过程处理业务逻辑,并做到99.9%以上的参数化查询,一是可大幅提高数据库请求效率,二是防止注入攻击。为什么不是100%?在个别场景中,有一些特例,这些特例可以通过统一的函数进行安全方面的过滤,并且这些特例中的输入参数并不依赖于外部提供,后文将详细说明。

原文地址:http://www.cnblogs.com/sheng_chao/p/5801401.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/328663.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解读分库分表中间件Sharding-JDBC

转载自 解读分库分表中间件Sharding-JDBC编者按】数据库分库分表从互联网时代开启至今,一直是热门话题。在NoSQL横行的今天,关系型数据库凭借其稳定、查询灵活、兼容等特性,仍被大多数公司作为首选数据库。因此,合理采用分库分表…

java面试设计模式

https://blog.csdn.net/yinyuehepijiu/article/details/38663843

新闻发布项目——实体类(User)

package bdqn.newsMange.entity; /*** User的实体类* author Administrator**/ public class User {private int userId;//编号private String userName;//用户名private String userPassword;//密码private String uRole;//角色public int getUserId() {return userId;}public…

js webpack 配置路径_webpack中如何设置html引入js的路径

如题所示,如果webpack这样配置var htmlWebpackPlugin require(html-webpack-plugin);const CleanWebpackPlugin require(clean-webpack-plugin);let pathsToClean [dist,];module.exports {entry: ./src/app.js,output: {path: __dirname /dist,filename: main.[chunkhash…

HTTP 报文结构

https://www.jianshu.com/p/a2c4ede32d11

Java魔法堂:URI、URL(含URL Protocol Handler)和URN

转载自 Java魔法堂:URI、URL(含URL Protocol Handler)和URN一、前言                              过去一直搞不清什么是URI什么是URL,现在是时候好好弄清楚它们了!本文作为学习笔记…

升讯威微信营销系统开发教程:(1)订阅号和服务号深入分析

微信开发系列教程,将以一个实际的微信平台项目为案例,深入浅出的讲解微信开发、应用各环节的实现方案和技术细节。 原创内容,欢迎转载,转载请注明出处。 首先在第1章节中,我们先理清什么是订阅号,什么又是服…

不安装cudnn可不可以_Linux非root用户如何优雅的安装cuda和cudnn

Linux非root用户如何优雅的安装cuda和cudnn发布时间:2018-05-23 16:11,浏览次数:804, 标签:LinuxrootcudacudnnLinux非root用户如何优雅的安装cuda和cudnn跑深度学习模型时,总会遇到各种版本的问题。如深度学习框架与cuda的版本不…

如果你也会C#,那不妨了解下F#(4):了解函数及常用函数

函数式编程其实就是按照数学上的函数运算思想来实现计算机上的运算。虽然我们不需要深入了解数学函数的知识,但应该清楚函数式编程的基础是来自于数学。 例如数学函数f(x) x^2x,并没有指定返回值的类型,在数学函数中并不需要关心数值类型和返…

新闻发布项目——实体类(newsTb)

package bdqn.newsMange.entity;import java.util.Date;/*** 新闻的实体类* author Administrator**/ public class newsTb {private int newsID;// 编号private int categoryID;//类别编号(外键)private String summary;// 摘要private String title;//题目private String con…

Java URL协议扩展实现

转载自 Java URL协议扩展实现在信息交互系统设计中,不乏有自定义通讯协议设计。本章会介绍如何利用 java.net.URL 类来自定义协议。一般而言, URL 的格式是: protocol://[authority]hostname:port/resource?queryString 。 URL 类能够解析…

axure8 事件改变样式_AxureRP8实战手册-案例2(文本框:边框变色)

案例2. 文本框:边框变色案例来源:百度-登录界面案例效果:光标进入文本框时:(图1-6)案例描述:在登录界面中,包含用户名与密码的输入框。当焦点进入输入框时,输入框边框与内部图标变为蓝色;失去…

URL的getFile()和getPath()方法的区别

转载自 URL的getFile()和getPath()方法的区别 import java.net.MalformedURLException; import java.net.URL; public class dd { /** * param args */ public static void main(String[] args) { try { URL url new URL("file://ftp.yoyodyne.com/pub/files/fo…

webpack打包发布

npm run dev npm run dist --线上 git status git add . git commit -am "online adapter" git push git pull git branch --查看当前分支是在哪里master 还是 admin yarn install v1.3.2 yarn run dist -- 打包 fe-deply.sh --shell脚本 自动发布脚本 gi…

介绍开源的.net通信框架NetworkComms

Networkcomms 是一款C# 语言编写的TCP/UDP通信框架 作者是英国人 以前是收费的 目前作者已经开源 开源地址是:https://github.com/MarcFletcher/NetworkComms.Net networkcomms通讯框架使用简单方便,性能稳定. 从github上下载到源码后,需要Visual studio安装nuget 加载相关D…

dplayer js控制 自动全屏_vue-video-player 通过自定义按钮组件实现全屏切换效果【推荐】...

最近公司的产品上线,一些高级功能在基础版本中不对用户开发,通过视频的形式展示。产品开发用的是 vue, 经同事介绍使用了vue-video-player视频播放插件,通过 demo案例很快实现了视频播放效果class"vjs-custom-skin"ref"videoP…

新闻发布项目——实体类(comment)

package bdqn.newsMange.entity;import java.util.Date;/*** 新闻评论表*/ public class comment {private int commentID;//编号private String cmmUser;//用户名private String ip;//ipprivate String cmmContent;//内容private int newsID;//新闻IDprivate Date cmmDate;//…

java字符串格式化:String.format()方法的使用

转载自 java字符串格式化:String.format()方法的使用常规类型的格式化 String类的format()方法用于创建格式化的字符串以及连接多个字符串对象。熟悉C语言的读者应该记得C语言的sprintf()方法,两者有类似之处。format()方法有两种重载形式。 l for…

java web每天定时执行任务(四步轻松搞定)

https://www.cnblogs.com/LiSheng97625/p/4648739.html java web每天定时执行任务(四步轻松搞定) 第一步: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44…

从Unity3D编译器升级聊起Mono

接前篇Unity 5.3.5p8 C#编译器升级,本文侧重了解一些Mono的知识。 Unity3D的编译器升级 新升级的Mono C#编译器(对应Mono 4.4) Unity编辑器及播放器所使用的Mono运行时还未升级。 新编译器仍针对C# 4,是旧的编译器也支持的版本。 …