一面
1带欢、自我介紹、自己做的項目和技術領域
開放題
2烤惊、項目中的監(jiān)控:那個監(jiān)控指標常見的有哪些乔煞?
答:CPU、內(nèi)存柒室、IO 等等渡贾。建議下載個nmon工具,里面有各個指標伦泥。
數(shù)據(jù)庫:Mysql(緩存命中剥啤、索引、單條SQL性能不脯、數(shù)據(jù)庫線程數(shù)府怯、數(shù)據(jù)池連接數(shù))
中間件:1.消息2、負載均衡3防楷、緩存(包括線程數(shù)牺丙、連接數(shù)、日志)复局。
網(wǎng)絡: 吞吐量冲簿、吞吐率
應用: jvm內(nèi)存、日志亿昏、Full GC頻率
3峦剔、微服務涉及到的技術以及需要注意的問題有哪些?
4角钩、注冊中心你了解了哪些吝沫?
答:Consul 呻澜、Eureka、ZooKeeper
5惨险、consul 的可靠性你了解嗎羹幸?
6、consul 的機制你有沒有具體深入過辫愉?有沒有和其他的注冊中心對比過栅受?
7、項目用 Spring 比較多恭朗,有沒有了解 Spring 的原理屏镊?AOP 和 IOC 的原理
答:(1). IoC(Inversion of Control)是指容器控制程序?qū)ο笾g的關系,而不是傳統(tǒng)實現(xiàn)中痰腮,由程序代碼直接操控闸衫。控制權由應用代碼中轉到了外部容器诽嘉,控制權的轉移是所謂反轉。 對于Spring而言弟翘,就是由Spring來控制對象的生命周期和對象之間的關系虫腋;IoC還有另外一個名字——“依賴注入(Dependency Injection)”。從名字上理解稀余,所謂依賴注入悦冀,即組件之間的依賴關系由容器在運行期決定,即由容器動態(tài)地將某種依賴關系注入到組件之中睛琳。
(2). 在Spring的工作方式中盒蟆,所有的類都會在spring容器中登記,告訴spring這是個什么東西师骗,你需要什么東西历等,然后spring會在系統(tǒng)運行到適當?shù)臅r候,把你要的東西主動給你辟癌,同時也把你交給其他需要你的東西寒屯。所有的類的創(chuàng)建、銷毀都由 spring來控制黍少,也就是說控制對象生存周期的不再是引用它的對象寡夹,而是spring。對于某個具體的對象而言厂置,以前是它控制其他對象菩掏,現(xiàn)在是所有對象都被spring控制,所以這叫控制反轉昵济。
(3). 在系統(tǒng)運行中智绸,動態(tài)的向某個對象提供它所需要的其他對象野揪。
(4). 依賴注入的思想是通過反射機制實現(xiàn)的,在實例化一個類時传于,它通過反射調(diào)用類中set方法將事先保存在HashMap中的類屬性注入到類中囱挑。 總而言之,在傳統(tǒng)的對象創(chuàng)建方式中沼溜,通常由調(diào)用者來創(chuàng)建被調(diào)用者的實例平挑,而在Spring中創(chuàng)建被調(diào)用者的工作由Spring來完成,然后注入調(diào)用者系草,即所謂的依賴注入or控制反轉通熄。 注入方式有兩種:依賴注入和設置注入; IoC的優(yōu)點:降低了組件之間的耦合找都,降低了業(yè)務對象之間替換的復雜性唇辨,使之能夠靈活的管理對象。
AOP(Aspect Oriented Programming)
(1). AOP面向方面編程基于IoC能耻,是對OOP的有益補充赏枚;
(2). AOP利用一種稱為“橫切”的技術,剖解開封裝的對象內(nèi)部晓猛,并將那些影響了 多個類的公共行為封裝到一個可重用模塊饿幅,并將其名為“Aspect”,即方面戒职。所謂“方面”栗恩,簡單地說,就是將那些與業(yè)務無關洪燥,卻為業(yè)務模塊所共同調(diào)用的 邏輯或責任封裝起來磕秤,比如日志記錄,便于減少系統(tǒng)的重復代碼捧韵,降低模塊間的耦合度市咆,并有利于未來的可操作性和可維護性。
(3). AOP代表的是一個橫向的關 系纫版,將“對象”比作一個空心的圓柱體床绪,其中封裝的是對象的屬性和行為;則面向方面編程的方法其弊,就是將這個圓柱體以切面形式剖開癞己,選擇性的提供業(yè)務邏輯。而 剖開的切面梭伐,也就是所謂的“方面”了痹雅。然后它又以巧奪天功的妙手將這些剖開的切面復原,不留痕跡糊识,但完成了效果绩社。
(4). 實現(xiàn)AOP的技術摔蓝,主要分為兩大類:一是采用動態(tài)代理技術,利用截取消息的方式愉耙,對該消息進行裝飾贮尉,以取代原有對象行為的執(zhí)行;二是采用靜態(tài)織入的方式朴沿,引入特定的語法創(chuàng)建“方面”猜谚,從而使得編譯器可以在編譯期間織入有關“方面”的代碼。
(5). Spring實現(xiàn)AOP:JDK動態(tài)代理和CGLIB代理 JDK動態(tài)代理:其代理對象必須是某個接口的實現(xiàn)赌渣,它是通過在運行期間創(chuàng)建一個接口的實現(xiàn)類來完成對目標對象的代理魏铅;其核心的兩個類是InvocationHandler和Proxy。 CGLIB代理:實現(xiàn)原理類似于JDK動態(tài)代理坚芜,只是它在運行期間生成的代理對象是針對目標類擴展的子類览芳。CGLIB是高效的代碼生成包,底層是依靠ASM(開源的java字節(jié)碼編輯類庫)操作字節(jié)碼實現(xiàn)的鸿竖,性能比JDK強沧竟;需要引入包asm.jar和cglib.jar。 使用AspectJ注入式切面和@AspectJ注解驅(qū)的切面實際上底層也是通過動態(tài)代理實現(xiàn)的缚忧。
(6). AOP使用場景:
Authentication 權限檢查
Caching 緩存
Context passing 內(nèi)容傳遞
Error handling 錯誤處理
Lazy loading 延遲加載
Debugging 調(diào)試
logging, tracing, profiling and monitoring 日志記錄屯仗,跟蹤,優(yōu)化搔谴,校準
Performance optimization 性能優(yōu)化,效率檢查
Persistence 持久化
Resource pooling 資源池
Synchronization 同步
Transactions 事務管理
另外Filter的實現(xiàn)和struts2的攔截器的實現(xiàn)都是AOP思想的體現(xiàn)桩撮。
8敦第、Spring Boot除了自動配置,相比傳統(tǒng)的 Spring 有什么其他的區(qū)別店量?
為Spring 生態(tài)系統(tǒng)的開發(fā)提供一種更簡潔的方式芜果,提供了很多非功能性特性,例如:嵌入式 Server融师,Security右钾,統(tǒng)計,健康檢查旱爆,外部配置等等舀射,主要體現(xiàn)在以下幾點:
1.Spring Boot可以建立獨立的Spring應用程序;
2.內(nèi)嵌了如Tomcat怀伦,Jetty和Undertow這樣的容器脆烟,也就是說可以直接跑起來,用不著再做部署工作了房待;
3.無需再像Spring那樣搞一堆繁瑣的xml文件的配置邢羔;
4.可以自動配置Spring驼抹。SpringBoot將原有的XML配置改為Java配置,將bean注入改為使用注解注入的方式(@Autowire)拜鹤,并將多個xml框冀、properties配置濃縮在一個appliaction.yml配置文件中。
5.提供了一些現(xiàn)有的功能敏簿,如量度工具明也,表單數(shù)據(jù)驗證以及一些外部配置這樣的一些第三方功能;
6.整合常用依賴(開發(fā)庫极谊,例如spring-webmvc诡右、jackson-json、validation-api和tomcat等)轻猖,提供的POM可以簡化Maven的配置帆吻。當我們引入核心依賴時,SpringBoot會自引入其他依賴咙边。
9猜煮、Spring Cloud 有了解多少?
Spring Cloud是一系列框架的有序集合败许。它利用Spring Boot的開發(fā)便利性巧妙地簡化了分布式系統(tǒng)基礎設施的開發(fā)王带,如服務發(fā)現(xiàn)注冊、配置中心市殷、消息總線愕撰、負載均衡、斷路器醋寝、數(shù)據(jù)監(jiān)控等搞挣,都可以用Spring Boot的開發(fā)風格做到一鍵啟動和部署。Spring Cloud并沒有重復制造輪子音羞,它只是將目前各家公司開發(fā)的比較成熟囱桨、經(jīng)得起實際考驗的服務框架組合起來,通過Spring Boot風格進行再封裝屏蔽掉了復雜的配置和實現(xiàn)原理嗅绰,最終給開發(fā)者留出了一套簡單易懂舍肠、易部署和易維護的分布式系統(tǒng)開發(fā)工具包。
10窘面、Spring Bean 的生命周期
一個Bean從創(chuàng)建到銷毀翠语,如果是用BeanFactory來生成,管理Bean的話
Spring上下文中的Bean也類似,如下
1财边、實例化一個Bean--也就是我們常說的new啡专;
2、按照Spring上下文對實例化的Bean進行配置--也就是IOC注入制圈;
3们童、如果這個Bean已經(jīng)實現(xiàn)了BeanNameAware接口畔况,會調(diào)用它實現(xiàn)的setBeanName(String)方法,此處傳遞的就是Spring配置文件中Bean的id值
4慧库、如果這個Bean已經(jīng)實現(xiàn)了BeanFactoryAware接口跷跪,會調(diào)用它實現(xiàn)的setBeanFactory(setBeanFactory(BeanFactory)傳遞的是Spring工廠自身(可以用這個方式來獲取其它Bean,只需在Spring配置文件中配置一個普通的Bean就可以)齐板;
5吵瞻、如果這個Bean已經(jīng)實現(xiàn)了ApplicationContextAware接口,會調(diào)用setApplicationContext(ApplicationContext)方法甘磨,傳入Spring上下文(同樣這個方式也可以實現(xiàn)步驟4的內(nèi)容橡羞,但比4更好,因為ApplicationContext是BeanFactory的子接口济舆,有更多的實現(xiàn)方法)卿泽;
6、如果這個Bean關聯(lián)了BeanPostProcessor接口滋觉,將會調(diào)用postProcessBeforeInitialization(Object obj, String s)方法签夭,BeanPostProcessor經(jīng)常被用作是Bean內(nèi)容的更改,并且由于這個是在Bean初始化結束時調(diào)用那個的方法椎侠,也可以被應用于內(nèi)存或緩存技術第租;
7、如果Bean在Spring配置文件中配置了init-method屬性會自動調(diào)用其配置的初始化方法我纪。
8慎宾、如果這個Bean關聯(lián)了BeanPostProcessor接口,將會調(diào)用postProcessAfterInitialization(Object obj, String s)方法浅悉、璧诵;
注:以上工作完成以后就可以應用這個Bean了,那這個Bean是一個Singleton的仇冯,所以一般情況下我們調(diào)用同一個id的Bean會是在內(nèi)容地址相同的實例,當然在Spring配置文件中也可以配置非Singleton族操,這里我們不做贅述苛坚。
9、當Bean不再需要時色难,會經(jīng)過清理階段泼舱,如果Bean實現(xiàn)了DisposableBean這個接口,會調(diào)用那個其實現(xiàn)的destroy()方法枷莉;
10娇昙、最后,如果這個Bean的Spring配置中配置了destroy-method屬性笤妙,會自動調(diào)用其配置的銷毀方法冒掌。
另外我們這里描述的是應用Spring上下文Bean的生命周期噪裕,如果應用Spring的工廠也就是BeanFactory的話去掉第5步就Ok了
11、HashMap 和 hashTable 區(qū)別股毫?
區(qū)別:Hashtable是線程安全的膳音,效率比較低
Hashtable既不支持Null key也不支持Null value。Hashtable的put()方法的注釋中有說明
Hashtable默認的初始大小為11铃诬,之后每次擴充祭陷,容量變?yōu)樵瓉淼?n+1。
HashMap默認的初始化大小為16趣席。之后每次擴充兵志,容量變?yōu)樵瓉淼?倍
Hashtable在計算元素的位置時需要進行一次除法運算,而除法運算是比較耗時的
HashMap為了提高計算效率宣肚,將哈希表的大小固定為了2的冪想罕,這樣在取模預算時,不需要做除法钉寝,只需要做位運算弧呐。位運算比除法的效率要高很多。
HashMap是繼承自AbstractMap類嵌纲,而HashTable是繼承自Dictionary類俘枫。不過它們都實現(xiàn)了同時實現(xiàn)了map、Cloneable(可復制)逮走、Serializable(可序列化)這三個接口
12鸠蚪、Object 的 hashcode 方法重寫了,equals 方法要不要改师溅?
不需要茅信,Ojbect類中有兩個方法equals、hashCode墓臭,這兩個方法都是用來比較兩個對象是否相等的蘸鲸,如果兩個對象相等(equal),那么必須擁有相同 的哈希碼(hash code)
即使兩個對象有相同的哈希值(hash code)窿锉,他們不一定相等
重寫equals()方法就必須重寫hashCode()酌摇,但重寫hashcode方法不一定要重寫equals方法
13、Hashmap 線程不安全的出現(xiàn)場景
用ConcurrentHashMap 線程安全
多線程處理時hashmap線程不安全
首先hashmap里這個size沒有用volatile關鍵字修飾嗡载,代表這不是一個內(nèi)存可見的變量窑多,線程操作數(shù)據(jù)的時候一般是從主存拷貝一個變量副本進行操作,操作完成過后在把size的值寫回到主存size的
線程不安全問題應該屬于并發(fā)問題之一的洼滚,屬于相對高級的問題了埂息。這個時候的問題已經(jīng)不僅僅局限于代碼層面了,很多時候需要結合JVM一起分析了
14、線上服務 CPU 很高該怎么做千康?有哪些措施可以找到問題
定位出現(xiàn)問題的堆棧信息排查具體問題
1享幽、top命令:Linux命令“娠酰可以查看實時的CPU使用情況琉闪。也可以查看最近一段時間的CPU使用情況。
2砸彬、ps命令: Linux命令颠毙。強大的進程狀態(tài)監(jiān)控命令∩暗铮可以查看進程以及進程中線程的當前CPU使用情況蛀蜜。屬于當前狀態(tài)的采樣數(shù)據(jù)。
3增蹭、jstack: Java提供的命令滴某。可以查看某個進程的當前線程棧運行情況滋迈。根據(jù)這個命令的輸出可以定位某個進程的所有線程的當前運行狀態(tài)霎奢、運行代碼,以及是否死鎖等等饼灿。
4幕侠、pstack:Linux命令“恚可以查看某個進程的當前線程棧運行情況
15晤硕、JDK 中有哪幾個線程池?順帶把線程池講了個遍
JUC提供了調(diào)度器對象Executors來創(chuàng)建線程池庇忌,可創(chuàng)建的線程池有四種
1舞箍、newFixedThreadPool創(chuàng)建一個指定工作線程數(shù)量的線程池。每當提交一個任務就創(chuàng)建一個工作線程皆疹,如果工作線程數(shù)量達到線程池初始的最大數(shù)疏橄,則將提交的任務存入到池隊列中。
2略就、newCachedThreadPool創(chuàng)建一個可緩存的線程池捎迫。這種類型的線程池特點是:
1).工作線程的創(chuàng)建數(shù)量幾乎沒有限制(其實也有限制的,數(shù)目為Interger. MAX_VALUE), 這樣可靈活的往線程池中添加線程。
2).如果長時間沒有往線程池中提交任務残制,即如果工作線程空閑了指定的時間(默認為1分鐘),則該工作線程將自動終止掖疮。終止后初茶,如果你又提交了新的任務,則線程池重新創(chuàng)建一個工作線程。
3恼布、newSingleThreadExecutor創(chuàng)建一個單線程化的Executor螺戳,即只創(chuàng)建唯一的工作者線程來執(zhí)行任務,如果這個線程異常結束折汞,會有另一個取代它倔幼,保證順序執(zhí)行(我覺得這點是它的特色)。單工作線程最大的特點是可保證順序地執(zhí)行各個任務爽待,并且在任意給定的時間不會有多個線程是活動的 损同。
4、newScheduleThreadPool創(chuàng)建一個定長的線程池鸟款,而且支持定時的以及周期性的任務執(zhí)行膏燃,類似于Timer。(這種線程池原理暫還沒完全了解透徹)
16何什、SQL 優(yōu)化的常見方法有哪些
查詢條件減少使用函數(shù)组哩,避免全表掃描
減少不必要的表連接
有些數(shù)據(jù)操作的業(yè)務邏輯可以放到應用層進行實現(xiàn)
可以使用with as
盡量避免使用游標,因為游標的效率較差
不要把SQL語句寫得太復雜
不能循環(huán)執(zhí)行查詢
用 exists 代替 in
表關聯(lián)關系不要太糾結
查詢多用索引列取查处渣,用charindex或者like[0-9]來代替%%
inner關聯(lián)的表可以先查出來伶贰,再去關聯(lián)leftjoin的表
可以進行表關聯(lián)數(shù)據(jù)拆分,即先查出核心數(shù)據(jù)罐栈,再通過核心數(shù)據(jù)查其他數(shù)據(jù)黍衙,這樣會快得多
參考SQL執(zhí)行順序進行優(yōu)化
表關聯(lián)時取別名,也能提高效率
使用視圖悠瞬,給視圖建立索引進行優(yōu)化
使用數(shù)據(jù)倉庫的形式们豌,建立單獨的表存儲數(shù)據(jù),根據(jù)時間戳定期更新數(shù)據(jù)浅妆。將多表關聯(lián)的數(shù)據(jù)集中抽取存入一張表中望迎,查詢時單表查詢,提高了查詢效率
對查詢進行優(yōu)化凌外,應盡量避免全表掃描辩尊,首先應考慮在 where 及 order by 涉及的列上建立索引
應盡量避免在 where 子句中對字段進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描康辑,如:
select id from t where num is null
可以在num上設置默認值0摄欲,確保表中num列沒有null值,然后這樣查詢:
select id from t where num=0
19.應盡量避免在 where 子句中使用!=或<>操作符疮薇,否則將引擎放棄使用索引而進行全表掃描
17胸墙、SQL 索引的順序,字段的順序
18按咒、查看 SQL 是不是使用了索引迟隅?(有什么工具)
在select語句前加上EXPLAIN即可
19、TCP 和 UDP 的區(qū)別?TCP 數(shù)據(jù)傳輸過程中怎么做到可靠的智袭?
UDP(User Data Protocol奔缠,用戶數(shù)據(jù)報協(xié)議)是與TCP相對應的協(xié)議。它是屬于TCP/IP協(xié)議族中的一種
1)為了保證數(shù)據(jù)包的可靠傳遞吼野,發(fā)送方必須把已發(fā)送的數(shù)據(jù)包保留在緩沖區(qū)校哎;
(2)并為每個已發(fā)送的數(shù)據(jù)包啟動一個超時定時器;
(3)如在定時器超時之前收到了對方發(fā)來的應答信息(可能是對本包的應答瞳步,也可以是對本包后續(xù)包的應答)闷哆,則釋放該數(shù)據(jù)包占用的緩沖區(qū);
(4)否則,重傳該數(shù)據(jù)包谚攒,直到收到應答或重傳次數(shù)超過規(guī)定的最大次數(shù)為止阳准。
(5)接收方收到數(shù)據(jù)包后,先進行CRC校驗馏臭,如果正確則把數(shù)據(jù)交給上層協(xié)議亡容,然后給發(fā)送方發(fā)送一個累計應答包废恋,表明該數(shù)據(jù)已收到稼病,如果接收方正好也有數(shù)據(jù)要發(fā)給發(fā)送方肮韧,應答包也可方在數(shù)據(jù)包中捎帶過去。
20帮寻、說下你知道的排序算法吧
常見的內(nèi)部排序算法有:插入排序乍狐、希爾排序、選擇排序固逗、冒泡排序浅蚪、歸并排序、快速排序烫罩、堆排序惜傲、基數(shù)排序等
21、查找一個數(shù)組的中位數(shù)贝攒?
通過二分查找法來找中位數(shù)
基本思想是:假設ar1[i]是合并后的中位數(shù)盗誊,那么ar1[i]大于ar1[]中前i-1個數(shù),且大于ar2[]中前j=n-i-1個數(shù)隘弊。通過ar1[i]和ar2[j]哈踱、ar2[j+1]兩個數(shù)的比較,在ar1[i]的左邊或者ar1[i]右邊繼續(xù)進行二分查找梨熙。對于兩個數(shù)組 ar1[] 和ar2[], 先在 ar1[] 中做二分查找开镣。如果在ar1[]中沒找到中位數(shù), 繼續(xù)在ar2[]中查找。
算法流程:
得到數(shù)組ar1[]最中間的數(shù)咽扇,假設下標為i.
計算對應在數(shù)組ar2[]的下標j邪财,j = n-i-1
如果 ar1[i] >= ar2[j] and ar1[i] <= ar2[j+1]舅列,那么 ar1[i] 和 ar2[j] 就是兩個中間元素,返回ar2[j] 和 ar1[i] 的平均值
如果 ar1[i] 大于 ar2[j] 和 ar2[j+1] 那么在ar1[i]的左部分做二分查找(i.e., arr[left ... i-1])
如果 ar1[i] 小于 ar2[j] 和 ar2[j+1] 那么在ar1[i]的右部分做二分查找(i.e., arr[i+1....right])
如果到達數(shù)組ar1[]的邊界(left or right)卧蜓,則在數(shù)組ar2[]中做二分查找
時間復雜度:O(logn)。
歡迎工作一到五年的Java工程師朋友們加入Java高級架構:706315665
群內(nèi)提供免費的Java架構學習資料(里面有高可用把敞、高并發(fā)弥奸、高性能及分布式、Jvm性能調(diào)優(yōu)奋早、Spring源碼盛霎,
MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)
合理利用自己每一分每一秒的時間來學習提升自己耽装,不要再用"沒有時間“來掩飾自己思想上的懶惰愤炸!趁年輕,使勁拼掉奄,給未來的自己一個交代规个!