企業開發架構及技術的變更

寫在前面

  1. 興趣是學習最好的老師
  2. 知古鑑今
  • 概述
  • Java+Servlet
  • Java+JSP
  • JSP和PHP
  • 前後端分離架構+Javascript+Restful+SpringMVC+Angular
  • iframe實現企業應用集成
  • 微應用架構

概述

在互聯網飛速發展的過程中,企業開發所使用的技術及架構也在發生變化。過早的內容我們暫且不去描述,本文只從九十年代說起。那時是沒有前端概念的,所有的事情都是後端在做,從業務邏輯到頁面繪製,所使用的技術是java和servlet;後來頁面內容逐漸豐富,引入了更加方便的jsp技術;再後來jsp的弊端逐漸顯現,一種新的想法橫空出世,引入前後端分離架構;隨着前端後各自的不斷深化,所能支撐的業務體量和複雜度不斷攀升,也逐步引入了容器化、微服務、微應用架構...

Java+Servlet

Servlet是什麼?

1997年,Sun 公司推出了 Servlet。Servlet 是 一種基於 Java 的動態網站開發技術。
嚴格來說,Servlet 只是一套 Java Web 開發的規範,或者說是一套 Java Web 開發的技術標準。只有規範並不能做任何事情,必須要有人去實現它。所謂實現 Servlet 規範,就是真正編寫代碼去實現 Servlet 規範提到的各種功能,包括類、方法、屬性等。

Servlet 規範是開放的,除了 Sun 公司,其它公司也可以實現 Servlet 規範,目前常見的實現了 Servlet 規範的產品包括 Tomcat、Weblogic、Jetty、Jboss、WebSphere 等,它們都被稱爲“Servlet 容器”。Servlet 容器用來管理程序員編寫的 Servlet 類。


如何使用Servlet?

   public class HelloWorld extends HttpServlet {  
        public void doGet(HttpServletRequest request, HttpServletResponse response)  
                throws ServletException, IOException {  
            response.setContentType("text/html");  
            PrintWriter out = response.getWriter();  
            out.println("<html>");  
            out.println("<head>");  
            out.println("<title>Hello World</title>");  
            out.println("</head>");  
            out.println("<body>");  
            out.println("<h1>Hello World!</h1>");  
            out.println("</body>");  
            out.println("</html>");  
        } 
    }  

可以看到Servlet在展示頁面的時候,輸出HTML語句採用了老的CGI(Common Gateway Interface: Servlet之前渲染頁面的方式,因servlet效率更高、可移植性更強、功能更強大而被替代)方式,是一句一句輸出,所以,編寫和修改HTML非常不方便,如果一個頁面超級複雜,動不動幾千行代碼,那這個Servlet效率也就太低了。而且整個Servlet代碼也會十分臃腫而且可讀性非常差。

Applet

您可能還聽說過 Applet,它和 Servlet 是相對的:
Java Servlet 是“服務器端小程序”,運行在服務器上,用來開發動態網站;
Java Applet 是“客戶端小程序”,一般被嵌入到 HTML 頁面,運行在支持 Java 的瀏覽器中。

Applet 和 Servlet 都是基於 Java 的一種技術,功能都非常強大,但是 Applet 開發步驟繁雜,而且只能在安裝 Java 虛擬機(JVM)的計算機上運行,現在已經被 JavaScript 全面替代,幾乎沒有人再學習 Applet。

PHP

PHP 繼承自一個老的工程,名叫 PHP/FI。PHP/FI 在 1995 年由 Rasmus Lerdorf 創建,最初只是一套簡單的 Perl 腳本,用來跟蹤訪問他主頁的人們的信息。它給這一套腳本取名爲“Personal Home Page Tools”。隨着更多功能需求的增加,Rasmus 寫了一個更大的 C 語言的實現,它可以訪問數據庫,可以讓用戶開發簡單的動態 Web 程序。Rasmus » 發佈了 PHP/FI 的源代碼,以便每個人都可以使用它,同時大家也可以修正它的 Bug 並且改進它的源代碼。
後續
1997 年 11月 發佈PHP/FI 2.0
1998 年 6 月 發佈 PHP 3.0
2000 年 5月 發佈 PHP 4.0
2004 年 7 月 發佈 PHP 5.0

Java+JSP

