java web应用的历程

lunchbox 发布于 2024-10-17 65 次阅读


java web应用的历程

想要浏览本地计算的资源很简单,一个最基本的操作系统都会提供文件管理的功能。对于大众来说浏览特定的文件,而不用关注文件类型,存储介质的不同,是因为操作系统,硬件驱动,文件解析软件的共同作用。

而如何访问他人计算机上的资源呢?

  • 通过一个计算机开放的端口

不论是b/s或者是c/s的架构,本质上都是向对方传输相应的计算机资源,再通过客户端来展示这些资源。

而b/s,即web应用是当今最为流行的一种计算机应用层之间的交互形式。

b/s与c/s

在gui出现的年代,各种gui应用如雨后春笋般涌现,但碍于操作系统的底层环境,各种不一样的gui操作库,这让如何在不同的计算机上提供相同的内容成了个棘手的问题。

随着年代的发展,早期的浏览器从只提供最基础的文本和图形,到能够使用html,css规范展示页面,能够使用自带的js解释器,使用js动态处理页面元素,还能提供io,文件管理功能,已然实现飞跃式的成长。可以说,浏览器就是另一个操作系统,在常用的操作系统环境中提供了一个中间层,为所有使用者提供了一个统一的且方便实用的客户端。

各家自实现的资源传输协议(可理解为书信的格式)也被渐渐统一,http,websocket,ftp等都是常见的资源规范。

单体应用

只需要一台计算机,能接受请求,返回规范的传输格式,那么浏览器就可以展示你精心设计的页面。

静态资源

对于如何组织文件,如何实现http,ftp等协议的实现又是五花八门。这时候nginx,apache等提供了方便且统一的服务器实现。只需通过相应的配置,启动服务器,那么对于每个人,我们都能在浏览器上浏览到相同的页面。

动态资源

静态资源服务器虽然满足了博客这种简单的互联网需求,但对于如论坛,商城这种不同人看得到不一样的页面的动态需求却无能为力。

一个能够提供动态资源的需求出现,各家也提供了不同的实现。

  • nginx的cgi技术,将配置中指定的文件交给相应的处理程序执行,然后返回对应的规范资源。只要实现了cgi的规范,不限于php,java,ruby,cpp等语言都可以提供资源。

  • nginx的代理转发,转发到特定的程序,由程序处理。(cgi,fastcgi都存在性能问题,使用特定的程序能大幅优化性能,如php的swoole)

  • ASP(Active Server Pages)是一种由微软开发的服务器端脚本技术(过时 当今的服务器基本都在linux上)。

  • java也在大趋势下出现了自身的服务器规范 - jakarta ee(java ee)。对于不同的web需求,java规范了如servlet,listener的前台规范,也有ejb的数据层操作规范。实现了规范的容器程序如Tomcat,Jboss,Weblogic等出现在市场。(ps 在js还未一统浏览器的时候,还出现过applet,浏览器运行发送过来的class)

  • ruby的puma,Python的Gunicorn/Daphne等

碍于直接返回html资源的拼接字符串过于丑陋,参考asp而出现的jsp技术(jakarta 规范)得以流行起来。

jakarta ee容器

容器是java提供web服务器的功能的程序,根据实现的功能模块不同,可分为servlet容器,ejb容器等。

不必要的ejb

ejb就是把数据库对应的java bean操作封装在相应的服务器容器上的技术。而jta是请求ejb封装的接口的规范。

如果没有统一的浏览器出现,那么客户端总要自己实现一部分的逻辑操作,而数据库部分的连接与处理定然不能直接在客户端上完成。于是在客户端与数据库之间引入ejb容器这个中间层,处理不同应用的事务(必须一次性完成的数据操作),提供全局事务的管理功能。

然而只在b/s层面上看,ejb过于笨重。因为数据库的连接,处理只需要在服务器上,不会在用户的客户端上。本地事务(在这个服务器程序上)即可提供所需的功能。

这里就引入了spring的事务功能,剔除ejb的开发。

servlet

