我的架构经验系列文章 - 后端架构 - 框架层面

框架层面:

SOA

在这一篇中会逐个介绍一下自己对这些XXX的理解,其实每一个理念都不是莫名其妙产生的而是有产生背景的,这些时髦的名词不是用来炫耀的,而是真正要理解它们是干什么的,并且框架千万不能乱用理念也千万不能乱用,并不是把所有的这些都用上你的系统才是一个牛逼的系统,一定要适合才是最好的,并且要保持简单可靠的原则。所谓SOA,字面上来说是面向服务的架构。有的人不说SOA其实他已经SOA了,有的人大谈SOA但其实只是在用Web服务,SOA可大可小。你可以认为服务调用就是SOA了,也可以认为服务调用只是SOA中的很小一部分。个人觉得SOA的理念是说,把业务逻辑从类库的封装提升到服务的封装,并且通过不同的信道不同的编码格式来提供服务,使异构系统之间也能重用服务,说白了就是让代码从本机重用提升到了跨机器的重用。从最简单的来说,把组件封装成自制的服务,通过交换消息来使用服务提供的功能,那么就是SOA了,但这也仅仅是SOA的开始,比如你是否想过下面的问题怎么解决?

你的服务是否可以被外部的异构系统使用?精心开发5年的UI前端框架!

如果你的服务又需要调用另外的服务,怎么处理复杂的调用关系,怎么监控整个调用过程?

服务调用怎么纳入事务的控制中?

服务越来越多,接口越来越多,怎么知道应该调用哪个服务哪个接口?

接口的版本升级了怎么办?

服务有太多人调用,怎么进行负载均衡,怎么限制调用人数?

怎么做安全,限制服务的匿名调用?

服务怎么进行测试?

服务调用失败后怎么办?

服务怎么进行升级和重新部署?

因此,SOA其实不仅仅是调用服务,在监控和治理上有很多事情要做,SOA可大可小。不管怎么说,从理念上来说,SOA确实是一种进步,复杂逻辑都封装成服务,一个复杂的系统可能调用不同的服务就可以完成了,每一个服务都是自治的,很好的降低了系统整体的复杂度。其实一个复杂的系统如果复杂度在10000的话,那么分成四层实现10*10*10*10就可以大大降低复杂度,每一层只要做好10复杂度就好了,由上层来调用下层。OSI如果不是七层模型,而是一层模型的话很难想象怎么去处理整个复杂的过程。

精心开发5年的UI前端框架!

RPC

字面上来说就是远程过程调用,RPC(这里我们说广义上的RPC)也可以是SOA实现的一种方式,SOA并不一定都通过Web服务实现。从实现原理上来说RPC其实并不是很复杂,无非就是客户端有一个代理,收集客户端要调用的远程方法以及参数,然后序列化成消息提交到远程,到了远程之后把消息反序列化,动态执行客户端所需要的方法(当然也包括创建对应的对象),然后把结果通过另外一个消息返回给客户端,当然其中的细节太多了。从客户端和服务端交换数据依赖的信道来说一般使用TCP或HTTP,也可能会是UDP。

ORM

对象关系映射解决面向对象系统和数据库阻抗不匹配的问题,大家都知道的ORM的定义。这里我想说的是ORM的出发点是好的,而且在某些应用中ORM确实可以改善代码可读性,增加编码效率,个人认为ORM是有使用情况的,不是所有的数据访问都适合使用ORM框架的,Java的SSH也有那么一点误导,Struts不是实现MVC的唯一方法,Spring不是实现IOC的唯一方法,Hibernate也不是实现数据访问的唯一方法,我觉得ORM:

它适合领域复杂的,表多的,表之间关系多的,访问量相对较小的,企业应用。

它不适合业务相对简单,表之间关系不多,访问量超大的互联网应用。

对于ORM来说要入门是简单的,但是要用好不是这么容易的:

如果没有正确使用很可能导致产生大量的SQL语句,而使用者还不知道。

如果没有正确使用很可能会拉取过多不必要的数据,而使用者还不知道。

如果没有正确使用很可能会产生性能不高的SQL语句,而使用者还不知道。

