挨踢部落故事匯(34):全棧工程師的自我修煉
原創(chuàng)【51CTO.com原創(chuàng)稿件】 史亞風(fēng)是一個全棧工程師,5年的開發(fā)經(jīng)驗(yàn),積累了很多idea,這些idea從傳統(tǒng)的Java Web到Golang、SVM、hadoop、UI Automation都有涉及,對每一件事情,他都有自己的思考,劍走偏鋒。另外亞風(fēng)是一位兼職的魔術(shù)師,在省賽國賽等魔術(shù)大賽中屢屢獲獎,工作之余也經(jīng)常參加演出,也許是魔術(shù)打開了亞風(fēng)的靈感,如下文中提到的FoolQQ,讓很多開發(fā)者看完源碼后大呼很神奇。
零基礎(chǔ)自學(xué)編程獨(dú)立建站
亞風(fēng)從2013年7月參加工作開始,一晃,快五個年頭了。他初次接觸編程是在2010年的時候,大一上學(xué)期剛結(jié)束,春節(jié),大家忙著串親戚、走朋友。在上海創(chuàng)業(yè)的叔叔回來過年,吃過年夜飯,照例是一次深入的家庭談話。寒暄過后,叔叔提出想建個網(wǎng)站,一開始亞風(fēng)是拒絕的,畢竟才大一,只學(xué)過C語言,沒接觸過Web,當(dāng)時連“Web”這個詞都沒聽過。但是看著叔叔焦急的樣子,亞風(fēng)還是硬著頭皮答應(yīng)下來。他做事是個激進(jìn)派,直到現(xiàn)在也是這樣,別人交代的事情總想盡快落實(shí)。當(dāng)時他家里沒有網(wǎng),第二天就去了附近的網(wǎng)吧,搜搜怎樣建個網(wǎng)站。幸好亞風(fēng)找了一套視頻,講的HTML/CSS/JS基礎(chǔ)?,F(xiàn)在看來當(dāng)時的路很正確,對初學(xué)者而言看視頻跟著做,很容易成功并一步一步建立信心。學(xué)了一周,依葫蘆畫瓢地把網(wǎng)站的幾個主要頁面做出來了,滿滿成就感。當(dāng)然,后面花了一些時間磨合需求,期間也了解了繞不過去的兼容性問題。
但是下一個問題是,后臺程序怎么辦呢?很巧,視頻后面是Java Web開發(fā)的內(nèi)容,從此,也讓他走上了Java工程師的道路?,F(xiàn)在他回想起來真的很神奇,如果視頻后面是PHP他現(xiàn)在大概就是PHP工程師了吧。從未接觸過Java的亞風(fēng),要從Java基礎(chǔ)語法學(xué)到JSP,然后是SQL。周期不短,沒有之前那么順,他叔叔也在催,說實(shí)話很多東西似懂非懂,亞風(fēng)也就學(xué)了20多天,還是硬生生把一個后臺程序做出來了。又過了一個學(xué)期,暑假,直接去了叔叔那兒,基于用友的ERP、CRM做一些軟件的二次開發(fā),在這個過程中他熟悉了Java體系,學(xué)習(xí)了Spring、MyBatis、Maven,前端又系統(tǒng)的學(xué)了一遍,然后是jQuery等等。接下來每逢寒暑假他都會去叔叔那兒幫忙,在這個過程中不斷完善自己,也為后面的就業(yè)積累了實(shí)戰(zhàn)經(jīng)驗(yàn)。
海量大報(bào)文數(shù)據(jù)持久化
畢業(yè),亞風(fēng)來到了一家信息領(lǐng)域技術(shù)研究公司,接觸的第一個項(xiàng)目就是一個高并發(fā)下大報(bào)文數(shù)據(jù)的持久化問題?;赥T/TC做的,但是壓測性能一直上不去??蛻粢髥喂?jié)點(diǎn)18KB報(bào)文持久化達(dá)到5000TPS,他在數(shù)據(jù)庫和代碼優(yōu)化后只達(dá)到單節(jié)點(diǎn)2100TPS,不過很快事情有了轉(zhuǎn)機(jī),一次偶然的實(shí)驗(yàn),亞風(fēng)單獨(dú)壓測TC,發(fā)現(xiàn)不經(jīng)過TT并發(fā)寫入多個TC文件可以達(dá)到5000TPS,而之前使用TT訪問TC的方式只能基于一個TC文件,結(jié)合應(yīng)用“寫多讀少”的特點(diǎn),并考慮分布式架構(gòu),可以設(shè)計(jì)出如下架構(gòu):
如圖,每臺server上有一個基于socket的read server供Web讀取,而寫的部分并發(fā)寫入多個TC文件中?,F(xiàn)在需要解決的是,你需要知道某個報(bào)文存在哪兒了,也就是在哪臺server的哪個文件中,很顯然只需要在數(shù)據(jù)庫中保存server所在的IP信息和文件的名稱就ok了,這個數(shù)據(jù)庫就像hdfs中的namenode一樣。數(shù)據(jù)表應(yīng)該至少包含三個字段,分別是IP、TC文件名稱、報(bào)文的key。這個案例他還記得很清楚,畢竟當(dāng)時花了很長時間做實(shí)驗(yàn),在不改變原有系統(tǒng)架構(gòu)的情況下,這是個好辦法。另外TC真的很強(qiáng)勁而且穩(wěn)定。
基于SVM的驗(yàn)證碼識別
2014年,亞風(fēng)出差北京,待了半年多。給中國電信集團(tuán)做內(nèi)部門戶項(xiàng)目,當(dāng)時要做一個手機(jī)門戶,在和外圍多個系統(tǒng)談接口,進(jìn)展緩慢。于是他自己提出用爬蟲的方式試試,短短一周完成了很多接口,積累了不少爬蟲經(jīng)驗(yàn),不過很多系統(tǒng)都用到了驗(yàn)證碼,因此這是一個繞不過去的關(guān)。亞風(fēng)基于像素比較和SVM做了識別,效果不錯,在人工智能在中國火起來之前接觸了這些,還是很不錯的。為了讓讀者有個感性的認(rèn)識,舉個例子,你經(jīng)??吹叫涡紊尿?yàn)證碼,它們有不同的顏色,甚至?xí)で暮車?yán)重。以數(shù)字“8”為例
計(jì)算機(jī)怎么分別這是8而不是6或者7呢?
我們把“8”放大,可以看到圖像是由一個一個色塊組成的,每個色塊都有一個顏色值,再設(shè)置一個閾值,大于這個閾值的色塊設(shè)置成黑色,反之設(shè)置成白色,就得到了一個黑白的數(shù)字“8”,這叫二值化,接下來從左到右、自上而下,白色的標(biāo)記為0,黑色的標(biāo)記為1,得到一個二進(jìn)制的數(shù)組,這就是SVM的輸入,SVM會自動根據(jù)這些數(shù)據(jù)構(gòu)建多維空間,根據(jù)距離判斷數(shù)字到底是幾。這些數(shù)字組成多維空間的坐標(biāo),這個坐標(biāo)可以看做一個點(diǎn),通過很多張“8”圖片的訓(xùn)練,會形成一個“8”組成的點(diǎn)群,看上去就像銀河系的星河。顯然,判斷某顆星球?qū)儆阢y河系,它必然在銀河系劃分的范圍之內(nèi),否則可能是別的星系。
基于單例對象的定制Ajax框架Fela
日子平靜的來到了2015,亞風(fēng)公司各產(chǎn)品的UI也開始基于UED統(tǒng)一設(shè)計(jì),摒棄了之前Extjs的厚重,這帶來了一個問題,使用最多的分頁表格頁面需要結(jié)合UED提供的CSS重新實(shí)現(xiàn),如果放手不管,每個人都會有自己的實(shí)現(xiàn),又因?yàn)闃邮胶途W(wǎng)上的差別大,無法直接套用某個Ajax框架,因此只能定制。需要一個輕量級的Ajax框架,滿足分頁、查詢、各種事件支持、后臺數(shù)據(jù)解析、表單數(shù)據(jù)打包、以及盡可能的簡單,F(xiàn)ela應(yīng)運(yùn)而生。Fela基于單例對象,和傳統(tǒng)Ajax框架不同,單例對象的使用使得Fela更輕量級,在JavaScript中單例有很多優(yōu)勢,諸如更小的內(nèi)存開銷,加載即創(chuàng)建,方便覆蓋重寫,對象結(jié)構(gòu)清晰以及易于和JSON互轉(zhuǎn)等;
但是這樣做也帶來一些問題,比如一個頁面里只有一個對象,為此,亞風(fēng)使用克隆代替new來生成新的對象,避免了初始化大對象時構(gòu)造方法中的耦合,也使得使用者對大對象得以按需取用,書寫結(jié)構(gòu)清晰的代碼。他設(shè)計(jì)了別名和方法鏈,力求讓一個傳統(tǒng)的表格數(shù)據(jù)頁面、查詢框等等的開發(fā)盡可能簡單。編寫Fela只用了三天時間,不到500行的代碼小而精巧,公司的幾個產(chǎn)品基于此開發(fā),基本做一個頁面前臺只需要簡單的配置,縮短了開發(fā)周期。最重要的是,F(xiàn)ela通過有限的API約束了代碼,使得每個人寫出來的代碼看上去都差不多。它的源碼在這>>。
搭載黑科技的表單工具——如意
2016年起,亞風(fēng)開始完善自己的理論,工作之余擠出時間看了不少書籍,JVM原理、并發(fā)編程、TCP/IP原理等等,也做了一些hadoop技術(shù)棧的學(xué)習(xí),很多東西之前知道,但大都太碎片化,不成體系,讀書讓他理順了他們的關(guān)系。在IT行業(yè),知道的越多,就越發(fā)覺得自己還很渺小,反倒是讀書少時,更容易自滿。根據(jù)項(xiàng)目要求,這一年他花了四分之一的時間獨(dú)立做了一個表單平臺——如意。如意相對亞風(fēng)以前的作品可謂是大制作,為此他還拍攝了一部宣傳片。如意有很多特性,全控件支持、首創(chuàng)可視化業(yè)務(wù)邏輯設(shè)計(jì)、多數(shù)據(jù)源、多租戶、在線JS編程等等。2017年10月份,亞風(fēng)用這個項(xiàng)目參加了51CTO開發(fā)者大賽,很幸運(yùn),如意已經(jīng)入圍了,希望后面它能取得好成績。這一年,他被任命為公司軟件實(shí)驗(yàn)室的執(zhí)行主任,負(fù)責(zé)創(chuàng)新型項(xiàng)目的研發(fā)、以及疑難問題的解決。
讓計(jì)算機(jī)識別自己!
亞風(fēng)參與了很多新興項(xiàng)目,如GIS、聲紋時長識別、問答機(jī)器人等等。在GIS項(xiàng)目的開發(fā)過程中他提出了一個基于讓計(jì)算機(jī)通過圖像識別來操作自己的屏幕的方法論,這就好像在計(jì)算機(jī)前面擺了個鏡子,這樣它就可以看到自己,從而操作自己。這為項(xiàng)目節(jié)省了不少人工的工作量,主要用于自動化的批量幾何圖形繪制。后來把它應(yīng)用在操作QQ上,由于目前讀寫QQ的機(jī)器人都是基于爬蟲分析SmartQQ報(bào)文來實(shí)現(xiàn)的,然而SmartQQ騰訊已經(jīng)不再維護(hù),其HTTP服務(wù)端經(jīng)常不可用,且經(jīng)常需要不定時的重啟,于是基于圖像識別,亞風(fēng)開源了FoolQQ。由于計(jì)算機(jī)給自己截圖的輸出圖像是高清的,意味著開發(fā)者可以直接基于像素比對來實(shí)現(xiàn)圖像比對。判斷一個圖像中是否包含某個子圖像就會像下面這樣簡單:
- public static boolean isEqual(int x, int y, BufferedImage image, BufferedImage point) {
- int pointW = point.getWidth();
- int pointY = point.getHeight();
- for (int m = 0; m < pointW; m++)
- for (int n = 0; n < pointY; n++) {
- if (image.getRGB(x + m, y + n) != point.getRGB(m, n)) {
- return false;
- }
- }
- return true;
- }
很幸運(yùn),這個項(xiàng)目得到了一些個人開發(fā)者的捐助,也讓亞風(fēng)有了維護(hù)下去的動力。
【寫在最后】
2017年很快就結(jié)束了,前面是亞風(fēng)這些年一些代表性的研發(fā),篇幅有限,還有很多例子不說了。程序員的職場很公平,你的待遇幾乎和你的知識成正比,前提是你真的掌握。最后總結(jié)一些研發(fā)的經(jīng)驗(yàn):
1.架構(gòu)永遠(yuǎn)是第一位的,如果你的性能和目標(biāo)差很遠(yuǎn),請不要嘗試細(xì)節(jié)優(yōu)化;
2.不要重復(fù)造輪子,關(guān)注IT領(lǐng)域的動態(tài),經(jīng)常訪問51CTO這樣的網(wǎng)站,知識的廣度可以讓你省不少事;
3.如果非要造輪子,設(shè)計(jì)則顯得尤為重要,一定要站在用戶角度看問題,要知道你的用戶是誰;
4.個人技術(shù)提升和日常工作有時候是沖突的,找到雙贏的點(diǎn)很重要,優(yōu)秀的員工應(yīng)該是一個合作者的心態(tài);
亞風(fēng)和朋友常說,進(jìn)了這個圈子就是一場看不到終點(diǎn)的修行,最好的結(jié)果是,你一直在前行的路上、在離終點(diǎn)越來越近的路上,這就夠了。
如果你也愿意分享你的故事,請加51CTO開發(fā)者QQ交流群 669593076聯(lián)系群主小官,期待你精彩的故事!
【51CTO原創(chuàng)稿件,合作站點(diǎn)轉(zhuǎn)載請注明原文作者和出處為51CTO.com】