第一天
上午九點到下午三點左右,入職活動結束,被帶到工位。
-
安裝環境,
- jdk 1.8 64位
- maven這邊工程通過maven構建,推薦使用maven3以上版本
- IDEA 下載。idea自帶maven插件,但需要在默認的settings.XML文件中添加內部的maven遠程倉庫地址
- git下載安裝,代碼寄存在gitlab。
- 所有安裝環境部署完畢之后,了解工具的使用
-
熟悉團隊的各位成員,相互認識和學習
- 注意事項:
- 每周三晚上八點之前提交周報:寫這一周的學習內容,遇到的問題,解決的方法,什么收獲
- 每天的學習中遇到的問題記下來,晚上找時間向師傅請教。做到當天的問題當天解決。
第二天
- 學習阿里的代碼編程規范
- 根據規范中總結的經驗,結合自己之前編碼中的個人習慣進行反思,發現自己存在之前存在很多編碼不規范的地方,對這些地方進行重點總結(規范內容較多,后續還會繼續看)
- 了解spring boot。由于內網資料看不到,自己在外網搜一下相關教程,并使用spring boot搭建一個hello world程序。
第三天
熟悉信用證基本概念,了解國內跟單流程
-
java基礎復習:
-
jvm類加載機制
- 類加載器
類加載器類型 名稱 負責加載 加載的類 Bootstrap ClassLoader 引導類加載器 核心java class 所有java.開頭的類 Extension ClassLoader 擴展類加載器 擴展的java class javax.開頭的、放在ext目錄下面的 System ClassLoader 系統類加載器 用戶程序自身的class 系統中配置的環境變量classpath路徑下面的類 - 類加載機制
- 全盤負責:當一個classLoader加載一個類的時候,該class所依賴的所有class 也由這個classloader負責載入。除非是顯示的使用另一個classLoader載入。
- 雙親委托:先讓父類的加載器加載,如果父類加載器無法加載的話,再該類的加載器進行加載。
垃圾回收
內存模型
基礎集合類
jdk 8 新特性
-
servlet
- 生命周期:
- 初始化:servlet容器會在啟動時初始化一些servlet,如果在web.xml中的servlet標簽之間加入load-startup 1
- 生命周期:
-
-
maven工具學習,重點關注如下問題
-
如何解決jar沖突
在項目中的pom文件中將沖突依賴排除,具體寫法:比如我們要講一個依賴中的相應jar包排除
<dependency> <groupId>com.xxx.xx</groupId> <artifactId>xxx</artifactId> <version>x</version> <exclusions> <exclusion> <artifactId>com.springsource.slf4j.org.apache.commons.logging</artifactId> <groupId>org.slf4j</groupId> </exclusion> </exclusions> </dependency>
?
?
-
第四天
-
START
- 之前有過java web開發經驗,對于servlet的生命周期以及基本開發過程有了解,但對于filter和listener了解不是很深。對這些盲點進行逐一攻破
- 對web.xml的所有常用的配置深入掌握(規范、原理),對不常用的標簽要有所了解
- 能夠準確描述出servlet、filter、listener各自發揮的作用、生命周期、加載順序等
- 使用filter、servlet、listener編寫一個動態網頁小demo
- filter servlet listener:
- 初始化順序:listener -》filter -》servlet
- 銷毀順序:servlet- 》filter-》listener(和初始化順序相反)
-
web.xml
?
-
filter
- 定義:過濾器,對web服務器所管理的web資源:例如jsp、servlet、靜態文件等進行攔截。例如實現URL級別的權限訪問、過濾敏感詞匯
- 主要用于對
httpServletRequest
進行預處理,也可以對httpServletResponse
進行后處理。 - 完整流程:FIlter對用戶請求預處理--》servlet對請求進行做出相應--》FIlter在對相應進行后處理
filter鏈:在一個web應用中,可能會有多個filter,這些filter 組合起來稱作filter鏈。filter的執行順序根據filter在web.xml中定義的順序一致
filer 生命周期:和servlet一樣,filter的創建和銷毀由web容器負責,當web容器啟動時,將創建filter實例對象,調用init方法。filer對象只會創建一次,故filer是單例的。在多線程情況下會存在線程安全性問題,故不要在file類中定義屬性變量,最好是無狀態的,如果非要使用,一定要使用線程安全的類。比如并發包中的類。
filer的四種攔截方式:REQUEST 、FORWORD、 INCLUDE、ERROE
REQUEST:直接訪問目標資源
FORWORD:轉發
INCLUDE:例如:<jsp:include>
-
ERROR:web.xml中配置error-page時
可以在
filter-mapping
中添加多個dispatch子元素 filer用在哪:權限檢查、編碼過濾
如何使用filer:實現javax.servlet.Filer接口,并覆蓋doFilter方法
public class MyFilfer implements Filer{ @Override public void doFilter(ServletRequest srep, ServletResponse sresp, FilterChain fc) { //TODO } }
在web.xml中添加filter
<filter> <filter-name>myFilter</filter-name> <filer-class>MyFilfer</filer-class> </filter> <filter-mapping> <filter-name>myFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
?
-
servlet
- 生命周期:servlet實例的創建有兩個時機:
- 客戶端第一次請求某個servlet時,系統創建servlet的實例
- web應用啟動時立刻創建servlet 實例,需要在web.xml中配置
<load-on-startup>1(或大于1)</load-on-startup>
- 容器中只存在一個servlet實例。單例多線程的。故也是線程不安全
-
Demo :使用servlet 和 filter 實現登錄小程序
- filter 對用戶請求進行攔截,驗證是否登錄。如果session有用戶信息,則放過。否則redirect到登錄頁面
- servlet 對登錄請求進行處理,將用戶信息保存到session中
git分支地址:http://gitlab.alibaba-inc.com/shixu.sx/user_login/tree/master
-
問題解決
JVM性能調優監控常用命令
-
jps :列出jvm中正在運行的進程信息
-q 不輸出類名、Jar名和傳入main方法的參數 -m 輸出傳入main方法的參數 -l 輸出main類或Jar的全限名 -v 輸出傳入JVM的參數 shixu.sx@$ jps -l 9520 sun.tools.jps.Jps 17924 org.apache.catalina.startup.Bootstrap 9812 org.jetbrains.jps.cmdline.Launcher 14184 14440 org.jetbrains.idea.maven.server.RemoteMavenServer
-
jstack: 主要用來查看某個java線程堆棧信息
場景:找出某個java 進程中最耗費cpu的java線程,并定位堆棧信息
方案:
-
首先找出該java進程的進程id,比如要找bootstrap進程,
- 在windows環境下,命令行輸入:
jps | findstr "bootstrap"
- linux環境下,輸入:
jps | grep "bootstrap"
- 在windows環境下,命令行輸入:
-
根據進程id,找出該進程內最耗費資源的線程信息
命令行輸入:
top -Hp 進程id
, 然后根據列出的線程信息找到time最長的線程id-
將線程id轉化為十六進制,然后在命令行輸入
jstack 進程id | grep 線程id對應的十六進制數
,根據打印出來的堆棧信息可以知道是哪個線程的問題
-
-
-
jmap: 用來查看堆內存使用情況
使用
jmap -heap pid
查看進程堆內存使用情況。 -
jstat:jvm統計監測工具
S0C、S1C、S0U、S1U:Survivor 0/1區容量(Capacity)和使用量(Used) EC、EU:Eden區容量和使用量 OC、OU:年老代容量和使用量 PC、PU:永久代容量和使用量 YGC、YGT:年輕代GC次數和GC耗時 FGC、FGCT:Full GC次數和Full GC耗時 GCT:GC總耗時 堆內存 = 年輕代 + 年老代 + 永久代 年輕代 = Eden區 + 兩個Survivor區(From和To)
查看網絡端口命令:
-
windows:
- 查看所有端口占用:
netstat -ano
- 查看指定端口占用:
netstat -ano | findstr "端口號"
- 查看所有端口占用:
-
linux:
- 查看所有端口占用:
netstat -anp
- 查看指定端口占用:
netstat -anp | grep "端口號"
- 查看所有端口占用:
?
第五天
-
9點半到10點半,學習代碼規約
-
問題:
-
規約中一條:避免在有鎖的代碼塊中調用RPC方法,為什么?
A:一般情況下,鎖的粒度要越小越好,調用RPC本身就是一種粗粒度的處理,所以不建議放在同步代碼塊中。其次,RPC遠程調用不確定性太多,比如運行時間長、超時、事務回滾等,如果RPC方法需要運行很長時間,那么該鎖會一直被占用,導致其他線程等待時間過長。
-
-
-
jvm
- jvm內存區域
- pc寄存器:程序計數器,線程私有,保存當前線程執行的字節碼地址,唯一一個沒有規定任何OOM的區域
- 虛擬機棧:線程私有,每個線程被創建時都會同時創建一個對應的虛擬機棧,棧中存放著棧幀,每一個棧幀對應一個方法調用。棧幀中保存局部變量表、操作數棧、動態鏈接等
- 方法區:線程共享,大小可以動態調整,主要存放:類信息(名稱、方法、字段等元信息)、靜態變量。(注:jdk 8 之后方法區已經不存在,取而代之的是metaspace,一塊本地內存,由于類的元數據分配在本地內存中,元空間的最大可分配空間就是系統可用內存空間。)
- java堆:對象和數組都在這里分配空間。線程共享。垃圾回收的主要區域
- 垃圾回收算法回顧
- 遇到的問題
- 在JVM規范中規定,如果線程執行的是非native方法,則程序計數器中保存的是當前需要執行的指令的地址;如果線程執行的是native方法,則程序計數器中的值是undefined。為什么是undefined?如果是undefined的話,那么當cpu再次切換執行到該本地方法是,怎么找到要代碼行的地址?
- ?
-
maven 定義和相關命令回顧
項目管理和構建自動化工具
maven倉庫:
本地倉庫:第一次運行maven構建,會自動下載所有依賴的jar文件到本地倉庫中。它避免了每次構建都引用遠程倉庫的依賴文件
中央倉庫:maven社區提供,不需要配置。
遠程倉庫:如果maven在中央倉庫也找不到依賴的文件,會從用戶提供的遠成倉庫中查找
maven依賴搜索順序:1. 本地倉庫 2. 中央倉庫 3. 遠程倉庫 4. 都找不到,報錯編譯失敗
創建工程:
命令:
mvn archetype:generate -DgroupId=com.companyname.helloworld -DartifactId=helloworld Dpackage=com.company.helloworld -Dversion=1.0-SNAPSHOT
- 構建程序:
命令:
mvn package
- 安裝工程:
命令:
mvn install
(安裝到本地后,在本地倉庫會有該工程,其他的項目可以依賴該工程)
- 生成文檔
命令:
mvn site
-
spring
控制翻轉和依賴注入:
bean作用域
bean生命周期
依賴注入方式
基于set方法
-
基于構造方法
(二者優劣)
AOP原理,代理模式(動態代理cglib和jdk代理區別)
事務管理(編程式事務和聲明式事務)
demo小程序
-
總結:
- 今天主要是對spring的基礎知識和核心概念,以及常用的配置等進行了復習。回顧過程中發現,很多知識點停留在會用的水平,對底層實現不了解。比如注解這一塊,jvm在加載類的時候遇到注解該怎么處理、注解是如何引入相應的功能的,對這些問題了解以后,還要思考如何自己定義一個注解。周末要對這一點進行深入剖析。同時對于spring boot進行系統學習。
第六天
-
上午和師傅以及徐瀟師兄一起探討了在瀏覽器輸入
www.alibaba.com
,之后發生的一切,結合自己對這個問題的認識,發現自己對阿里整個網絡體系以及服務架構了解很不夠。- 域名解析:瀏覽器dns緩存、本地dns緩存、本地host文件、請求根dns服務器解析(查詢dns根域,自頂向下進行查詢)
- http連接:TCP三次握手,建立連接,客戶端與服務器
- 到達阿里負載均衡層(F5或者LVS,F5是硬件實現負載均衡,LVS針對傳輸層TCP\IP)
- VIPserver\vip
- 統一接入(HTTPS解密成HTTP,這是一個CPU密集型任務,在這里進行處理可以降低下游服務器壓力)
- Tengin\apach\NGINX(負載均衡,應用層負載均衡)
- 感想:對阿里的整體網絡架構了解還很不夠,比如VIP和VIPserver在其中的具體作用,CDN等如何實現加速,怎么更快解析DNS,如果找到一條更短的路由,等等,這些點以后要一一弄明白。
-
spring boot start
今天學習了spring boot,看了springboot的一些視頻,對spring boot有了一定的初步的認識,初步了解了spring boot的一些基本理念,如可以替換之前給予xml的配置,可以選用@configuration 和application.properties和application.yml來進行配置spring bean。了解到了spring starters ,通過這個可以減少maven依賴中的版本不匹配問題。
spring boot的學習中,通過運行demo,加深了對spring boot的理解,demo中集成了JPA。接下來會將springboot中加入其它start比如:mybatis、tddl等,進行學習。
感想:基于之前學習spring的基礎,spring boot的學習整體順利。但目前對spring boot的理解更多的是在spring boot的使用上,并理解相關的看到的一些注解,對spring boot的一些原理的還需要后面繼續深入。
- 三種啟動方式:
- main方法中啟動
- mvn:spring-boot:run
- mvn install 然后:java -jar 。。
- controller的使用
- @Controller:處理http請求
- @RestController = @Controller + @ResponseBody:Spring4之后新加的注解,原來返回json需要@ResponseBody配合@Controller
- @RequestMapping:配置url映射
- 獲取參數
- @PathVariable:獲取URL中的數據
- @RequestParam:獲取請求參數中的值
- @GetMapping@PostMapping:組合注解
- 三種啟動方式:
第七天
- 今天主要對HSF進行了學習。
在系統越來越復雜的情況下,傳統的架構會存在如下的問題:
- 各個模塊耦合度過高,導致升級更新困難,一處變處處變
- 擴展性差
- 團隊開發困難
- 分布式部署非常困難
而HSF是一個遠程RPC調用框架。面向服務,降低耦合性
- HSF:
通過配置provider和consumer的bean就ok。
provider暴露自己提供服務的接口,consumer根據接口進行調用。
返回的對象序列化后,通過網絡傳輸。
感想:關于hsf,今天學習的內容主要是對基本原理和基本概念進行學習,然后運行了一個小demo,對服務的發布和服務的消費進行了簡單的實現。接下來還會更深入的學習。
- OCR識別的結果亂碼問題:
針對ocr識別的結果中文亂碼的問題,我進行了單元測試,最后通過將亂碼內容用
iso-8859-1
編碼方式轉化為字節,然后再用utf-8
解碼,解決了這個問題。iso-8859-1
編碼方式是不支持中文的,所以當對含有中文的內容使用這種編碼方式進行編碼的時候,再次解碼肯定會出現亂碼。
因為java本身是跨平臺的語言, 亂碼問題在java開發中非常常見,比如java的IO操作、數據庫、內存、jav web等多種場景,而最終的問題就是出現在字節和字符的轉換上面。
- swift 報文格式
- AutoConfig
- SchedulerX
第八天
- 繼續學習HSF框架
通過看文檔,理解關于服務提供和服務的消費過程:
- 服務提供者將提供的服務和自己的IP注冊至注冊中心ConfigServer
- ConfigServer會將服務提供者的IP列表推送至服務消費者
- 服務消費者發起調用時,直接從ConfigServer推送過來的服務提供者的IP列表中選擇一個IP發起遠程調用
標準的service方式RPC:
- service 定義:基于OSGI的service定義方式
- 底層通信方式:萬變不離tcp\ip ,io方面使用異步NIO,并使用長連接
Provider和Consumer的啟動和處理過程
- 初識TDDL
問題:單一數據庫無法滿足性能要求
- 數據切分
- 讀寫分離
- 系統容災和主備切換以及運維等問題
TDDL提供用戶訪問和數據庫之前的隔離,實現透明操作
1.直接提供分庫分表,讀寫分離、主從備份等解決數據庫擴展問題的功能.
2.基于配置模型構建的包括數據庫在線擴容、準實時數據同步服務、運維平臺等支撐系統。
核心設計:
- SQL解釋器 :語法樹、查詢匹配規則、分庫分表
- 查詢優化器
- 執行器
HSF原理
HSF架構

HSF服務架構主要幾塊組成:
- ConfigServer: 用于服務的注冊與發現,server通過向ConfigServer注冊自己的服務,會在ConfigServer注冊自己的服務信息,如服務地址,發布的接口,服務版本等內容。client端可以從ConfigServer訂閱自己想要的服務,之后ConfigServer就會把訂閱的服務的信息發送給client,之后client和server就可以建立連接,進行RPC調用了。
- Diamond: 主要用于一些動態的配置內容,例如ConfigServer的地址,路由匹配,動態負載等配置。這些配置內容,可以通過在HSF服務治理網站上進行配置。
- Redis:負責存儲HSF的元數據,consumer和provider隔一段時間會將調用信息進行上報,同時存儲了應用名和服務映射等信息。
服務注冊發現流程

- Provider從Diamond中獲取Configserver的地址、類型等信息。
- Provider在Configserver上注冊自己的IP地址、端口號、服務名、版本號、Group號信息。
- Provider定期將元數據(調用次數、服務狀態等等)上報給Redis,用于服務治理。
- Consumer從Diamond中獲取Configserver的地址、類型等信息。
- Consumer根據服務名、版本號、Group號信息向Configserver訂閱Provider服務。
- Consumer定期將元數據(調用次數、服務狀態等等)上報給Redis,用于服務治理。
- Configserver推送Provider的IP地址列表給Consumer。
- Consumer選擇一個IP地址,與該Provider建立長連接、通過RpcRequest和RpcResponse進行調用。