武林中,"天下武功出少林"指各門各派的武功都與少林武學有必定的淵源,技術也是相同的道理,對於Java領域的應用而言,傳統行業與互聯網行業的技術都來自J2SE和J2EE的生態圈,可是兩個行業的側重點不一樣,傳統行業側重於嚴格的規範、複雜的流程、豐富的功能,所以或多或少的都會使用J2EE規範定義的技術,Appserver是J2EE規範的徹底實現,所以,傳統行業的企業級軟件開發基本都是部署在Appserver上的,這樣能夠重複利用Appserver提供的通用功能而節省開發和實現的工做量,然後者更注重互聯網產品的非功能質量需求,一般包括:高可用、高性能、安全性、可伸縮、可擴展等,互聯中最流行的一句話是:天線武功惟"快"而不破,充分看出互聯網企業里程序性能的重要性,爲了達到較好的性能,高度抽象的J2EE技術已經無法知足需求,所以互聯網技術更傾向於在簡單的J2SE上發展具備互聯網特點的技術棧,從新定義互聯網級的開發工具、平臺和技術棧。html
因爲筆者從傳統的外企轉型到互聯網已經有3個年頭,近兩年來面試了不少來自傳統行業的同行們,筆者發現這些同行們都有意向走進處於風口的互聯網,可是因爲傳統行業使用的技術棧與互聯網有所不一樣,不知從哪裏開始入手準備和提升,儘管他們有強烈的學習和提升的願望,本文就是給這些想從傳統行業跨入互聯網的小夥伴們準備的一篇導向性文章,幫助讀者瞭解互聯網的技術棧、瞭解互聯網的側重點、瞭解互聯網的核心技術,並給出如何以傳統行業的技術棧爲基礎快速掌握互聯網的核心技術,其實,那只有一牆之隔,捅破那張窗戶紙兒,一切都豁然開朗。前端
這裏須要再次澄清,我並不認爲互聯網行業的技術要比傳統技術深奧多少,這些技術跑不出J2SE和J2EE的生態圈,只不太高度抽象的J2EE技術因爲性能上的侷限性而被互聯網撇棄而已,可是不得不認可的是兩個行業的側重點不一樣,傳統行業側重於規範,流程,功能的複雜性以及正確性,而互聯網更側重於「快」,這裏的「快」有兩方面的意思,一個是產品運行效率要高,響應速度要快,另一個是開發效率要快,響應市場需求要快。從另一個側面說,傳統行業通常關注一個複雜系統的功能完善和豐富,而互聯網企業更關注一個簡單的垂直業務的非功能質量,例如:高性能,可用性,高併發,可擴展,可伸縮,安全性等,那麼,一個從業人員從傳統行業到互聯網行業,你到底還有多少距離?nginx
這兩年來面試下來看到了一個廣泛的現象,來自於傳統行業的技術人員,他們大多數掌握的技能是SSH,稍微資深一點的工程師對J2EE規範有所瞭解,他們仍然在使用J2EE規範的EJB, JPA, JMS, JCA, JAAS等技術,數據庫基本上使用Oracle,DB2,Sqlserver等等。傳統行業的開發人員基本實施「模塊包攬制」,這得益於J2EE規範的完整性,以及Appserver提供了基本全部架構須要的功能,開發人員只須要將各個業務模塊填入J2EE和Appserver提供給你的框架便可,所以,一個傳統的開發人員會包攬一個模塊從前臺到後臺全部的工做,這包括:HTML, JS, CSS, EJB, JPA, SQL, PLSQL等等。這些技術是否是一無可取,固然不是,反而是很是有價值的,那有了這些技術,咱們是否能夠一步跨入互聯網,也不是,還須要以這些技術爲基礎,進一步擴展技術視野,對欠缺的技術廣度和深度進行不足。git
下面就學習傳統行業技術人員擁有哪些技術積累,下一步又如何補充本身的知識面,成爲可以勝任互聯網行業的優秀技術人員呢?github
在傳統行業,相信你必定用過JMS,做爲J2EE規範的一部分,全部的Aappserver(Weblogic、Websphere、Jboss等)都有JMS的實現,那你必定知道JMS包含Queue和Topic兩種Subject,你也知道Send/Receive和Publish/Subscribe兩種收發模式,那在互聯網爲何就不用這些呢?面試
緣由主要有兩個,一個是商業的Appserver都是收費的,然而,互聯網提供的產品是免費的,互聯網使用的產品也可能是免費的,另一個緣由就是這些Appserver的實現性能差,有測評顯示ActiveMQ比JbossMQ速度要高出10倍,在某些應用場景下ZeroMQ的速度要高出一個數量級,可達到微妙級別的延遲,有興趣能夠參考ZeroMQ的性能 測試頁面 。算法
除此以外,一些開源的MQ的實現針對互聯網業務,提供了除Queue和Topic的支持,還有partition,group,broker等更復雜的消息模型,具體參考Kafka, Kafka的設計具備使用簡單、功能豐富、高性能等優勢,不但天生具備持久、分片、複製等功能,並且在使用上對開發者和運維的體驗也很好。對於Kafka的中間件設計,請參考個人博客文章 簡單易用的消息隊列框架的設計與實現 。spring
那麼若是你在傳統行業掌握了JMS規範定義的消息隊列技術,你只須要再往前走一步,請深刻學習開源的Kafka、RockitMQ、ActiveMQ、RabbitMQ、MemcacheQ、Redis、ZeroMQ、MSQ等。sql
在傳統行業,相信你們都用過Oscache和Ehcache, 前者主要針對網頁的緩存,後者主要針對數據庫數據的緩存,一般可做爲Hibernate的二級緩存,相信有些人還用過Jboss Cache,這是一個分佈式企業級可實時複製的Cache,有些人在項目中也寫了本身的緩存,甚至在一些項目中直接使用Hashtable做爲緩存,其實這些緩存加速了特定場景下的數據訪問,對你的項目成功起到了相當重要的做用。數據庫
可是互聯網行業則從另一個角度來使用緩存,主要應用場景有兩個:第一,大量的數據須要集中保存,在服務的任意節點上能夠訪問緩存中的任意數據,也就是須要數據的中心存儲,並且還要知足快速的查詢需求的場景;第二,數據庫讀性能是有瓶頸的,廉價硬件機器上的單機Mysql讀操做吞吐量在1000/s左右,大量的讀查詢會壓垮數據庫,這須要使用緩存來抗住讀流量,一般應用在有熱點數據的場景。
從這兩個應用場景來看,互聯網行業更關心分佈式緩存,那數據如何分佈呢?很簡單,Hash或者一致性Hash,因此,我們可不能夠先把Oscache和Ehcache放一邊,來研究一下Redis,Memcache或者淘寶的Tair呢?最簡單的辦法從Redis和Memcache的區別開始入手?可參考個人博客文章Redis vs. Memcache ,這裏博客文章只是簡單的介紹了Redis和Memcache的區別,要想深刻學習緩存技術推薦你們仔細閱讀 Redis設計與實現 一書。
除了要學習分佈式緩存,例如:Redis、Memcache自己的功能和技術點外,最主要的要有緩存分片的思想,在互聯網裏大多數的熱數據都是緩存在緩存服務中的,這須要大量的緩存服務器,單臺機器是不能知足需求的,那緩存分片是一個大話題,緩存分片的實現方式通常有以下3種:
經過代理層實現,例如Codis,在代理層實現數據的路由,對應用層透明。
客戶端分片,可參考個人開源項目 redic ,實現簡單、使用簡單、支持分片、複製、失效轉移等功能。
緩存服務器支持的高可用模式,例如:Redis 3.x、Sentinel等。
在傳統行業,相信你們都使用EJB和Webservice來提供服務的導出和導入,有些個別傳統行業不用APP服務器,僅僅使用JDK的RMI來導出和導入服務,可是爲何互聯網恰恰不喜歡這些技術呢?Webservice使用重量級的SOAP協議,臃腫的XML滿世界都是,性能上的去嗎? 那互聯網用什麼,互聯網使用輕量級的RPC框架和RESTful服務,前者使用輕量級的序列化框架,例如:Google的ProtoBuffer, 還有Hessian和Burlap等序列化協議,後者則使用簡單的HTTP協議,前者適合在內網作高性能的服務調用,然後者適合異構平臺的服務調用,例如: 跨語言,跨防火牆,先後臺之間等。RPC遠程調用請參考阿里的Dubbo框架和Twitter的Finagle框架,至於Rest框架參請考Spring Web MVC,Spring Boot、Jersey,Apache CXF等。
在互聯網的世界裏,幾乎全部的公司都實現了服務化,服務化致使的問題就是一致性問題,如何解決高併發系統的一致性呢?使用兩階段提交協議、三階段提交協議、TCC?仍是遵循ACID原理、CAP原理、BASE原理?若是咱們保證的是最終一致性模型,咱們都有哪些模式能夠應用,請參考個人博客文章 保證微服務架構一致性的公開課 ,這篇文章裏有視頻、PPT和完整的一致性保證的文章幫助你們學習一致性保證的最佳實踐和完善的理論體系。
最近微服務變得愈來愈流行,微服務其實是服務化的一個延續,是更細緻化的服務化的架構,微服務的服務框架的表明是Spring Cloud,它與Netflix集成,提供了限流、熔斷、倉壁隔離、失效轉移等爲服務化中必不可少的高級特性,你們能夠到 官網文檔 進一步學習Spring Cloud相關技術。
在傳統行業,大多數人開發人員都使用Oracle, DB2, Sqlserver數據庫,其實,從功能和性能上來說,他們都不亞於Mysql, 甚至比Mysql更優秀,可是Mysql是免費的,這使得Mysql獲得互聯網行業的青睞。
那麼咱們分析下,傳統行業的人員在數據庫方面欠缺什麼嗎?首先,Oracle和Mysql都使用B+樹索引,原理相同,使用方法相同;Oracle支持行級鎖,Mysql Innodb一樣支持行級鎖;Oracle Dataguard支持數據複製,Mysql也支持數據複製,可是Mysql的複製模式更靈活,而且支持主主配置。前面這些都是大同小異,若是你理解了相應的Oracle技術,你用不多的時間就能夠掌握Mysql的相關技術。可是不一樣點是,Oracle雖然支持集羣,經過增長服務節點的方式能夠增長服務性能,可是集羣的節點數量是有限的,而且數據存儲是共享的,因此擴容基本採用垂直方式,然而使用Mysql則採用水平擴展,也就是須要進行手工的分區分表,對數據進行分而治之,以知足日益增加的讀寫壓力以及數據存儲壓力。所以,若是想向互聯網轉行,必定要學好Mysql,推薦閱讀《高性能Mysql》,這本書是必讀的書籍,並且推薦每個應用開發人員都要通讀全書,而不是僅僅讀其中與應用相關的那部分。
在互聯網行業裏面對性能追求到達了極致,所以會要求開發人員對數據庫原理有所瞭解,其中最重要的部分就是索引,關於數據庫的索引原理可參考文章 MySQL索引背後的數據結構及算法原理 。
剛纔談到,高併發系統,壓力山大的時候怎麼辦?思想只有一個分而治之( divide-and-conquer)。所以,負載均衡則很是重要,傳統行業以銷售產品爲盈利模式,所以,大多數項目在須要負載均衡的時候,多使用F5硬件負載均衡。
實際上傳統的J2EE規範的EJB也能夠分佈式發佈,經過JNDI的集成,也能夠進行必定程度的負載均衡,可是這個負載均衡顯得過重量級,用起來很是的不方便,效率也很低,而且和APP服務器綁定。
那麼互聯網呢?多采用軟負載均衡,你必須瞭解LVS,nginx, Apache, Varnish, Haproxy等七層和三四層負載均衡原理和產品。
另外,在互聯網行業作Java開發,必定要對JVM有所瞭解,而且進行深刻的研究,例如:GC,類加載,Hotspot編譯器,多線程、併發和鎖,IO和NIO等。推薦閱讀《深刻理解Java虛擬機++JVM高級特性與最佳實踐》,《深刻理解Java7》,《Java Concurrency In Practice》,《Pro Java 7 NIO.2》,《Java Performance》等一系列深層次的JVM相關數據,最好能閱讀《The Java® Language Specification》和《The Java® Virtual Machine Specification》兩本龍書,這些書籍均可以從 Java核心必讀書籍共享 這篇文章下載。
做爲一個IT從業人員,必定要跟上技術潮流,像雲計算,大數據,CAP, BASE, 選主算法等概念不得不去了解,對於熱點技術不得不研究,例如: Hadoop, Hbase, Zookeeper, Openstack, Dooker, Kafka, Storm等。
對於大數據技術推薦閱讀Google三大論文,Mapreduce, GFS和BigTable,這三篇論文是大數據處理的鼻祖型論文,最核心的分佈式存儲、分佈式處理、大文件的高效存儲等技術都在這裏,大數據鼻祖的三大論文能夠從個人博客文章 谷歌大數據的三駕馬車 下載。
若是你決定要來互聯網一顯身手,你必須學會性能評估和容量估算,這包括對前端機、緩存、消息隊列、數據庫等各個性能指標的估算,例如:吞吞量,響應時間,內存,CPU,IO,網絡IO等。
性能和容量評估的方法論和典型案例可參考文章 互聯網性能與容量評估的方法論和典型案例。
爲了確保架構設計的合理性,性能和容量評估是在架構設計初期完成的,用來證實架構方案可行,可是在項目實施中和實施後,還須要對項目的進行壓測,來證實項目按照既定的目標而推薦和完成,關於性能測試的方法論和設計流程,我將會在後續文章中介紹給讀者。
在互聯網行業裏,處理大規模高併發的用戶請求的核心思想只有一個,那就是「分而治之」,所以,一般業務被拆分爲多個職責單一的服務,在某一個單服務裏,業務邏輯並不複雜,可是對非功能質量需求的要求較高,這一般表如今性能、可用性等方面,所以互聯網的架構設計中首要考慮的是非功能質量,這和傳統行業注重功能和業務流程的狀況有所不一樣,對於互聯網行業中,架構設計的案例,能夠參考這篇原創發號器Vesta的設計與實現 如何設計一款多場景分佈式發號器(Vesta) ,來了解互聯網業務的架構設計的風格和思路。
在互聯網企業裏,大多數產品都是針對用戶端的,用戶端的產品的特色是擁有海量的用戶、產品要可以處理海量用戶產生的大規模高併發的用戶請求,所以會對產品的可用性比較敏感,在這種環境下,技術攻關和線上應急顯得尤其重要,例如:如何解決線上線程卡死問題、如何解決OOM問題、如何解決服務超時問題等,能夠參考以下兩篇文章: Java服務化系統線上應急和技術攻關,你必須掌握的Linux命令 和 Java服務化系統線上應急和技術攻關,你必須擁有的那些應用層腳本和Java虛擬機命令 。
但願這篇文章可以幫助更多的傳統行業的從業人員轉入互聯網,在互聯網的大舞臺上展示你的才能,最後,附贈一張筆者在互聯網行業裏經過面試識別人才的《Java技能圖譜》,你們能夠根據其中的思惟導圖來深刻學習各項知識點,每一個知識點都須要系統的學習,或者看一本書或者查詢相關的資料,切記要積累知識的廣度的同事也要有必定的深度。