因此,即便是使用ORM也要对ORM产生的SQL语句张一个心眼,并且我们需要了解ORM中是如何做延迟加载、级联加载、主键缓存的,只有了解了这些机制才能真正用好ORM,如果对ORM不熟悉,如果在做互联网系统我觉得还是太平点吧,SQL语句精准高效。当然有的人要说了用SQL的话业务逻辑就可能不在代码中了,其实这个还是看SQL语句怎么写的,如果把SQL只是当做数据库和程序的沟通桥梁的话这不是问题,如果在SQL里面做一些判断做一些计算那就是自己的事情了。精心开发5年的UI前端框架!

IOC

控制反转依赖注入不是嘴上说说的,它是一个非常实用的理念。有的人即使在使用了IOC之后还没有意识到为什么要使用IOC,我总喜欢在面试的时候问为什么要用容器来创建对象,自己手动new出来有什么不好?有的人回答是手动new出来的性能不高,容器创建的是唯一的对象,那我就会问自己写一个单例的对象也是一样的,为什么要容器创建?其实这样的理解是有误的。个人认为管理对象的生命周期只是IOC容器的一个作用,IOC容器的意义在于:

管理了对象之间的关系。在OO中组合很有用,如果对象之间有复杂关系的话,那么我们就必须在new对象的时候来构建这种关系,这些关系其实都写死在代码中了。并且我们通过代码会直接把实际的类型写死,降低了针对接口编程的意义。如果能在配置文件中根据自己的需求来配置这种关系,由容器动态创建对象和对象之间关系的话,那么我们就把代码中依赖提取到了外部,由外部注入进去。在一个分层的应用程序中,我们不仅仅注入平行层级的对象,还可以注入下级对象,实现从上到下的自动注入,整个系统就非常灵活。

管理了对象的生命周期。有的时候出了单例或是new出来的对象,还会有根据线程、根据请求来的特殊声明周期的对象,如果手写代码来管理声明周期一来很麻烦,二来也不方便调整,通过容器来管理对象的声明周期简单高效,并且我们很容易对容器进行扩展提供不同的声明周期的字典即可扩展生命周期的类型。

AOP

面向切面编程对于职责分离和提高可测试性都很重要。一般来说代码有两种方式织入,静态的和动态的。所谓静态的就是在编译之前直接改了要包装的类,然后把关注点的入口方法封装进去一起编译的编译时增强。所谓动态的就是在运行的时候动态修改代码动态编译的运行时增强。一旦有了AOP,那么我们的事务、日志、权限、缓存之类和业务无关的代码就可以不出现和混在业务代码中了,根据需要进行配置就可以对任意的代码进行这些横切关注点的增强。一旦这些代码有修改,我们也只需要修改配置,而不是在代码中的几千个几万个地方去查找修改。精心开发5年的UI前端框架!

MVC

MVC对于网站特别是互联网网站来说是一种非常好的里面,MVC的优点体现在:

职责分离,不再是所有的代码都混在一起了,V和C的分离尤其重要。

职责分离早就了可以进行单元测试,可测试性也是重要的一环,对C可以进行单元测试是非常重要的。

大多数MVC框架都提供了AOP的织入点,在实现职责分离的时候还能实现横切关注点的自动执行和可替换性。

在实现MVC的时候我们不仅仅是能把MVC框架用上去就好了,要尽可能实现:

C中的诸如缓存、权限、日志之类的横切关注点务必提取出来通过AOP实现,不要和C的其它业务性逻辑混在一起。

C中的Action可以重用的尽量重用,Action的结果可以重用的也尽量重用。

可以考虑MVC和IOC相结合,把C用到一些服务或DAO动态注入进来。

对于V尽量确保V中不要有后端代码,V可以让前端开发直接编辑,由后端开发嵌入比较简单的Tag。如果VM明确的话,前端甚至可以直接写V。

TDD

测试驱动开发又是一个不小的概念。各种平台也有各种框架来实现Mock来实现单元测试。工具再好没有正确的编码理念也是没用的,要实现所有的代码都能通过单元测试来验证必要的几个因素包括:

程序没有很复杂的上下文环境,或者说上下文环境是可以被模拟的,否则怎么测试?

程序模块的职责是单一的清晰的,如果一个模块做了几十件事情,有几百个分支的话是很难测试,测试的粒度越是细越是容易测试。

针对现在大多数项目无法进行TDD,甚至无法进行单元测试的原因是因为往往时间很赶,只能有时间实现最基本的业务逻辑,而单元测试其实编码的时间不会比实际的编码少的,甚至更多。个人认为可以根据项目的性质不同来看,如果这个项目本来就是CRUD的,或者是一个临时的项目,单元测试TDD的意义不大。但如果这个项目是一个要被很多人使用的类库或者框架性质的项目,没有单元测试是无法想象的:

如果一个类库提供了100个功能,你不可能在修改了一个点之后就去手动测试一下这100个功能,必须通过自动化的手段进行。

类库需要确保在所有的边界情况都考虑到,手动测试或者黑盒测试是很难覆盖所有情况的。

如果你的类库没有提供单元测试,类库的使用者怎么在他们的执行环境来验证类库的可用性呢?因此还不仅仅是给自己用,别人还要使用你的单元测试来确保类库在自己的运行环境下可以正常工作。精心开发5年的UI前端框架!

其它

在这里先想总结一下,个人觉得这么多XXX中最需要有的就是MVC和IOC了,至于AOP有了当然更好,至于ORM和SOA则是看需求了,对于TDD么如果你在写一个类库或框架那是必须的,否则很难想象这套代码的稳定性会有多高。除了上面提到那那些XXX其实还有很多作为基础框架需要实现的东西,以前画过一个脑图参考:http://www.iteye.com/topic/1134828。作为框架我觉得有一些要素是需要满足的:

尽量保持框架对外的接口是很简单的,复杂的东西应该在框架内部处理掉,对框架的使用者透明。

框架的异常处理要完善,日志记录要完善,框架由于是对开发者透明的,因此最好在异常信息和日志信息中写明要调用者和框架的使用者怎么样去做才能解决这个问题而不是仅仅是说出了什么错。

一个完善的框架应该内建性能检测机制,或者提供http的接口可以让外部了解到框架内部的运行状况。

框架要做好测试,确保在不同的线程环境和不同的配置情况下框架都能正常运行。

框架最好有性能测试,让使用者明确这个框架能提供的性能,以便正确判断是否可以满足自己的需求。

时间: 2024-08-22 06:09:39

我的架构经验系列文章 - 后端架构 - 框架层面的相关文章

我的架构经验系列文章 - 后端架构 - 架构层面

架构层面: 日志集中 所谓日志集中就是把程序的所有日志和异常信息的记录都汇总到一起,在只有一台服务器的时候我们记录本地文件问题也不是最大,但是在负载均衡环境下再记录本地日志的话就出现问题了.在想查看网站日志的时候到哪台机器去查都不知道,难道有100台机器就100台机器逐一远程连上去看?因此,把这些数据汇总在一起保存对于大型网站系统来说是很必要的,这样我们就可以直接进行查看.搜索,也很明确可以知道是哪台机器的业务出了问题.至于这种日志数据是写到RDBMS还是NOSQL甚至是搜索引擎这就看需要了,总

我的架构经验系列文章 - 后端架构 - 设计层面

设计层面: 分层架构 分层架构是项目设计中很重要的一点,从根本的目的上来说就是为了职责的分离.最经典的三层架构,到四层五层六层,甚至有人开玩笑说十八层的分层,根据项目的需要可以分不同的层.这里说的层其实是逻辑层,从物理层的角度来说也有三层.四层五层的分层架构.之所以三层架构这么流行是因为它的分层把大的关注点进行了分离,层数恰到好处,表现层.业务逻辑层和数据访问层,分别处理面向用户呈现的.面向逻辑处理的和面向数据库存取数据的三大关注点.UI前端框架最新力作!有奖试读! 在分层架构中除了分层之外还需

我的架构经验系列文章 - 后端架构 - 系统层面

