应用服务框架的演变历史

2024-03-17 08:38

本文主要是介绍应用服务框架的演变历史,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在较长的一段时间里,LAMP框架是Web网站的常见方式:Linux+ Apache+ PHP+ MySQL,或者另外一套MVC规范,java里比较常见的选择通常是Spring +Struts +MyBatis +Tomcat,有时候也会选择重量级的EJB来实现,尽管在技术细节上的处理各不相同,但是都有一个共性:垂直应用架构。
垂直应用架构
垂直应用架构

一、传统的垂直应用架构

1.MVC架构
以经典的MVC垂直应用架构为栗子,通常分为三层:

  • View展示层,是用户看到并与之交互的界面。
  • Control层,用于前端Web请求的分发,调度后台的业务处理。
  • Model模型层,包含业务数据和执行逻辑。

标准的MVC模式并不包括数据访问层,所以通常还需要专门的ORM框架,可以屏蔽对底层数据库连接池和数据源的实现,提供对上层JDBC的访问,提升开发效率,常见的一般都是Hibernate和Mybatis。通常基于MVC框架的应用都会打成一个war包,部署在Tomcat等Web容器中。

业务组网也不复杂,通常做好双热机即可,可通过watchDog来检测应用,判断应用进程是否异常,如果一个出现问题可以立即启动到备机,如果考虑到更复杂的并发场景,可在后端做集群部署,还有前端F5等负载均衡处理。
双机逻辑组网图

2.垂直应用架构的缺陷

1.难以应付复杂的业务场景,且开发和维护的成本会增高。
2.团队协作效率差,公共功能重复开发,重复率高。
3.系统的可靠性变差,某个节点的故障会导致整个系统的“雪崩效应”。
4.维护和定制困难,复杂应用的业务拆分困难,代码修改牵一发而动全身。

当垂直应用越来越多,应用之间的交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使得前端能够更快的相应市场需求,同时将公共的API抽取出来,可以作为独立的公共服务给其他调用者消费,实现服务的共享和重用,于是有了RPC框架的需求。

二、RPC框架

RPC的全称为(Remote Procedure Call),远程过程调用,是一种进程间的通信方式,在2006年后的移动互联网时代开始兴起,出现了各种各样的开源RPC框架。
RRC框架原理

RPC的框架屏蔽了底层的传输方式(TCP/UDP),序列化方式(XML / JASON / ProtoBuf)和通信细节,使用者只需要知道who(谁)在where(哪里)提供了what(什么)服务即可。

一个最简单的RPC框架只需要考虑如下三个部分的实现:

  • 服务提供者,运行在服务端,负责提供服务接口定义和实现。
  • 服务发布者,运行在RPC服务端,负责将本地服务发布成远程服务,供其他消费者调用;
  • 本地服务代理,运行在RPC客户端,通过代理调用远程服务提供者,然后将结果进行封装返回给本地消费者;

在这里根据思路来简单提供一段代码实现,首先是服务的接口定义和实现:

/*** HelloService 服务接口*/
public interface HelloService {String hello(String name);}/*** HelloServiceImpl 服务接口的实现*/
public class HelloServiceImpl implements HelloService {public String hello(String name) {return "Hello " + name;}
}

服务的发布:

/*** RpcFramework**/
public class RpcFramework {/*** 暴露服务** @param service 服务实现* @param port 服务端口*/public static void export(final Object service, int port) throws Exception {if (service == null) {throw new IllegalArgumentException("service instance == null");}if (port <= 0 || port > 65535) {throw new IllegalArgumentException("Invalid port " + port);}System.out.println("Export service " + service.getClass().getName() + " on port " + port);ServerSocket server = new ServerSocket(port);for(;;) {try {final Socket socket = server.accept();new Thread(new Runnable() {@Overridepublic void run() {try {try {ObjectInputStream input = new ObjectInputStream(socket.getInputStream());try {String methodName = input.readUTF();Class<?>[] parameterTypes = (Class<?>[])input.readObject();Object[] arguments = (Object[])input.readObject();ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());try {Method method = service.getClass().getMethod(methodName, parameterTypes);Object result = method.invoke(service, arguments);output.writeObject(result);} catch (Throwable t) {output.writeObject(t);} finally {output.close();}} finally {input.close();}} finally {socket.close();}} catch (Exception e) {e.printStackTrace();}}}).start();} catch (Exception e) {e.printStackTrace();}}}