首先要說明的一點是JSP基於Servlet,JSP的本質是將原本Servlet中關於頁面繪製的內容單獨抽離出來由專人負責,最終還是要將JSP編譯成Servlet。

剛剛說到Servlet在開發頁面時超級複雜,這裏我們看JSP是如何解決這些問題的:

// Servlet
public class List_book extends HttpServlet {          
     public void doGet(HttpServletRequest request, HttpServletResponse response)  
             throws ServletException, IOException {  
        //聲明一個ArrayList.用來存放Book類中的數據  
         ArrayList<Book> list = new ArrayList<Book>(); 
         for(int i=0;i<10;i++){
                      Book book = new Book();  
         book.setName(res.getString("name"+i));  
         book.setAuthor(res.getString("author"+i));  
         list.add(book);  
         }
         //將list數據發送到.jap文件中  
         request.getRequestDispatcher("ListBook.jsp").forward(request, response);  
     }  
}  
// JSP
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%String path = request.getContextPath();%> 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>  
    <head>   
         <meta http-equiv="pragma" content="no-cache">  
         <meta http-equiv="description" content="This is my page">  
        <script></script> 
    </head>  
     <body>       
         <% ArrayList list = (ArrayList) request.getAttribute("list");  %>      
         <h2 align = "center">圖書列表</h2>  
         <table border = 1px align = "center">      
             <tr><th>圖書名稱</th><th>圖書作者</th></tr>    
            <!-- 繼續使用jsp語句 循環放入存放於list中的Book實體類中的數據 -->     
            <%              
             for(int i = 0;i<list.size();i++){      
                 Book book =(Book) 
                list.get(i);%>          
                <tr><th><%=book.getName() %></th><th><%=book.getAuthor()%></th><tr> 
             }
            %>  
         </table>  
    </body>
 </html>
// EL表達式和JSTL標籤庫
<c:if test="${session.username==='admin'}">
    Hello World!
</c:if>
<c:forEach items="${name}" var="name">
    ${name}<br />
</c:forEach>

首先頁面更加直觀了,然後利用MVC的思想將邏輯和UI分開,之後又引入了EL表達式和JSTL標籤庫,有效的解決了Servlet存在的問題,也使頁面展示邁入一個新的臺階。JSP曾經風靡一時,直至現在,很多老的系統都有JSP的留存,需要進行維護。

JSP受到的威脅

雖然出現了EL和JSTL,但是還是有些程序員會忍不住直接在JSP中寫java代碼。後來就出現了Free MarkerVelocity等模板引擎,程序員完全無法裏面寫java代碼了,其他都跟JSP差不多,通過標籤來負責展示邏輯。另外模板引擎還可以脫離web容器使用,這是JSP無法做到的。模板引擎出現後,JSP損失了部分用戶。

JSP存在的問題

  • 動態資源和靜態資源全部耦合在一起,服務器壓力大,因爲服務器會收到各種http請求,例如css的http請求,js的,圖片的等等。一旦服務器出現狀況,前後臺一起玩完,用戶體驗極差。
  • UI出好設計圖後,前端工程師只負責將設計圖切成html,需要由java工程師來將html套成jsp頁面,出錯率較高,修改問題時需要雙方協同開發,效率低下。
  • JSP必須要在支持Java的web服務器裏運行(例如tomcat,jetty,resin等),無法使用nginx等(nginx單實例http併發高達5w,沒有這個優勢,性能提不上來)。
  • 第一次請求JSP,必須要在web服務器中編譯成servlet,第一次運行會較慢。
  • 每次請求jsp都是訪問servlet再用輸出流輸出的html頁面,效率沒有直接使用html高。
  • jsp內有較多標籤和表達式,前端工程師在修改頁面時會遇到很多痛點。
  • 如果jsp中的內容很多,頁面響應會很慢,因爲是同步加載。
  • 需要前端工程師使用java的ide(例如eclipse),以及需要配置各種後端的開發環境,前端人員門檻較高。

JSP和PHP的區別

整體區別

  1. PHP是服務器腳本語言;JSP是服務器端編程技術。
  2. jsp使用Java語言,通過JDBC來訪問數據庫,訪問數據庫的接口比較統一;PHP對於不同的數據庫採用不同的訪問接口,訪問數據庫的接口不是很統一。
  3. Java採用面向對象,PHP採用面向過程。