Servlet 是一种 Java 技术,用于处理 Web 服务器上的客户端请求,特别是 HTTP 请求。它在 Java Web 容器中运行,为浏览器和 Web 客户端提供动态响应。Servlet 本质上是 Web 服务器与客户端之间的中间层,用于接收客户端的请求、处理请求并生成动态的响应内容,通常是 HTML 页面。
Servlet 的工作流程

  1. 客户端请求:客户端(通常是浏览器)通过 HTTP 请求与服务器进行通信。
  2. 服务器处理:服务器将请求转发给 Servlet 容器,容器会根据请求的 URL 选择合适的 Servlet。
  3. Servlet 处理:Servlet 会通过 doGet() 或 doPost() 等方法处理请求,执行业务逻辑,并可能与数据库或其他服务交互。
  4. 生成响应:Servlet 生成响应内容,通常是 HTML 页面、JSON 数据或文件。
  5. 返回响应:服务器将响应结果返回给客户端,完成整个请求-响应的过程。

引入spring mvc/structs(过时)的技术,简化直接的servlet api开发。

前后端分离

jsp虽然提供了页面的直观处理能力,但是它的实现与java绑定得太过深入。模板引擎是个不错的替代技术,但还是不能解决java开发效率的问题。

静态的页面与动态的服务器分离成了自然的技术选择。

将html,css,js以及静态的资源分开,前后端使用http通信。而后端统一使用无状态的restful风格接口规范。

ps:

无状态性要求:
每个请求都是独立的:服务器不会将前一次请求的信息保存为上下文或状态。这意味着每个请求都应包含所有必要的认证和参数,以便服务器能够正确处理。
不依赖服务器会话:服务器不应该依赖像服务器会话、内存中的状态等来判断请求的上下文。
客户端需要管理状态:由于服务器不存储状态,客户端需要自行管理和保存相关的信息(例如,用户登录信息、分页状态、会话等)

引入了统一的restful风格规范。
繁杂的spring部署配置,引出springboot 约定的配置+内嵌tomcat.

越来越臃肿的单体应用-微服务的出现

一个简单功能的改变,需要整个应用程序的再发布,严重影响了程序的迭代能力。

如何拆分应用?Netflix的开源组建提供了良好的示范。而在之后的生产应用中,srping也提出了相应的规范。微服务的改变是巨大的,他引入了众多全新的概念。然追根究底,还是计算机资源的获取流程处理。

微服务的资源请求流程

请求-》nginx(反向代理,负载均衡,限流)-》
spring网关-》具体的微服务应用

为了微服务的高可用,引入接口流量控制服务。
为了处理不同服务之间调用的消息积压问题,引入第三方消息队列程序。
为了处理安全问题,引入专门的安全服务。

不断地划分服务职责,每个人只负责相应的功能。

大量的数据

  • 数据库的存储

    微服务的划分仅是在程序业务处理上,而处理过程的最大耗时往往来自io。单一的数据库难以应付趋于庞大的数据量,单表有上限,单个数据库的io也有上限。
    引入springsphere-jdbc的分表分库框架。
    引入分布式数据库。

  • 数据库的统计

    关系型数据库在统计大量数据时会面临到数据库底层实现带来的性能问题,但数据又必须持久化存储。

    引入clickhouse,Scylladb数据库。

  • 数据库的全文搜索需要

    引入elasticsearch

  • 快速的数据查询,分布式服务之间的数据存储

    引入redis

  • 不好查询的日志

    引入loki,elk

  • 服务之间的消息数据

    引入rabbitMq,kafka,rocketMq

云时代

大量的微服务管理成了灾难,以及直接使用云的docker应用需求(应用部署,管理)。k8s+istio以不论编程语言的具体实现与和云部署的简单实现成了最主流的技术方案。

在这个时代,出现了go这种完全不需要类似jvm的运行环境,以及协程的简单高并发实现能力,迅速挤占了java的生态位。

而java直到21才拥有相似的纤程,在17才出现graalvm(能够打包成直接可执行文件,不需要jvm。但仍是实验性质)。springboot3激进拥抱jdk17,quarkus新时代响应式框架带着同步式编程出现。但他们打包成可执行文件的性能还是不够理想,甚至不如原有jit(jvm的动态编译二进制代码)的性能。

java如何拥抱云时代,还在继续探索。