服务的引用

   /*** 引用服务* @param interfaceClass 接口类型* @param host 服务器主机名* @param port 服务器端口* @return 远程服务*/@SuppressWarnings("unchecked")public static <T> T refer(final Class<T> interfaceClass, final String host, final int port) throws Exception {if (interfaceClass == null)throw new IllegalArgumentException("Interface class == null");if (! interfaceClass.isInterface())throw new IllegalArgumentException("The " + interfaceClass.getName() + " must be interface class!");if (host == null || host.length() == 0)throw new IllegalArgumentException("Host == null!");if (port <= 0 || port > 65535)throw new IllegalArgumentException("Invalid port " + port);System.out.println("Get remote service " + interfaceClass.getName() + " from server " + host + ":" + port);return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[] {interfaceClass}, new InvocationHandler() {public Object invoke(Object proxy, Method method, Object[] arguments) throws Throwable {Socket socket = new Socket(host, port);try {ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());try {output.writeUTF(method.getName());output.writeObject(method.getParameterTypes());output.writeObject(arguments);ObjectInputStream input = new ObjectInputStream(socket.getInputStream());try {Object result = input.readObject();if (result instanceof Throwable) {throw (Throwable) result;}return result;} finally {input.close();}} finally {output.close();}} finally {socket.close();}}});}}public class RpcProvider {public static void main(String[] args) throws Exception {HelloService service = new HelloServiceImpl();RpcFramework.export(service, 1234);}}

服务的调用:

public class RpcConsumer {public static void main(String[] args) throws Exception {HelloService service = RpcFramework.refer(HelloService.class, "127.0.0.1", 1234);for (int i = 0; i < Integer.MAX_VALUE; i ++) {String hello = service.hello("World" + i);System.out.println(hello);Thread.sleep(1000);}}
}

2.RPC的不足
在大规模服务化以前,应用以前只能通过暴露接口和应用远程服务的方式去调用,服务越来越多的时候会有以下情况:

  • 服务URL的配置管理变的困难
  • 服务间的依赖关系变成错综复杂,难以分清哪个应用要在哪个应用前启动
  • 服务的调用量越来越大,服务的容量问题出现问题,某个服务需要多少机器、什么时候该加机器
  • 缺乏一个服务注册中心,动态的注册和发现服务。

服务化之后,随之而来的就是服务治理问题,现在的RPC框架在这方面都有所欠缺,要解决这些问题必须通过服务框架+服务治理来完成,单凭RPC框架无法解决服务治理的问题。

三、SOA服务化架构

SOA,Service-Oriented Architecture,面向服务的架构(SOA)是一个组件模型,是一种粗粒度、松耦合的以服务为中心的架构,接口之间通过定义明确的协议和接口进行通信。
面向服务的核心是对传统的垂直架构进行改造,其中的核心技术就是分布式服务框架,应用也从集中式走向了分布式,大规模系统的架构设计原则就是尽可能的拆分,以达到更好的独立扩展与伸缩,更灵活的部署、更好的隔离和容错,更高的开发效率,具体的拆分策略是:横向拆分纵向拆分

业务纵向拆分:
根据业务的特性把应用拆开,不同的业务模块独立部署,将复杂的业务线拆分成相对独立的、灵活的具体能力域,由大到小分而治之。

纵向拆分示意图

业务横向拆分:
将核心的、公共的业务拆分出来,通过分布式服务框架对业务进行服务化,消费者通过标准的契约来消费这些服务,服务提供者独立打包、部署,与消费者解耦。
纵向拆分示意图

服务治理
拆分了之后,随着服务数的增多,亟需一个服务治理框架,有效管理服务,提升服务的运行质量,服务治理需要满足:服务生命周期管理,服务容量规划,运行期治理和服务安全等。目前较为成熟的商用服务框架有Spring cloud,阿里巴巴提供的开源的Dubbo框架,非开源的HSF框架,

至于Dubbo和HSF这两者的差别,抄一段来展示:阿里巴巴第一代RPC框架Dubbo是国内第一款成熟的商用级RPC框架,已于2011年正式对外开源,目前已发展成为国内开源价值最高、用户使用规模最大的开源软件之一。2016年度中国开源软件Top10。最新一代RPC框架HSF,全称High Speed Framework,也叫"好舒服","很舒服"框架,是阿里内部对这一款高性能服务框架的昵称,是一款面向企业级互联网架构量身定制的分布式服务框架。HSF以高性能网络通信框架为基础,提供了诸如服务发布与注册,服务调用,服务路由,服务鉴权,服务限流,服务降级和服务调用链路跟踪等一系列久经考验的功能特性。

架构原理
分布式服务的架构可以抽象为三层:

1、RPC层:底层通信框架(例如NIO框架的封装),序列化和反序列化框架等。
2、FilterChain层:服务调用职责链,例如负载均衡,服务调用性能统计,服务调用完成通知,失败重发等等。
3、Service层:java动态代理,将服务提供者的接口封装成远程服务调用;java反射,服务提供者使用,根据消费者请求消息中的接口名、方法名、参数列表反射调用服务提供者的接口本地实现类。

分布式服务框架的两个核心功能:服务治理和服务注册中心,服务中心中dubbo默认使用的是ZooKeeper,HSF默认使用的为ConfigServer。