php和jsp的語言比較

  • PHP是一種專爲Web開發而設計的,解釋執行的服務器腳本語言,它大量地借用C和Perl語言的語法,具有簡單容易上手的特點,所以學過c語言的都可以很快的熟悉php的開發。

  • JSP是一種服務器端編程技術,有助於創建動態網頁。它是以Java語言作爲腳本語言,結合HTML語法的;熟悉JAVA語言和HTML語法的人可以很快上手。但java不光要需要學習語法,好用熟悉一些核心的類庫,瞭解、掌握面向對象的相關知識。java要比PHP難學,因而JSP技術要比PHP難掌握。

php和jsp的數據庫訪問比較

  • jsp使用Java語言,通過JDBC來訪問數據庫,通過不同的數據庫廠商提供的數據庫驅動方便地訪問數據庫。訪問數據庫的接口比較統一。
  • PHP對於不同的數據庫採用不同的數據庫訪問接口,所以數據庫訪問代碼的通用性不強。例如:用Java開發的web應用從MySQL數據庫轉到Oracle數據庫只需要做很少的修改。而PHP則需要做大量的修改工作。

php和jsp的性能比較

  • JSP是基於Java編程語言,所以對API的支持非常龐大,在Web開發方面支持大量的第三方庫。;而PHP對API的訪問權限有限,支持的第三方庫比較少。
  • JSP支持對象緩存,而PHP不支持緩存。
  • JSP是Java類的抽象,因此它可以被垃圾收集;而PHP不支持垃圾收集。
  • JSP非常擅長維護用戶會話,而PHP每次都會破壞用戶的會話。
  • JSP執行需要更多時間,因爲它被轉換爲Servlet,編譯和執行;而PHP執行所需的時間比JSP少,隨着編碼減少和快速開發和執行,即時反饋和更高的生產力。

php和jsp的系統設計架構比較

  • 採用Java的web開發技術,需要使用的是面向對象的系統設計方法,而PHP還是採用面向過程的開發方法。所以用Java進行開發前期需要做大量的系統分析和設計的工作。

php和jsp的跨平臺性比較

  • Java和PHP都有很好的跨平臺的特性。幾乎都可以在不作任何修改的情況下運行在Linux或者Windows等不同的操作系統上。

php和jsp的開發成本比較

  • PHP最經典的組合就是:PHP + MySQL + Apache。非常適合開發中小型的web應用,開發的速度比較快。而且所有的軟件都是開源免費的,可以減少投入。
  • JSP在學習週期和開發週期都比較長,且所需的軟件不是全都免費的,開發成本比較高。

前後端分離架構+Javascript+Restful+SpringMVC+Angular

前後端分離

JSP存在的問題在淘寶等電商急速發展後越發明顯。成千上萬的頁面管理,也讓大家也意識到前端需要投入更多的精力了。這種前後端分離的思想就是後端工程師只關注於後端頁面的開發,不再處理前端問題。前端工程師只關注於自己的頁面開發。需要數據交互的時候,兩者會有一份接口文檔。

新的開發方式 SpringMVC+Angular

前後端分離思想很快流行起來,java從JSP轉向了Restful結構,SpringMVC也開始流行起來。

前端頁面上放棄了JSP,只使用簡單的Html、CSS負責展示,動態的內容就引入了JavaScript。一般的做法就是使用ajax請求JSON,根據JSON內容動態渲染DOM。

爲了讓DOM渲染的更高效,前端工程師將MVC也搬到了前端,Angular框架就是如此,Angular使用js作爲控制器,html作爲視圖,在js中異步去請求數據,然後html使用Angular標籤來負責展示邏輯(就像JSTL、EL一樣),把請求到的數據填充到html中,可以避免去直接操縱DOM。

從此,前後端各立門戶,各建工程,分了前端工程和後端工程(前端也做工程化,也需要打包、測試、部署),只要約定好數據接口,大家在需求開發時可以並行開發,各司其職。展示有問題找前端,數據有問題找後端。

架構上的改變

以前的做法是所有動態、靜態資源都打包成一個war包,部署到tomcat中,單機部署,單機提供服務,這對於以往一些流量不大的網站或者一些內部系統來講,這種做法完全足夠了。但是如今互聯網性能要求越來越高,單點是不可能滿足高性能,高併發,高可用的要求的。

