Internet Project Architecture

Internet Project Architecture

 

 

what is architectural design

 

      In layman's terms, architecture design is like the process of answering application questions in primary school exams, but the problems to be solved are more complex, the process of conception and design is more extensive, and the workload of solving problems is greater.

 

 

 

 

Project quality indicators

 

      The ultimate goal of software development is to use code to implement abstract business logic, and then evaluate the project according to the following indicators:

 

  • Function : The functional goal is the basic requirement of the application. If the established functional logic cannot be realized, the application will lose its meaning of existence. Therefore, the realization of product requirements is the basic goal of the application.
  • Availability : This is also a basic standard for software requirements. If the server is down, the database is down, and whether the system can continue to be used is a single point problem. The simple way is to do clustering. Although it will increase the maintenance, this is a single point to solve. the most effective method.
  • Performance : On top of the basic functions, there will be some performance requirements, but few product managers or users can put forward such requirements in advance, so architects must have rich experience to discover and solve (or do for future performance improvement). Prepare for) performance issues. The main measures of performance are: the corresponding time of a single request, the number of concurrent requests for a single instance, and the maximum concurrency of services.
  • Scalability : The current development mode of Internet applications: rapid response, iterative development; put forward requirements, respond quickly, and go online as soon as possible. Therefore, this requires the system architecture design to better respond to new requirements and changes in requirements.

 

 

 

 

The main process of architectural design

 

  • Identify the problem domain
  • data modeling
  • Module division
  • Technical selection
  • Description of key processes
  • Code
  • Acceptance Test

 

 

 

Identify the problem domain

 

       I remember getting the papers corrected by the teacher after the primary school exam, and getting annoyed at the big red crosses one by one: "Hey, I read the wrong question again." The wrong direction is more harmful than the wrong method. If you don't find the right direction, the project will go in the opposite direction and deviate far from the goal. The demand description from product managers or users is our problem domain, but the demand description from product managers will be more comprehensive and contain a lot of content, while those from users are relatively simple and relatively vague. For example, the requirements document of an e-commerce project will be very large. When you get a requirement document of dozens or hundreds of pages (some programmers say that my product only has a paragraph, "copy the function of the XXX website", haha) , often do not know where to start, so we have to find the key problems from the complex problem domain.

 

例子1:

 

    1. 用户可以在我们的app给其他人转钱

     

    从 1 出发,又延伸出几个问题

 

    2. 用户访问:用户注册、登陆

 

    3. 用户信息:用户可以查看自己信息,还有绑定基本信息

 

    4. 用户交易:给别人转钱,钱是怎么转过去的,一般通过第三方机构的API实现

 

    从 3 出发,又往下延伸

 

    3.1. 补全用户信息:在注册时,尽量简单,等用户需要交易或其他操作时,让用户不全信息,如:email 、mobileNo 、 银行卡。

 

    3.2. email 和 mobileNo 绑定:这里的绑定,需要发送验证,然后激活。

 

    3.3. 银行卡绑定:需要依赖第三方平台的API

 

    从 4 出发,又往下延伸

 

    4.1. 收钱的人是不是app用户

 

    4.2. 收钱的人是不是我的朋友,如果是直接交易,如果不是那是否允许交易,如果允许交易,交易后是否成为朋友

 

    4.3. 交易完成后,应该显示用户的交易记录,成功的怎样显示,失败的怎样显示

 

 