四、微服务

SOA解决了应用服务化的问题,随着服务化实践的深入,服务的规模也越来越大,服务治理的问题也越来越多,这时候出现了微服务的思想。微服务架构由多个微小服务构成,每个服务就是一个独立的可部署单元或组件,它们是分布式的,相互解耦的,通过轻量级远程通信协议(比如REST)来交互,每个服务可以使用不同的数据库,而且是语言无关性的。它的特征是彼此独立、微小、轻量、松耦合,又能方便的组合和重构,犹如《超能陆战队》中的微型机器人,个体简单,但组合起来威力强大。

微服务之所以这么火,另一个原因是因为 Docker 的出现,它让微服务有一个非常完美的运行环境,Docker 的独立性和细粒度非常匹配微服务的理念,Docker的优秀性能和丰富的管理工具,让大家对微服务有了一定的信息,概括来说 Docker 有如下四点适合微服务:

  • 独立性:一个容器就是一个完整的执行环境,不依赖外部任何的东西。
  • 细粒度:一台物理机器可以同时运行成百上千个容器。其计算粒度足够的小。
  • 快速创建和销毁:容器可以在秒级进行创建和销毁,非常适合服务的快速构建和重组。
  • 完善的管理工具:数量众多的容器编排管理工具,能够快速的实现服务的组合和调度。

作者:YitaiCloud
链接:https://www.jianshu.com/p/62398fa9bc64
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

这篇关于应用服务框架的演变历史的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/818425

相关文章

修改若依框架Token的过期时间问题

《修改若依框架Token的过期时间问题》本文介绍了如何修改若依框架中Token的过期时间,通过修改`application.yml`文件中的配置来实现,默认单位为分钟,希望此经验对大家有所帮助,也欢迎... 目录修改若依框架Token的过期时间修改Token的过期时间关闭Token的过期时js间总结修改若依

MyBatis框架实现一个简单的数据查询操作

《MyBatis框架实现一个简单的数据查询操作》本文介绍了MyBatis框架下进行数据查询操作的详细步骤,括创建实体类、编写SQL标签、配置Mapper、开启驼峰命名映射以及执行SQL语句等,感兴趣的... 基于在前面几章我们已经学习了对MyBATis进行环境配置,并利用SqlSessionFactory核

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

数据治理框架-ISO数据治理标准

引言 "数据治理"并不是一个新的概念,国内外有很多组织专注于数据治理理论和实践的研究。目前国际上,主要的数据治理框架有ISO数据治理标准、GDI数据治理框架、DAMA数据治理管理框架等。 ISO数据治理标准 改标准阐述了数据治理的标准、基本原则和数据治理模型,是一套完整的数据治理方法论。 ISO/IEC 38505标准的数据治理方法论的核心内容如下: 数据治理的目标:促进组织高效、合理地

ZooKeeper 中的 Curator 框架解析

Apache ZooKeeper 是一个为分布式应用提供一致性服务的软件。它提供了诸如配置管理、分布式同步、组服务等功能。在使用 ZooKeeper 时,Curator 是一个非常流行的客户端库,它简化了 ZooKeeper 的使用,提供了高级的抽象和丰富的工具。本文将详细介绍 Curator 框架,包括它的设计哲学、核心组件以及如何使用 Curator 来简化 ZooKeeper 的操作。 1

查看提交历史 —— Git 学习笔记 11

查看提交历史 查看提交历史 不带任何选项的git log-p选项--stat 选项--pretty=oneline选项--pretty=format选项git log常用选项列表参考资料 在提交了若干更新,又或者克隆了某个项目之后,你也许想回顾下提交历史。 完成这个任务最简单而又有效的 工具是 git log 命令。 接下来的例子会用一个用于演示的 simplegit

【Kubernetes】K8s 的安全框架和用户认证

K8s 的安全框架和用户认证 1.Kubernetes 的安全框架1.1 认证:Authentication1.2 鉴权:Authorization1.3 准入控制:Admission Control 2.Kubernetes 的用户认证2.1 Kubernetes 的用户认证方式2.2 配置 Kubernetes 集群使用密码认证 Kubernetes 作为一个分布式的虚拟

Spring Framework系统框架

序号表示的是学习顺序 IoC(控制反转)/DI(依赖注入): ioc:思想上是控制反转,spring提供了一个容器,称为IOC容器,用它来充当IOC思想中的外部。 我的理解就是spring把这些对象集中管理,放在容器中,这个容器就叫Ioc这些对象统称为Bean 用对象的时候不用new,直接外部提供(bean) 当外部的对象有关系的时候,IOC给它俩绑好(DI) DI和IO

Sentinel 高可用流量管理框架

Sentinel 是面向分布式服务架构的高可用流量防护组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。 Sentinel 具有以下特性: 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应