一:软件体系结构概述
1.当前流行的软件设计开发方法有哪些?
基本架构
分布式架构
数据处理架构
2.什么是软件体系结构?
软件体系结构为软件系统提供了一个结构、行为和属性的高级抽象,由构成系统的元素的描述、这些元素的相互作用、指导元素集成的模式以及这些模式的约束组成。软件体系结构不仅指定了元素的组织结构和拓扑结构,并且显示了系统需求和构成元素之间的对应关系,提供了一些决策的基本原理。
3.软件架构设计的重要性
- 是利益关注方的沟通工具
- 早期决策都是由架构设计决定的,从总体上决定了软件设计是对的还是错的,决定了软件最后的开发结果
- 好的结构还可以作为不断传递的财富,被重用。
二:基于软件构件的软件架构
1.什么是软件构件?
软件构件是一个组合单元,只有契约指定的接口和显式的上下文依赖关系。软件构件可以独立部署,并由第三方组成。
2.什么是基于软件构件的工程?
基于构件的软件工程,也称为基于构件的开发,是软件工程的一个分支,它强调对整个软件系统中可用的广泛功能的关注点的分离。它是一种基于重用的方法,用于定义、实现和将松散耦合的独立构件组合到系统中.这种做法的目的是为软件本身和赞助这类软件的组织带来同样广泛的短期和长期利益。
3.在Spring框架中,构件的组织与管理由谁负责,构件之间的依赖关系是如何让实现的?
是由Spring框架负责;提供服务的组件时被“注入”而不是直接“写入”到请求者的代码当中的。运行时,由框架把这些组件组织在一起,这种技术称之为依赖注入。同时,框架需要构件遵守一些特定的约定,一般需要通过写配置文件的形式来被告知如何注入代码。
三:分层架构与C/S,B/S架构
1.所有的进行数据管理的桌面应用在逻辑上一般采用什么软件架构?请描述该架构?
采用分层架构。
-
展示层:用户界面,和用户进行交互,绘制一个窗口,界面上有各种的输入控件,用户可以通过这些控件看到数据的状态并进行数据的操作。 -
业务逻辑处理层:接收用户在展示层的各种操作,进行额外的处理,如判断数据是否合法,判断用户是否有权限等各种各样的业务处理,如果有权限再将数据保存或者读取的请求交给数据访问层,即逻辑判断 -
数据访问层:把数据写入到数据库或者磁盘的代码,这些代码不是直接被用户调用。用户在展示层进行的操作是要依靠业务逻辑层这个桥梁来对用户的操作进行解释和处理,最终决定如何用数据访问层来进行数据的持久化。
图形表示:
2.进行数据管理的桌面应用在物理上一般采用什么结构进行部署?
客户机/服务器模式,具体三种方式
- 1)胖客户瘦服务器端:展示层和业务逻辑层放在客户端,数据处理层放在服务器端,业务逻辑代码的更新需要在所有客户端上都进行更新升级,管理开销较大。
- 2)瘦客户胖服务器端:展示层放在客户端,业务逻辑层和数据处理层放在服务器端,业务逻辑代码的更新容易,部署和管理方便。
- 3)三层结构:即客户端、应用服务器、数据库服务器。用户这一层通过各种各样的通信协议跟应用服务器进行通信,将它在展示层进行的操作告诉应用服务器,也就是执行对应的业务逻辑层的代码,业务逻辑层的代码再通过数据访问层的协议将对数据或者文件的操作交给的第三层进行数据的管理。形成了三层的分布式架构模式。其中,通过浏览器完成三层架构的实现方法,称之为B/S,用户的GU被运行在浏览器上,每次从server上下载GUI的代码,可以拿到最新的GUI的界面。使得部署和管理的开销更小。比thin client开销更小。因为用户界面代码更新也并不需要额外去处理。
3.spring是支持开发三层架构的技术框架,它是通过什么技术来实现server这个角色的?
servlet是用于实现C/S或B/S架构中server这个角色的。
servlet用于接受用户请求,然后在服务器上做计算,并将结果返回给用户。C/s架构中处理这些请求的基本方法是service()方法。应用服务器会把用户的请求作为参数交给servce()方法作为request去处理,service方法执行期间会对response对象进行修改,作为对用户的响应和对用户结果的传递.B/S架构中是用http servlet来支持B/S架构,用于专门针对HTTP协议进行处理和结果返回。整个运行过程就是通过doGet()方法处理用户从根目录上发过来的请求,servlet处理后,再返回请求中对应的结果页面,以此类推,实现用户不断的与服务器的交互。
四:RESTFUL架构
1.Restful架构能解决MVC开发中的什么问题?
- 为了解决展示页面和计算逻辑混杂,MVC中引入了模板引擎。
模板引擎可以使写模板的人和写计算逻辑的人实现一定的解耦.但UI中需要的变量名以及请求发送到后台哪个controller的方法等内容仍需和后端写业务逻辑代码的人员进行沟通.没有完全独立开来.且都同属在一个工程目录下。 - 用户的接口不标准。控制器中处理用户请求的方法与requestmapping对应,当用户发过来的请求URL之后就调用controller中相应的方法去解释,这些URL从用户角度看,就是系统与用户进行交互的接口,但是系统给用户提供的接口是不标准的,URL的命名是随意的,需要沟通URL的格式。
2.Restful架构中http请求的常见方式有哪些?
- GET(SELECT):从服务器获取资源(一项或多项)
- POST(CREATE/insert):在服务器新建一个资源
- PUT(UPDATE):更新资源(客户端提供改变后的完整资源)
- PATCH(UPDATE):部分更新资源(客户端提供需要改变的部分资源)-DELETE(DELETE):删除资源
- HEAD:获取资源头部(元数据)
- OPTIONS:获取资源信息,如某资源有哪些接口可以使用。
3.Restful架构中是如何实现应用状态的转移的,其目的是什么?
- 所有的资源通过hateoas框架把某一个对象转成Entitymodel或collectionmodel封装的restful资源的形式,即在资源中间添加links,客户端根据返回的links可以导航到其他的资源从而实现客户端上的应用状态的转移。这里hateoas是通过超媒体来提供客户端与服务器之间的交互。即客户端通过一个简单的初始URI,并从返回值获取可以操作的其他信息。这样对接后端时,几乎不需额外的信息。可进一步实现前后端的解耦。
- 其目的是实现客户端无需借助任何文档即能调用到所有的服务器资源
五:可扩展架构
1.大量用户并发访问时,服务器响应变慢,用户体验较差,如何解决?
- 垂直扩展:通过买更好的设备,提升系统性能。无法购买更好的设备,可通过虚拟化技术(如容器技术和虚拟机)削弱机器的性能,如削弱80%、50%等的方式来逐步的对比在不同性能下用户的体验度。用容器技术的话可以利用谷歌的开源工具Jib,将spring boot应用直接打包成可以在docker上运行的应用,封装成docker的镜像。垂直扩展优点:应用不需更改,可以直接换机器实现。垂直扩展缺点:机器本身性能有上限。
- 水平扩展:买更多的机器。用户访问的仍然是单一的server,实际由负载均衡器派送用户请求到不同server上,将所有负载分摊到不同server上。用户看来好像是被一个很闲的server处理着请求,实际是被负载均衡器控制着不使它的请求跟别的用户请求发生冲突,从而提升用户的体验。负载均衡器常见的是HAPROXY 。
2.为了提高用户的访问速度,水平扩展中服务器通过cache共享相同请求的计算结果,那么如何知道需要的请求结果在哪个cache上?
哈希或一致性哈希。
因为server按照一定的规则,将要存储的数据进行分区存放到不同的cache server上,不需要负载均衡器。而分区的方法主要是哈希或一致性哈希。所以查找的方法就是哈希或一致性哈希。哈希方法是根据缓存数据的某些键算一个哈希值,在和n(缓存服务器的数量〉求模得到存取的cacher server的标识号,这个数字范围在0-n-1这个范围上的整数,比如o,然后把这个键值对应的程序计算结果存储到0号cacher server上。当取数据的时候就用同样的键值去进行规则计算得到存储结果的cacher server。这种方法当分布式系统中横向伸缩或节点故障等,会形成节点的自动增加或删除,导致几乎所有的绑定失效大量失效会造成了某个时间点的网络抖动和性能急剧下降。一致性hash算法把取余的基数固定为一个常数232,把范围控制在[0,232-1]的区间。把这个区间按照顺时针的方向均匀分布在一个圆环上,称之为HASH环。hash环正上方的点代表o,按顺时针依次是1、2、3…[^32-1。把集群的节点根据IP或节点名进行HASH得到散列码并取余后分布在hash环上。
3.水平扩展时,当请求被不同的服务器服务时,单纯的在服务器的内部保存这个会话状态是不行的,因为如果请求被转发到了一个未保存这个会话状态的服务器时,会失去会话数据,如何让服务器之间能够共享会话数据,避免突然失去之前的状态呢?
利用session server技术
-
一种方法让多个web-server之间相互同步session,这样每个web-server之间都包含全部的session。缺点: session的同步需要数据传输,占内网带宽,有时延。一般会限制集群中的节点数量,不超过5个 -
第二种方法利用Session Stickiness,负载均衡器有一个基本的功能就是会话粘性。它可以记住一次会话中的转发,下次同一个用户来就转发到同一个server上,这样避免会话失效; -
第三种方法是后端统一集中存储:Spring Session with JDBC。通过数据库来存储会话数据,所有的server要获取或者改变会话数据时就从数据库中读取。当数据不大时,可以把数据存储到sql数据库中。优点:没有安全隐患、可以水平扩展,数据库/缓存水平切分即可、web-server重启或者扩容都不会有session丢失。不足:增加了一次网络调用,并且需要修改应用代码。
六:微服务架构
1.什么是微服务架构,每个微服务有什么特点,微服务之间如何通信? spring框架中提供微服务的技术架构叫什么?
-
将一个大的系统拆成若干个独立的小系统,分别进行维护和部署,它们之间可以通过轻量级的通信协议(http等)进行通信,在功能上还是一个完整的整体,这样的设计方法称之为微服务的架构。 -
微服务下,每个功能部件的本身形成一个可以独立运行的系统,它们之间用通信协议进行通信,形成一个功能和之前一样的大系统。 优点:做负载均衡时,每个模块可以独立进行水平扩展,打展的重足个一t次。用户量少的、计算工作简单的模块可以少扩展几个副本,这样有效的节省系统资源,使系统更加高效。而原系统做水平扩展时,是整体进行扩展,每个部件都有相同数量的副本。 -
spring框架通过Spring Cloud来提供微服务
2.微服务架构中的基础设施有哪些,分别起到什么作用?
微服务通过Eureka Service discovery注册发现信息,并通过它调用其他微服务。通过ZIPkin Distributed logging service用于记录所有系统的调用过程,可以实现对系统中调用的追踪。通过Configure service保存和管理微服务系统的所有配置信息,相当于一个仓库。 先启动Configure service,再启动Eureka Service discovery,最后是其他的业务系统。每个服务都可以独立的开发和运行,每个服务都带自己的数据库、接口的定义和逻辑的实现,所以可以单独维护。
3.微服务系统中为了防止因为某个服务失效而导致其他服务失效,采取什么措施?
采用断路器这样的概念来解决。
和生活中短路开关的概念一样,一方面保护电路不致于电流过大出现火灾,另一方面通知用户。在微服务系统面通知调用者,使得调用者采取一些措施不要导致错误不断蔓延到其他业务。调用者将调用请求不是直接发给被调用方,而是交给断路器,由它转发给被调用者。如果被调用者产生了问题(如过忙,线路断开),断路器感知到问题。通知用户或者提供一些默认的结果,以防止调用者失效、错误蔓延。
七:无服务架构
1.什么是无服务结构?
无服务器架构是指应用程序使用第三方管理的Function和服务,因此不需要管理服务器。
无服务器架构主要包含了两个方面:
-
BaaS (Backend as a Service,后端即服务)∶使用第三方服务(如Firebase、Auth0)来达成目的。使用BaaS的应用程序通常是富客户端应用程序,如SPA或移动App。客户端负责处理大部分的业务逻辑,其他部分则依赖外部服务,如认证、数据库、用户管理,等等。 -
Faas (Function as a Service,Function即服务)∶包含服务器端业务逻辑的无状态Function。这些Function运行在独立的容器里,基于事件驱动,并由第三方厂商托管,如AWS Lambda或者Azure Functions。
2.无服务架构的设计思想是什么?
无服务不单是允许租用基础设施,而且在软件开发的过程中可以完全尽重使用第三方现有的软件服务或者将一些业务逻辑写成一个个的计算单元,部者到别人的管理的容器中去,用的时候再去调用这些业务逻辑单元,从而使得对服务器的管理成本降低很多甚至为0。只需完成业务逻辑部分,其他的够可以交给第三方完成。
八:管道过滤器架构
1.Spring中如何支持管道过滤器架构的应用设计﹖管道过滤器架构的应用场景是什么?
- spring batch是一种支持管道过滤器风格的开源技术框架。可以进行大规模的数据批处理应用的开发,简化开发过程。
- 在设计多步的数据处理软件系统中常用的设计方法
- 管道过滤器是复杂的数据多步转换处理的一种方法
- UNIX Command Pipelines 、编译器、Java lO Streams、Axis
2.管道-过滤器架构的核心构件有哪些,这种架构的优缺点是什么?
组成:Pipes/Filter/Data Source/Data Sink
- Filter:完成单步数据处理功能,从pipe中接收数据,处理完后再交给下一个Filter
- Data Source/Data Sink/Filter 以Pipe连接
- Pipe连接相邻元素,前一个元素的输出为后一个元素的输入
优点:
- 过滤器(代表数据处理的逻辑)可以重用/重组合/可替换
- 不需要保存中间结果,因为管道可以直接将前一个filter的结果发送给下一个filter
- 高效的并行处理(多active部件)
缺点:
- 数据传输开销较大:需要借助管道
- 数据转换开销较大
- 错误处理较为复杂:用户无法在线交互,只能看到数据进去和数据输出,如果有错,检错和消除错误较为困难。
核心部件图形表示:
3.spring batch中实现管道-过滤器架构的开发模式是什么?
rob是封装整个批处理过程的单位,跑一个批处理任务,就是跑一个Job所定义的内容。 Step是对Job某个过程的封装,一个Job可以包含一个或多个Step,一步步的Step按特定逻辑执行,才代表Job执行完成。 定义一个Job关键是定义好一个或多个Step,然后把它们组装好即可。而定义Step有多种方法,但有一种常用的模型就是输入——处理—─输出,即Item Reader、Item Processor和Ithm Writer。比如通过ItemReader从文件输入数据,然后通过Item Processor进行业务处理和数据转换,最后通过Item Writer写到数据库中去。
Spring Batch 提供了许多开箱即用的Reader和Writer
九:事件驱动架构
1.什么是事件驱动架构?举例应用的例子
- 当软件系统中存在的一些事件发生,导致其他部分执行或者操作的设计方法叫事件驱动架构
- GUI设计,调试器
2.事件驱动架构的核心部件有哪些?
事件生产方产生事件。由事件管理器部件将事件散发出去告诉一个或若干个的事件消费方。事件消费方对事件进行评估是否做出响应,若响应则执行相关的动作完成这个事件。所以事件发生,驱动了另外一些部件的响应。整个系统的运行是靠事件来驱动运行的。事件消费方之前需要在事件管理器这里注册相应事件,当该事件发生时,事件管理器会触发该事件消费方。
2.为什么要使用事件驱动架构?
因为可以实现软件系统中的松耦合原则。具体原因如下:
3.事件驱动架构的实现方式有哪些?
两种方式:观察者模式,发布/订阅模式
-
观察者模式:
-
发布/订阅模式
- 事件源向事件管理器发布事件,事件在事件管理器中可能被分成一个或多个topic
- 事件订阅者首先告知事件管理器对某个事件感兴趣,相应事件发生时来告知。
- 事件的注册是专门向一个事件管理器组件进行注册
- 事件分发过程可以通过消息队列或者消息总线来实现
4.典型发布订阅者管理模式举例。
-
EventBus是Google对Java api进行扩展增强的库,包含很多关于集合,图形,并发等方法。具体包含的方法可以查看github guava wiki。 -
EventBus不需要组件之间相互明确注册即可通过发布订阅的方式完成组件之间的通信,EventBus不适用于进程之间的通信。 -
是google的java工具类库,支持在GRE以及Android上应用开发。 -
Guava在guava-libraries中提供了事件总线EventBus库,实现事件发布订阅模式。Guava提供了同步事件EventBus和异步实现AsyncEventBus两个事件总线 -
事件源发布事件(post())到eventBus. -
订阅者在eventBus中注册,并用@subscribe标注一些方法,它们代表对事件的处理方法,这些事件可以对eventBus上面别人post过来的事件进行处理。 -
事件总线按照订阅,将事件分发给订阅者去执行。 -
订阅事件的类型根据传送的参数类型确定。 -
publisher不知道事件发布给了哪些订阅者,订阅者也不知道事件从哪个oublisher来的.是宗全解棚的。
5.请比较发布订阅者管理模式和观察者模式。
- 观察者:事件管理器集成在事件源中,隐含了事件分发这个职责。事件源知道所有事件的消费方。观察者这个对象发现对象(目标)改变之后,自动通知其他对象(观察者,可以是多个,自由添加),其他对象作出反应。事件源和事件消费者耦合度较高。事件源和事件消费者之间的通信是同步的。
- 发布订阅模式:事件源和事件消费者之间通过事件通道进行解耦,双方都不知道对方的存在。事件源和事件消费者之间的通信是完全异步的。
- 事件通道作为调度中心,管理事件的订阅和发布工作,彻底隔绝了订阅者和发布者的依赖关系。即订阅者在订阅事件的时候,只关注事件本身,而不关心谁会发布这个事件;发布者在发布事件的时候,只关注事件本身,而不关心谁订阅了这个事件。
- 观察者模式是松耦合,发布订阅模式发布者和订阅者完全解耦的。
十:响应式架构
1.同步阻塞和异步非阻塞的区别?
发出request的线程被服务方挂起,当服务方得到response后就唤醒挂起线程,并将response返回给调用方。
同步:Sender发送请求后,直到Receiver有结果才返回。
阻塞:Sender获取结果期间一直被block,即在此期间sender不能处理其它事情。
异步:Sender请求发出后,立刻返回,然后等待Receiver的callback,最后再次请求获取response。
非阻塞:Sender等待Receiver的callback期间可处理其它事情。
异步非阻塞就是响应式
关注两点:变化和反应,变化在前,反应在后。
- 原来是逻辑代码执行作为主线,数据作为参与者。
- 现在以数据作为主线,逻辑代码执行作为参与者,即原来是数据传递到逻辑代码里,现在是逻辑代码传递到数据里。
- 逻辑代码通过Lambda表达式,函数式编程传递。
2.响应式架构的实现方法是采用消息驱动通信中的发布订阅模式实现,spring的Reactive Streams定义了实现这种架构的规范,包括哪四个核心概念?
-
消息发布者:只有一个subscribe接口,是订阅者调用的,用来订阅发布者的消息。发布者在订阅者调用request之后把消息push给订阅者。 -
订阅者subscriber:包括四个接口,这些接口都由Publisher触发调用。
- onSubscribe()告诉订阅者订阅成功,并返回一个Subscription;通过Subscription订阅者告诉发布者发送指定数量的消息 (request 完成)
- onNext()是发布者有消息时,调用订阅者这个接口来达到发布消息的目的;
- onError()通知订阅者,发布者出现了错误;
- onComplete()通知订阅者消息发送完毕。
-
订阅Subscription:代表的是一种订阅上下文对象,它在订阅者和发布者之间进行传输,从而在两者之间形成一种契约关系.
- request()方法:用于请求n个元素,订阅者可通过不断调用该方法来向发布者请求数据;
- cancel()方法:用来取消这次订阅。
- Subscription对象是确保生产者和消费者针对数据处理速度达成一种动态平衡的基础,也是流量控制中实现背压机制的关键所在。
-
处理器: Processor同时继承了Subscriber和publisher;其代表一个处理阶段。
- 它既是一个Subscriber,又是一个Publisher;
- Processor夹在第一个Publisher和最后一个Subscriber 中间,对数据进仃处理。有点尖队stream主的map,filter等方法。
- 在数据流转中,Processor 以Subscriber的身份订阅Publisher接受数据,乂以Publisher万T按叹只它Subscriber的订阅,它从自己订阅的Publisher收到数据后,做一些处理,然后转发给订阅它的
subscriber。
3.请描述基于响应式架构的程序设计步骤和带有处理器的响应式架构的设计步骤?
- 响应式架构的程序设计步骤
- 有处理器的响应式架构的设计步骤
- 创建一个发布者publisher:
- 创建一个Processor
- 发布者将消息给processor来做处理之后转发到最终订阅者
- 创建一个最终订阅者
- 处理器与订阅者,建立订阅关系
- 生产数据并发布
- 结束后,关闭发布者
|