例子2:

 

    1. 我是app用户,想添加某人成为朋友

 

    从 1 出发,延伸出下面问题

 

    2. 我想加的人,是不是app用户

 

    3. 加朋友前和加朋友后,看到的这个用户信息有无变化

 

    4. 加朋友的申请流程

 

    从 2 出发,往下延伸

 

    2.1. 根据别人的email 、mobileNo,在app中查看是否存在,如果存在,就可以申请加好友;如果不存在,就邀请他成为用户

 

    2.2. 从我的通讯录中,现有的email、mobileNo,查看这些是否存在已经是app用户的,如果有,可以申请加好友

 

    从 3 出发,往下延伸

 

    3.1. 加好友前,可以看到别人的姓名、电话等基础信息

 

    3.2. 加好友后,除了可以看到基础信息外,还可以看到别人的一些公开的交易记录

 

    3.3. 用户可以设置自己的交易记录是否公开,公开的话,可以让他的共同朋友看到,如果不公开的话就看不到

 

    从 4 出发,往下延伸

 

    4.1. 能不能重复申请添加好友

 

    4.2. 添加好友申请,是否有有效期

 

    4.3. 申请添加好友后,是不是要推送消息,还有app的图标上是否加上一个1标记

 

    

       不断的展开问题域,就可以把整个流程转起来。当然实际应用的时候我们不会把所有的问题域都总结出来,确定了关键问题就可以开始数据建模了。

 

 

 

性能问题

 

        性能的问题域应该是针对关键路径确定的,比如用户交易,绑定银行卡,查看交易记录等。针对于这些关键路径问题,可以定义一些问题域,比如单实例支持1秒内完成1000条交易记录的查询,100单/秒的交易提交等。

 

 

扩展性问题

 

       扩展性是最难把握的,因为每个人经历不同,针对同样的项目会对未来需求有不同的预期,因此怎么把握当前的功能和未来的变化,如何平衡性能和扩展的关系,是架构师设计的关键。以我的的经验来看,扩展把我关键问题,优先满足关键问题的性能,确定最小功能集。确定最小功能集的优势可以快速实现,快速验证需求的准确性,每次需求开发都完成最小和最关键的需求。设计的时候要满足一些思想和原则,OOP(面向对象设计)原则:1、单一职责原则;2、开放闭合原则;3、里氏替换原则;4、依赖倒置原则;5、接口隔离原则;数据库设计三范式等等。扩展的问题域也可以参考友商或者与有经验的产品运营沟通,大致了解存在的扩展性。电商项目可能会有:投资,基金,买黄金等业务都是电商的一些扩展需求。

 

 

 

 

 

数据建模

 

       确定了问题域就可以开始答题了,确定数据模型。大部分的应用基本使用的仍然是关系型数据库,所以我们针对问题域先创建数据表,当然也存在一些项目使用NoSQL存储或者不持久化数据,这里确定的就是问题域的实体类。上面问题域中的每一个名称,都可以建一个表。如:用户、交易记录、申请加好友记录。

 

       我比较喜欢使用powerdesigner做数据库模型,可以直观的看到表结构,方便修改,可以生成大部分DB的DDL SQL。为上面找出的名词(实体结构)创建表结构,然后根据产品需求文档一条一条的阅读判断,当前表结构是否可以满足需求,如果不能满足,在表中添加列或者添加新的表来满足此需求,不断的去丰富表结构直到完全满足需求。当然在建模的过程中也会调整原来的表结构,毕竟不断的增加需求,会引起数据模型的变化,所以最初建立的肯定不完整,不断调整直到满足所有需求。

 

 