系统层面: 高可用性 所谓高可用性也就是通过避免单独故障加上快速故障转移实现一旦某台物理服务器出现故障能实现故障快速恢复.一般来说,可以采用两种方式,如果可以做业务可以做负载均衡则通过负载均衡实现集群,然后针对每一台服务器进行监控,一旦发生故障则从集群中移除:如果业务只能有单点入口那么可以通过实现Standby机加上虚拟IP机制,实现Active机在出现故障之后虚拟IP转移到Standby的快速故障转移.一般可以使用KeepAlived或HeartBeat实现高可用(当然,硬件手段实现也可以,这

我的架构经验系列文章 - 后端架构 - 性能层面

性能层面: 性能分析 我觉得性能分析的话要注意几个要点: 不要去猜:对于自己写的代码你是否知道你的代码要执行多久,是不是还在用时间相减来测试代码执行时间?现在有很多自动化的工具可以在程序运行的时候,测试代码中每一句语句的执行时间,可以有效分析出代码的性能瓶颈.对于比较重要的业务逻辑建议采用类似的工具来进行性能分析,有的时候性能慢的代码不一定是自己写的还可能是框架内提供的,如果没有一个丰富的编码经验是不太可能知道这些点的,但是通过这样的分析工具你就能知道这个地方会慢,虽然框架的代码我们不能改,但是

我的架构经验系列文章 - 后端架构 - 语言层面

语言层面: 运行时元数据获取 所谓运行时元数据获取也就是在程序 运行的时候通过代码动态 获得类型.方法.属性的信息,然后可以动态获得属性的值,执行方法等等,在有的语言中称为反射.反射不一定是高效的,但是在写框架程序的时候反射是一种很有用的技术 ,并且反射的性能开销往往是可以通过诸如缓存等手段来最小化的.比如在ORM中,根据实体类的信息动态获得所有的属性,然后取得其值,生成要到数据库 中执行的SQL语句.理解反射熟练掌握反射的使用以及性能优化是编写框架类代码很重要的一点. 错误处理 任何后端语言都

我的架构经验系列文章 - 后端架构 - 安全层面

安全层面: SQL注入 SQL注入是一个古老的安全问题,现在任何程序都不应该再出现这样的问题了,其原理非常简单,在过去大多数程序都是直肠子通数据库的,因此如果拼接SQL并且在参数上没有做好过滤或者没有使用参数形式来生成SQL语句的话可能会导致用户在页面上输入的恶意代码直接在数据库中执行.SQL注入的危害点在于整个网站有1000个数据点,如果其中有1个点有漏洞那么整站的数据其实都有危险了,很多开发会注重资金相关的模块但是忽略新闻相关的模块,如果都是使用一套数据库的话那么一个不重要模块的漏洞就会影响

我的架构经验系列文章 - 前端架构

框架层面:近几年前端发展很快,前端之所以叫前端因为前端是已经可以独立成为一种职业了,js也不再是十年前的玩具了,以前富客户端RIA的应用可能会用flash/flex或是silverlight,现在可以使用js来完成大部分的功能,因此js作为一门前端的支撑语言也不仅仅是进行的简单的编码,越来越多框架性的东西出现了.越来越多的开发模式转变为后端只是吐json的数据源,而前端做所有UI的事情. MVC MVC实现职责分离是很好的,大多数网站在后端都会引入MVC框架,对于一个前端负责所有呈现和前端业务逻

mysql 架构篇系列 2 复制架构一主一从搭建(异步复制)

一. 环境准备 1.1 主库环境(172.168.18.201) 环境 说明 查看脚本 操作系统版本 CentOS Linux release 7.4.1708 (Core) cat /etc/redhat-release 操作系统用户名和密码 root  js*2015 IP地址 172.168.18.201 ip addr 网关Gateway 172.168.18.1 cat /etc/sysconfig/network-scripts DNS 172.168.16.11 mysql 版本

Java底层技术系列文章-线程池框架

一.线程池结构图    二.示例 定义线程接口 public class MyThread extends Thread { @Override publicvoid run() { System.out.println(Thread.currentThread().getName() + "正在执行"); }}   1:newSingleThreadExecutor ExecutorService pool = Executors. newSingleThreadExecutor()