現在的做法是靜態資源全部部署到nginx中,動態資源放在tomcat中,也就是動靜分離的思想。一個請求過來,先請求nginx的靜態資源,瀏覽器加載靜態資源後,通過nginx的反向代理請求後端服務器,這裏還可以使用nginx的負載均衡,添加多臺後端服務器


這樣,html頁面+json渲染 == 最終展示在用戶面前的頁面。

tomcat和nginx區別:
nginx是Http服務器,專爲處理Http請求而誕生,處理Http請求能力強,適合用於處理靜態資源(通過Http請求如實地返回內容,並且每個請求處理時間不會很長),底層採用單線程異步非阻塞方式,當讀取靜態資源發生IO時,可以先處理其他請求。據說nginx單機能抗5W併發。
tomcat是servlet/JSP容器,就是servlet/JSP運行的環境,tomcat把接收到的http請求交給servlet處理,然後servlet處理那些不講邏輯的業務邏輯,適合處理動態資源。tomcat一般採用線程池的方式處理請求,當請求數量多,線程處理時間長,線程處理不過來,線程間會頻繁切換,消耗大量cpu資源和內存。當請求超過一定的數量,會拒絕連接。因此JSP並不適合用於高併發的場景

iframe實現企業應用集成

企業應用集成的概念在JSP、PHP時代就已經比較廣泛了。在開發大型項目時,爲了提高性能,往往要分成多個模塊進行開發,並且需要具有一定的擴展性,來應對未來的變化。
基於iframe的企業集成方案應運而生。


當用戶訪問嵌入第三方服務的iframe頁面時,本方服務向統一身份認證平臺驗證用戶服務權限並得到第三方服務令牌,通過URL傳送給第三方服務,第三方服務解析後向統一身份認證平臺驗證該用戶權限令牌信息,若用戶權限令牌信息正確則提供服務。
在此基礎上,還可以通過瀏覽器提供的postMessage實現跨源通信。
這種集成方案被廣泛應用與各個生產平臺。

微應用架構

什麼是微應用?

20世紀末,隨着電商的興起,業務需求越發旺盛,代碼量驟增。網絡公司,如 Netflix 和亞馬遜,都面臨着大規模軟件開發的挑戰。要將數百個貢獻者對龐大的共享代碼庫進行修改所產生的摩擦降到最小,從而將代碼庫進行切割,使團隊可以更快地行動,減少操作衝突。如今,移動開發團隊也面臨同樣的挑戰,另外,他們還面臨着額外的挑戰:應用程序作爲單一的二進制文件交付,用戶可以下載到自己的設備上運行。隨着移動應用程序代碼庫的增長,編譯成越來越大的二進制文件所需的時間也越來越長。爲了應對這些問題,產生了微應用的概念。
微服務將後端分離出來的區域單獨部署。與此類似,移動開發者可以將應用程序的不同核心部分——單一特性、共享業務邏輯和低級特性——轉移到獨立的模塊庫中。由此產生的模塊彼此獨立,並且獨立於主要的應用程序代碼庫,團隊可以自行處理它們。這種架構不同於其他強調模塊化的方法,即微應用(Microapp)。


因此,微應用的架構包括一個模塊化設計,並輔之以專門的應用程序(稱爲微應用),供開發和測試使用,這就是爲了提高開發者的速度。與 MVC (模型-視圖-控制器)或 MVVM (模型-視圖-控制器) 等明確定義的框架相比,它更像是一種抽象的框架,因爲架構根據具體應用的特性而有所不同。然而,儘管沒有一種放之四海而皆準的辦法,但所有的成功實施都是一樣的。

微應用的特點

  • 技術棧無關:主框架不限制接入應用的技術棧,子應用具備完全自主權。
  • 獨立性強:獨立開發、獨立部署,子應用倉庫獨立。
  • 狀態隔離:運行時每個子應用之間狀態隔離。