数据建模的建议

 

    1. 数据表包含自增id,创建时间createTime,更新时间updateTime和版本号version

 

  • 自增的id:主键,根据id查询或者更新时,速度毕竟快。
  • createTime和updateTime:记录创建时间和最后的更新时间,排查问题的关键点
  • version:编辑时version++,是一个很方便的乐观锁,能比较大的提升数据库的性能

 

    2. 不使用外键,这点有一些和数据库设计的规范相悖,但是这是来自真实经验总结,外键约束带来的数据完整性的优势远远小于更新逻辑实现的难度。从性能和扩展性来看不使用外键也是利大于弊,大数据高并发大流量的互联网应用提供性能的常用方法是:提高数据库的访问速度,缓存数据,数据库分库分表支撑高并发等,外键是对这些方法的一个制约。

 

 

    3. 不使用id作为表关联,虽然我们不创建外键约束,但是不代表表之间没有关联关系。所以表之间仍然会有外键,但是没有外键约束,设计这个外键的时候要考虑数据的增长型,数据没有确定的规模,那么参考增长的速度,我们可以设定一个未来3-5年的数据规模,如果单表不能满足,则数据存在分表的可能性,那么表间的关联使用全局的唯一id的方式一个更好的选择。全局唯一id的方式有很多算法,使用数据库(oracle的sequence和mysql的自增id,这里是为生成id的特殊表的自增)生成是一个比较好的方式,当然也可以使用组合方式添加数据类型,时间,地域等方式,也有使用uuid算法计算的方式,只要可以满足不重复的特点,选取那种方式可以参考一下产品的意见,因为这个字段用户可能感知。

 

 

    4. 表有没有多少列的标准?记得刚开始做设计的时候,经常怀疑自己是不是分的表太多或者太少,太大了是不是会影响性能,太少了是不是有点画蛇添足。应用最初的设计最符合设计原则和设计思想的,没有收到工期,团队分割,实现难度等非设计因素的影响,所以我们应该尽量的坚持最初的设计,克服其他因素的影响。

 

 

    5. 冗余字段是否有必要?我的做法是不使用,保持原有的设计,如果系统真的流量比较大,查询性能太低,可以通过把读服务从业务系统中分离(这里要注意不是数据库的读写分离)。从业务上把读写分开,做一些便于查询和提高性能的设计,通过一些数据抽取方式同步数据。这里会有人提出异议,这样做会导致用户的读延迟,其实展示性数据对数据的延迟是有很大的容忍度的,只有业务系统需要做到数据的一致,那么业务系统对数据的读取是针对性的,很少会出现需要很多关联数据的情况,所以最初设计系统时尽量少的使用冗余字段去提供查询的方便性和性能。

 

 

 

 

模块划分

 

       如果数据模型主要为满足功能目标的话,模块划分会比较多的兼顾性能和扩展性,常用的互联网应用的模块划分和部署结构有如下几种(这里讨论的划分和部署是互联网应用的服务器端),不考虑浏览器和APP等客户端,当然介绍的几种也是常用的结构。

 

 

单实例结构


       
 

  • 优势:结构简单,便于开发部署
  • 劣势:可能存在性能瓶颈,扩展性差,系统耦合性高

 

 

集群结构


       
 

    备注:db层作为整体描述,可能存在单DB,读写分离,分库分表或者数据cluster等技术

 

  • 优势:性能大大提升(理论上可以无上限)
  • 劣势:负载存在平衡的可能,仍然会存在性能瓶颈,扩展性差

 

 

分布式结构

 

       
 

       分布式系统是把不同的业务切分到不同的实例中,功能相关的聚合到同一个实例中,系统间使用网络协议通信的一种结构。

 

  • 优势:扩展性强,高内聚,低耦合
  • 劣势:结构复杂, 事务控制难度大,开发工作量大

 

 

混合结构

 

       
 

    混合结构是分布结构基础之上每个模块又实现集群结构,所以这个模式放大了分布式结构的优势和劣势。

 

  • 优势: 扩展性强,高内聚,低耦合,健壮性高
  • 劣势: 结构复杂, 事务控制难度大,开发工作量大

 

 

总结

 

       大部分的互联网应用的结构都可以用上面的4个结构描述,当然这里只是简单的描述,一些应用为了提高数据库访问会加上DB缓存,为了提高页面的访问速度做页面静态化和CDN,为了应对大数据的存储和检索使用NoSQL数据库等,但是我们设计的结构是不受影响的。

 

 

 

如何选择系统结构

 

      1. 系统是否能满足未来2-3年的增长,如果采用混合结构的系统工作量要远远大于单例结构的系统,对初创企业来说,上线才是最大的需求,所以拼速度的时候就要放弃优雅。如果公司有一定的规模,开发的应用是核心业务或者未来的核心业务,采用扩展性强的混合结构应对未来的快速发展的业务需求是一个更好的选择。

 

      2. 人力因素,混合结构要比单实例的结构工作量增加很多,并且对团队整体的技术水平有较高的要求,所以要”量力而行”。

 

      3. 时间因素,很多互联网公司的工期不是技术评估的,是由”市场”确定的,所以火烧眉毛的时候就别讲究性能和扩展了,上线再说。

 

      4. 架构不是一成不变的,不断增加的访问和不断变化的需求改变着系统的架构。快速响应,不断迭代才是互联网应用的方式。所以最初的架构,尽量的做到高内聚低耦合,这样不断的提高系统的短板,逐渐完善系统结构。

 

 

 

分布式结构电商模块描述


       
 
 

显示层

 

    前台:用户端界面显示层,依赖用户服务,商品服务,交易服务和支付服务。

 

    后台:运营端界面显示层,运营人员管理各种数据的界面。 依赖用户服务,商品服务,交易服务和支付服务。

 

服务层

 

    用户服务:注册,登录,用户管理等

 

    商品服务:商品浏览,库存展示,商品管理,库存管理等

 

    交易服务:购物车服务,订单计算, 订单提交,订单列表等

 

    支付服务:生成支付链接,支付成功跳转,支付成功逻辑处理等

 

基础组件

 

    DB:数据存储

 

    Redis:使用redis实现用户状态session机制,便于将来集群部署;实现购物车功能,用户购物车服务端持久化,便于用户跨浏览器购物车管理。

 

    第三方支付组件:用于与第三方支付服务交互

 

 

 

 

 

技术选型

 

    1. 如果非必要请使用常用的技术,框架等,常用技术和框架使用者多,所以会比较少的遇到非业务问题。曾经参与的一个项目,其中一个模块由一个比较熟悉python的同学负责,系统刚刚上线,因为一些原因要离职,没有人可以接下来,只好找其他的语言重新开发了一遍。

 

 

    2. 熟悉的优于强大的,尽量采取团队比较熟悉的技术或者使用团队中有人可以指导的技术。记得5年前为甲方公司做一个需求和Bug跟踪的工作流的系统,轻率的决定使用JBPM,因为团队中没有人研究过,所以花了大量的时间使用这个框架,最后也没有很好的使用,导致项目步履蹒跚。

 

 

 

 

 

关键流程描述

 

       关键流程描述是检查系统架构是否满足需求和指导开发的必要条件。关键流程描述是使用流程图解决关键问题的过程,它的使用者是团队其他成员和自己,所以格式不重要,其他人能明白就好。

 

 

要注意的地方:

 

      1. 有始有终,流程应该是从用户进入应用开始到离开应用的完整过程,比如交易的过程,应该从用户用户登陆到找到朋友到用户支付成功这一个过程。

 

      2. 流程图突出重点,比如上面举例的交易过程,应该突出交易相关的流程判断,不必描述用户注册,找回密码等过程。

 

      3. 简要说明,避免过于详细,比如交易的过程中需要更新库存,但是不需要描述更新库存前的库存校验这些是提交订单的内部实现。

 

流程图可以做成如下:



 

 

 

 

 

 

代码实现

 

      代码首先是给人读的,其次才是给机器读,所以良好的代码结构是项目存活更长时间的良药。

 

代码分层

 

       功能单一原则,mvc是互联网应用的一种基础模式,从功能层次上划分为,v显示层,c控制层,m业务层。以Java实现业务分层如下:


    

 

    controller:页面控制层,用于页面出参入参转换和页面跳转

 

    vo:贫血实体对象,用于页面和业务层的数据传输

 

    bo:业务实现层

 

    dao:数据访问层,用于处理与数据库的交互

 

    service:业务逻辑层,主要负责业务逻辑和一些运算

 

 

命名规范

 

       代码中使用的类,方法,变量,参数等,采用统一风格命名,英文或者中文拼音,驼峰或者下划线分隔,尽量采用业界常用风格。类,变量和参数采用使用名词,方法使用动词等。

 

 

注释风格

 

       采用统一的注释风格,方法内一般采用行注释,其他地方采用段注释。

 

 

 

 

验收测试

 

       积极配合测试团队对项目的测试,他们是为项目健康上线保驾护航的人,不是挑刺的人。

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326237422&siteId=291194637