微應用的操作手冊

  • 注意系統間的界限:採用微應用架構需要時間,需要大量的學習和實驗。在你最初的幾次模塊提取過程中,要注意你的系統組件之間的界限、一個組件的隔離和遷移要求,代碼庫應該如何組織,以及你的工具需要如何改進以支持應用程序的構建、測試和部署,因爲應用程序已經變得完全模塊化。

  • 先抽離完全獨立的模塊:在應用程序中已被隔離或由多個特性共享的部分可以成爲你第一個模塊提取的理想選擇。這幾個模塊只需對代碼做一些簡單的更改,讓你的團隊專注於提取過程本身並加以學習。例子包括基礎組件,如 API 客戶端;無處不在的用戶界面元素,例如具有自定義風格的按鈕;或沒有上游依賴關係的低級特性集羣,例如標準庫擴展。

  • 時常總結拆分模塊的標準和方法:一旦你提取出三到五個模塊,就把你所學到的轉化爲創建新模塊的明確標準。這些標準應該規定一個模塊的代碼庫應該如何組織,它應該如何集成到面向用戶的應用程序中,以及它的 CI 設置。自動化應該使任何人都能生成構建新模塊所需的“腳手架”。這種在學習、文檔和工具方面的早期投資將爲剩餘的遷移工作奠定堅實的基礎。

目前國內對微應用的應用

single-spa

single-spa是一個用於前端微服務化的JavaScript前端解決方案。single-spa的核心就是定義了一套協議。協議包含主應用的配置信息和子應用的生命週期,通過這套協議,主應用可以方便的知道在什麼情況下激活哪個子應用。
配置信息
在single-spa中的配置信息也稱爲:Root Config,如下就是具體的配置項。需要配置子應用的名稱,加載方式以及加載時機。

 { 
            name: "subApp1", //子應用的名稱
            app: () =>//告訴主應用如何加載子應用的代碼,
            System.import("/a/b/subAPP/code"), 
            activeWhen: "/subApp1", //告訴主應用何時激活子應用
 }

single-spa提供registerApplication將子應用的信息註冊到主應用中。

 singleSpa.registerApplication(
        { 
            name: 'appName', 
            app: () => System.import('appName'), 
            activeWhen: '/appName', 
        }
)

過程如圖


qiankun

qiankun是基於single-spa提出的微前端框架, 提供了更加開箱即用的API(single-spa+sandbox+import-html-entry)。

Module Federation以及EMP

Module Federation是webpack5中的新特性,主要是用來解決多個應用之間代碼共享的問題,可以更加優雅的實現跨應用的代碼共享,使用這個方法也可以實現微前端。

公司內以及其他微前端框架

在搜索相關資料的時候,關注到公司內部和其他企業也有很多優秀的微前端的解決方法,比如司內的微前端oteam,無界和Hel微前端等產品,美團的基於React的中心路由基座式微前端和Bifrost框架,字節的lModern.js和lGarfish。微前端的生態逐漸繁榮,之後也會繼續學習其相關的知識。

技術選型

當理解完理論開始實踐時,第一關便是技術選型,現有的備選方案如上一章所述,這裏提出一些具體的選型建議:

single-spa:是第一個微前端框架,當前流行的大量框架都是single-spa的上層封裝,但是如果作爲生產選型,single-spa提供的是較爲基礎的api,應用在實際項目中需要進行大量封裝且入侵性強,使用起來不太方便。但是如果想學習相關技術或者封裝一套更靈活的解決方法還是很值得使用的。

qiankun: 阿里開源的一套框架,基於single-spa的上層封裝,社區活躍度較高,在國內的生態較好,中文文檔齊全,有大量的先行者鋪路,比較適合用於生產環境。

EMP: 基於module federation實現的一套可以跨應用共享資源的框架,除了具備微前端的能力外,還實現了跨應用狀態共享、跨框架組件調用的能力,屬於司外最年輕的微前端框架(暫時不適用於生產環境中),目前在github上是1.6kstar (qiankun是11.9k)。

微前端的進一步探索詳見參考文章。

參考文章:

曾經風光無限的jsp技術,爲什麼現在很少有人用了呢?
從JSP的發展歷程談談前後端分離
JSP的缺點和前後端分離的好處
瞭解一下iframe頁面嵌入使用,輕鬆實現頁面集成
JSP的前世今生~
PHP 的歷史
Servlet到底是什麼(非常透徹)
Servlet 簡介
php和jsp之間有哪些區別
FreeMarker 快速入門
CGI與Servlet的區別和聯繫
瞭解新興架構模式:微應用架構
微前端究竟是什麼?微前端核心技術揭祕!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章