面試:第八章:SpringMVC、Springboot、Mybatis、Dubbo、Zookeeper、Redis、Elasticsearch、Nginx 、Fastdfs、ActiveMQ

SpringMVC:

簡單的介紹一下Spring Mvc的工作原理?

 

1、用戶向服務器發(fā)送請求,請求被SpringMVC的前端控制器DispatcherServlet截獲。

2、DispatcherServlet對請求的URL(統(tǒng)一資源定位符)進行解析,得到URI(請求資源標識符),然后根據(jù)該URI,調(diào)用HandlerMapping獲得該Handler配置的所有相關的對象,包括Handler對象以及Handler對象對應的攔截器,這些對象都會被封裝到一個HandlerExecutionChain對象當中返回。

3、DispatcherServlet根據(jù)獲得的Handler,選擇一個合適的HandlerAdapter。HandlerAdapter的設計符合面向?qū)ο笾械膯我宦氊熢瓌t,代碼結(jié)構(gòu)清晰,便于維護,最為重要的是,代碼的可復制性高。HandlerAdapter會被用于處理多種Handler,調(diào)用Handler實際處理請求的方法。

4、提取請求中的模型數(shù)據(jù),開始執(zhí)行Handler(Controller)。在填充Handler的入?yún)⑦^程中,根據(jù)配置,spring將幫助做一些額外的工作消息轉(zhuǎn)換:將請求的消息,如json、xml等數(shù)據(jù)轉(zhuǎn)換成一個對象,將對象轉(zhuǎn)換為指定的響應信息。數(shù)據(jù)轉(zhuǎn)換:對請求消息進行數(shù)據(jù)轉(zhuǎn)換,如String轉(zhuǎn)換成Integer、Double等。 數(shù)據(jù)格式化:對請求的消息進行數(shù)據(jù)格式化,如將字符串轉(zhuǎn)換為格式化數(shù)字或格式化日期等。數(shù)據(jù)驗證:驗證數(shù)據(jù)的有效性如長度、格式等,驗證結(jié)果存儲到BindingResult或Error中。

5、Handler執(zhí)行完成后,向DispatcherServlet返回一個ModelAndView對象,ModelAndView對象中應該包含視圖名或視圖模型。

6、根據(jù)返回的ModelAndView對象,選擇一個合適的ViewResolver(視圖解析器)返回給DispatcherServlet。

7、ViewResolver結(jié)合Model和View來渲染視圖。

8、將視圖渲染結(jié)果返回給客戶端。

url和uri的區(qū)別?

URI包括URL和URN兩個類別,個人的身份證號就是URN,個人的家庭地址就是URL,URN可以唯一標識一個人,而URL可以告訴郵遞員怎么把貨送到你手里。

 
Springboot:

簡單的介紹一下Springboot?

Springboot用來簡化spring應用的初始搭建以及開發(fā)過程 使用特定的方式來進行配置(properties或yml文件)
可以創(chuàng)建獨立的spring引用程序 main方法運行
Springboot嵌入的Tomcat 無需部署war文件
簡化maven配置

starters自動依賴與版本控制
Mybatis:

1、什么是mybatis?

(1)mybatis是一個優(yōu)秀的基于java的持久層框架,它內(nèi)部封裝了jdbc,使開發(fā)者只需要關注sql語句本身,而不需要花費精力去處理加載驅(qū)動、創(chuàng)建連接、創(chuàng)建statement等繁雜的過程。

(2)mybatis通過xml或注解的方式將要執(zhí)行的各種statement配置起來,并通過java對象和statement中sql的動態(tài)參數(shù)進行映射生成最終執(zhí)行的sql語句,最后由mybatis框架執(zhí)行sql并將結(jié)果映射為java對象并返回。

(3)MyBatis 支持定制化 SQL、存儲過程以及高級映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數(shù)以及獲取結(jié)果集。MyBatis 可以使用簡單的 XML 或注解來配置和映射原生信息,將接口和 Java 的 POJO映射成數(shù)據(jù)庫中的記錄。

2、Mybait的優(yōu)點:

(1)簡單易學,容易上手(相比于Hibernate) —- 基于SQL編程;

(2)JDBC相比,減少了50%以上的代碼量,消除了JDBC大量冗余的代碼,不需要手動開關連接;

(3)很好的與各種數(shù)據(jù)庫兼容(因為MyBatis使用JDBC來連接數(shù)據(jù)庫,所以只要JDBC支持的數(shù)據(jù)庫MyBatis都支持,而JDBC提供了可擴展性,所以只要這個數(shù)據(jù)庫有針對Java的jar包就可以就可以與MyBatis兼容),開發(fā)人員不需要考慮數(shù)據(jù)庫的差異性。

(4)提供了很多第三方插件(分頁插件 / 逆向工程);

(5)能夠與Spring很好的集成;

(6)MyBatis相當靈活,不會對應用程序或者數(shù)據(jù)庫的現(xiàn)有設計強加任何影響,SQL寫在XML里,從程序代碼中徹底分離,解除sql與程序代碼的耦合,便于統(tǒng)一管理和優(yōu)化,并可重用。

(7)提供XML標簽,支持編寫動態(tài)SQL語句。

(8) 提供映射標簽,支持對象與數(shù)據(jù)庫的ORM字段關系映射。

(9)提供對象關系映射標簽,支持對象關系組建維護。

3、MyBatis框架的缺點:

(1)SQL語句的編寫工作量較大,尤其是字段多、關聯(lián)表多時,更是如此,對開發(fā)人員編寫SQL語句的功底有一定要求。

(2)SQL語句依賴于數(shù)據(jù)庫,導致數(shù)據(jù)庫移植性差,不能隨意更換數(shù)據(jù)庫。

4、MyBatis框架適用場合:

(1)MyBatis專注于SQL本身,是一個足夠靈活的DAO層解決方案。

(2)對性能的要求很高,或者需求變化較多的項目,如互聯(lián)網(wǎng)項目,MyBatis將是不錯的選擇。

5、#{}和${}的區(qū)別是什么?

#{}是預編譯處理,${}是字符串替換。

Mybatis在處理#{}時,會將sql中的#{}替換為?號,調(diào)用PreparedStatement的set方法來賦值;

Mybatis在處理${}時,就是把${}替換成變量的值。

使用#{}可以有效的防止SQL注入,提高系統(tǒng)安全性。
 
Dubbo:

簡單的介紹一下Dubbo?(Dubbo是什么)

dubbo就是個服務調(diào)用的東東。

為什么怎么說呢?

因為Dubbo是由阿里開源的一個RPC分布式框架

那么RPC是什么呢?

就是不同的應用部署到不同的服務器上,應用之間想要調(diào)用沒有辦法直接調(diào)用,因為不在一個內(nèi)存空間,需要通過網(wǎng)絡通訊來調(diào)用,或者傳達調(diào)用的數(shù)據(jù)。而且RPC會將遠程調(diào)用的細節(jié)隱藏起來,讓調(diào)用遠程服務像調(diào)用本地服務一樣簡單。

dubbo有哪些組件?

主要有五個角色/核心組件,分為是Container(容器)、Provider(服務的提供方)、Registry(注冊中心)、Consumer(服務的消費方)、Monitor(監(jiān)控中心)。

容器:主要負責啟動、加載、運行服務提供者;

注冊中心:注冊中心只負責地址的注冊和查找

監(jiān)控中心:監(jiān)控中心負責統(tǒng)計各服務調(diào)用次數(shù)、調(diào)用時間

Dubbo支持什么協(xié)議?

Dubbo協(xié)議:缺省協(xié)議、采用了單一長連接和NIO異步通訊、使用線程池并發(fā)處理請求,能減少握手和加大并發(fā)效率
Zookeeper:

Zookeeper的實現(xiàn)原理?(工作原理)

Zookeeper會維護一個類似于標準的文件系統(tǒng)的具有層次關系的數(shù)據(jù)結(jié)構(gòu)。這個文件系統(tǒng)中每個子目錄項都被稱為znode節(jié)點,這個znode節(jié)點也可以有子節(jié)點,每個節(jié)點都可以存儲數(shù)據(jù),客戶端也可以對這些node節(jié)點進行getChildren,getData,exists方法,同時也可以在znode tree路徑上設置watch(類似于監(jiān)聽),當watch路徑上發(fā)生節(jié)點create、delete、update的時候,會通知到client。client可以得到通知后,再獲取數(shù)據(jù),執(zhí)行業(yè)務邏輯操作。Zookeeper 的作用主要是用來維護和監(jiān)控存儲的node節(jié)點上這些數(shù)據(jù)的狀態(tài)變化,通過監(jiān)控這些數(shù)據(jù)狀態(tài)的變化,從而達到基于數(shù)據(jù)的集群管理。

為什么要用zookeeper作為dubbo的注冊中心?能選擇其他的嗎?

Zookeeper的數(shù)據(jù)模型是由一系列的Znode數(shù)據(jù)節(jié)點組成,和文件系統(tǒng)類似。zookeeper的數(shù)據(jù)全部存儲在內(nèi)存中,性能高;zookeeper也支持集群,實現(xiàn)了高可用;同時基于zookeeper的特性,也支持事件監(jiān)聽(服務的暴露方發(fā)生變化,可以進行推送),所以zookeeper適合作為dubbo的注冊中心區(qū)使用。redis、Simple也可以作為dubbo的注冊中心來使用。

項目中主要用zookeeper做了什么?(作用)

作為注冊中心用;主要是在服務器上搭建zookeeper,其次在spring管理的dubbo的配置文件中配置(暴露方和消費方都需要配置)
Redis:

簡單介紹一個redis?

redis是內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)存儲系統(tǒng),一個key-value類型的非關系型數(shù)據(jù)庫,可持久化的數(shù)據(jù)庫,相對于關系型數(shù)據(jù)庫(數(shù)據(jù)主要存在硬盤中),性能高,因此我們一般用redis來做緩存使用;并且redis支持豐富的數(shù)據(jù)類型,比較容易解決各種問題,因此redis可以用來作為注冊中心,?數(shù)據(jù)庫、緩存和消息中間件。Redis的Value支持5種數(shù)據(jù)類型,string、hash、list、set、zset(sorted set);

String類型:一個key對應一個value

Hash類型:它的key是string類型,value又是一個map(key-value),適合存儲對象。

List類型:按照插入順序的字符串鏈表(雙向鏈表),主要命令是LPUSH和RPUSH,能夠支持反向查找和遍歷

Set類型:用哈希表類型的字符串序列,沒有順序,集合成員是唯一的,沒有重復數(shù)據(jù),底層主要是由一個value永遠為null的hashmap來實現(xiàn)的。

zset類型:和set類型基本一致,不過它會給每個元素關聯(lián)一個double類型的分數(shù)(score),這樣就可以為成員排序,并且插入是有序的。

你還用過其他的緩存嗎?這些緩存有什么區(qū)別?都在什么場景下去用?

對于緩存了解過redis和memcache

Memcache和redis的區(qū)別:

數(shù)據(jù)支持的類型:redis不僅僅支持簡單的k/v類型的數(shù)據(jù),同時還支持list、set、zset、hash等數(shù)據(jù)結(jié)構(gòu)的存儲;memcache只支持簡單的k/v類型的數(shù)據(jù),key和value都是string類型

可靠性:memcache不支持數(shù)據(jù)持久化,斷電或重啟后數(shù)據(jù)消失,但其穩(wěn)定性是有保證的;redis支持數(shù)據(jù)持久化和數(shù)據(jù)恢復,允許單點故障,但是同時也會付出性能的代價

性能上:對于存儲大數(shù)據(jù),memcache的性能要高于redis

應用場景:

Memcache:適合多讀少寫,大數(shù)據(jù)量的情況(一些官網(wǎng)的文章信息等)

Redis:適用于對讀寫效率要求高、數(shù)據(jù)處理業(yè)務復雜、安全性要求較高的系統(tǒng)

案例:分布式系統(tǒng),存在session之間的共享問題,因此在做單點登錄的時候,我們利用redis來模擬了session的共享,來存儲用戶的信息,實現(xiàn)不同系統(tǒng)的session共享;

對redis的持久化了解不?

redis的持久化方式有兩種:

RDB(半持久化方式):按照配置不定期的通過異步的方式、快照的形式直接把內(nèi)存中的數(shù)據(jù)持久化到磁盤的一個dump.rdb文件(二進制的臨時文件)中,redis默認的持久化方式,它在配置文件(redis.conf)中。

優(yōu)點:只包含一個文件,將一個單獨的文件轉(zhuǎn)移到其他存儲媒介上,對于文件備份、災難恢復而言,比較實用。

缺點:系統(tǒng)一旦在持久化策略之前出現(xiàn)宕機現(xiàn)象,此前沒有來得及持久化的數(shù)據(jù)將會產(chǎn)生丟失

RDB持久化配置:

Redis會將數(shù)據(jù)集的快照dump到dump.rdb文件中。此外,我們也可以通過配置文件來修改Redis服務器dump快照的頻率,在打開6379.conf文件之后,我們搜索save,可以看到下面的配置信息:

save 900 1              #在900秒(15分鐘)之后,如果至少有1個key發(fā)生變化,則dump內(nèi)存快照。

save 300 10            #在300秒(5分鐘)之后,如果至少有10個key發(fā)生變化,則dump內(nèi)存快照。

save 60 10000        #在60秒(1分鐘)之后,如果至少有10000個key發(fā)生變化,則dump內(nèi)存快照。

AOF(全持久化的方式):把每一次數(shù)據(jù)變化都通過write()函數(shù)將你所執(zhí)行的命令追加到一個appendonly.aof文件里面,Redis默認是不支持這種全持久化方式的,需要在配置文件(redis.conf)中將appendonly no改成appendonly yes

優(yōu)點:數(shù)據(jù)安全性高,對日志文件的寫入操作采用的是append模式,因此在寫入過程中即使出現(xiàn)宕機問題,也不會破壞日志文件中已經(jīng)存在的內(nèi)容;

缺點:對于數(shù)量相同的數(shù)據(jù)集來說,aof文件通常要比rdb文件大,因此rdb在恢復大數(shù)據(jù)集時的速度大于AOF;

AOF持久化配置:

在Redis的配置文件中存在三種同步方式,它們分別是:

appendfsync always     #每次有數(shù)據(jù)修改發(fā)生時都會都調(diào)用fsync刷新到aof文件,非常慢,但是安全;

appendfsync everysec  #每秒鐘都調(diào)用fsync刷新到aof文件中,很快,但是可能丟失一秒內(nèi)的數(shù)據(jù),推薦使用,兼顧了速度和安全;

appendfsync no          #不會自動同步到磁盤上,需要依靠OS(操作系統(tǒng))進行刷新,效率快,但是安全性就比較差;

二種持久化方式區(qū)別:

AOF在運行效率上往往慢于RDB,每秒同步策略的效率是比較高的,同步禁用策略的效率和RDB一樣高效;

如果緩存數(shù)據(jù)安全性要求比較高的話,用aof這種持久化方式(比如項目中的購物車);

如果對于大數(shù)據(jù)集要求效率高的話,就可以使用默認的。而且這兩種持久化方式可以同時使用。  

做過redis的集群嗎?你們做集群的時候搭建了幾臺,都是怎么搭建的?

Redis的數(shù)據(jù)是存放在內(nèi)存中的,不適合存儲大數(shù)據(jù),大數(shù)據(jù)存儲一般公司常用hadoop中的Hbase或者MogoDB。redis主要用來處理高并發(fā)的,用我們的項目來說,電商項目如果并發(fā)大的話,一臺單獨的redis是不能足夠支持我們的并發(fā),這就需要我們擴展多臺設備協(xié)同合作,即用到集群。

Redis搭建集群的方式有多種,例如:客戶端分片、Twemproxy、Codis等,但是redis3.0之后就支持redis-cluster集群,這種方式采用的是無中心結(jié)構(gòu),每個節(jié)點保存數(shù)據(jù)和整個集群的狀態(tài),每個節(jié)點都和其他所有節(jié)點連接。如果使用的話就用redis-cluster集群。集群這塊是公司運維搭建的,具體怎么搭建不是太了解。

我們項目中redis集群主要搭建了6臺,3主(為了保證redis的投票機制)3從(高可用),每個主服務器都有一個從服務器,作為備份機。所有的節(jié)點都通過PING-PONG機制彼此互相連接;客戶端與redis集群連接,只需要連接集群中的任何一個節(jié)點即可;Redis-cluster中內(nèi)置了16384個哈希槽,Redis-cluster把所有的物理節(jié)點映射到【0-16383】slot上,負責維護。

redis有事務嗎?

Redis是有事務的,redis中的事務是一組命令的集合,這組命令要么都執(zhí)行,要不都不執(zhí)行,保證一個事務中的命令依次執(zhí)行而不被其他命令插入。redis的事務是不支持回滾操作的。redis事務的實現(xiàn),需要用到MULTI(事務的開始)和EXEC(事務的結(jié)束)命令 ;

緩存穿透

緩存查詢一般都是通過key去查找value,如果不存在對應的value,就要去數(shù)據(jù)庫中查找。如果這個key對應的value在數(shù)據(jù)庫中也不存在,并且對該key并發(fā)請求很大,就會對數(shù)據(jù)庫產(chǎn)生很大的壓力,這就叫緩存穿透

解決方案:

1.對所有可能查詢的參數(shù)以hash形式存儲,在控制層先進行校驗,不符合則丟棄。

2.將所有可能存在的數(shù)據(jù)哈希到一個足夠大的bitmap中,一個一定不存在的數(shù)據(jù)會被這個bitmap攔截掉,從而避免了對底層存儲系統(tǒng)的查詢壓力。

3.如果一個查詢返回的數(shù)據(jù)為空(不管是數(shù) 據(jù)不存在,還是系統(tǒng)故障),我們?nèi)匀话堰@個空結(jié)果進行緩存,但它的過期時間會很短,最長不超過五分鐘。

緩存雪崩

當緩存服務器重啟或者大量緩存集中在一段時間內(nèi)失效,發(fā)生大量的緩存穿透,這樣在失效的瞬間對數(shù)據(jù)庫的訪問壓力就比較大,所有的查詢都落在數(shù)據(jù)庫上,造成了緩存雪崩。 這個沒有完美解決辦法,但可以分析用戶行為,盡量讓失效時間點均勻分布。大多數(shù)系統(tǒng)設計者考慮用加鎖或者隊列的方式保證緩存的單線程(進程)寫,從而避免失效時大量的并發(fā)請求落到底層存儲系統(tǒng)上。

解決方案:

1.在緩存失效后,通過加鎖或者隊列來控制讀數(shù)據(jù)庫寫緩存的線程數(shù)量。比如對某個key只允許一個線程查詢數(shù)據(jù)和寫緩存,其他線程等待。
2.可以通過緩存reload機制,預先去更新緩存,再即將發(fā)生大并發(fā)訪問前手動觸發(fā)加載緩存
3.不同的key,設置不同的過期時間,讓緩存失效的時間點盡量均勻
4.做二級緩存,或者雙緩存策略。A1為原始緩存,A2為拷貝緩存,A1失效時,可以訪問A2,A1緩存失效時間設置為短期,A2設置為長期。

redis的安全機制(你們公司redis的安全這方面怎么考慮的?)

漏洞介紹:redis默認情況下,會綁定在bind 0.0.0.0:6379,這樣就會將redis的服務暴露到公網(wǎng)上,如果在沒有開啟認證的情況下,可以導致任意用戶在訪問目標服務器的情況下,未授權就可訪問redis以及讀取redis的數(shù)據(jù),攻擊者就可以在未授權訪問redis的情況下可以利用redis的相關方法,成功在redis服務器上寫入公鑰,進而可以直接使用私鑰進行直接登錄目標主機;

解決方案:

    禁止一些高危命令。修改redis.conf文件,用來禁止遠程修改DB文件地址,比如 rename-command FLUSHALL "" 、rename-command CONFIG"" 、rename-command EVAL “”等;
    以低權限運行redis服務。為redis服務創(chuàng)建單獨的用戶和根目錄,并且配置禁止登錄;
    為redis添加密碼驗證。修改redis.conf文件,添加requirepass mypassword;
    禁止外網(wǎng)訪問redis。修改redis.conf文件,添加或修改 bind 127.0.0.1,使得redis服務只在當前主機使用;
    做log監(jiān)控,及時發(fā)現(xiàn)攻擊;

    redis的哨兵機制(redis2.6以后出現(xiàn)的)

哨兵機制:

監(jiān)控:監(jiān)控主數(shù)據(jù)庫和從數(shù)據(jù)庫是否正常運行;

提醒:當被監(jiān)控的某個redis出現(xiàn)問題的時候,哨兵可以通過API向管理員或者其他應用程序發(fā)送通知;

自動故障遷移:主數(shù)據(jù)庫出現(xiàn)故障時,可以自動將從數(shù)據(jù)庫轉(zhuǎn)化為主數(shù)據(jù)庫,實現(xiàn)自動切換;

具體的配置步驟參考的網(wǎng)上的文檔。要注意的是,如果master主服務器設置了密碼,記得在哨兵的配置文件(sentinel.conf)里面配置訪問密碼

redis中對于生存時間的應用

  Redis中可以使用expire命令設置一個鍵的生存時間,到時間后redis會自動刪除;

  應用場景:

    設置限制的優(yōu)惠活動的信息;
    一些及時需要更新的數(shù)據(jù),積分排行榜;
    手機驗證碼的時間;
    限制網(wǎng)站訪客訪問頻率;

Elasticsearch:

簡單介紹一個Elasticsearch?

ElasticSearch是一個基于Lucene的搜索服務器。通過HTTP使用JSON進行數(shù)據(jù)索引,用于分布式全文檢索,解決人們對于搜索的眾多要求。

lucene與elasticsearch(solr)有什么區(qū)別?

lucene只是一個提供全文搜索功能類庫的核心工具包,而真正使用它還需要一個完善的服務框架搭建起來的應用。好比lucene是類似于jdk,而搜索引擎軟件就是tomcat 的。elasticsearch和solr,這兩款都是基于lucene的搭建的,可以獨立部署啟動的搜索引擎服務軟件。

基本概念:

 

與MySQL對比

 

利用kibana學習 elasticsearch restful api (DSL)

Kibana 是一個開源分析和可視化平臺,可視化操作 Elasticsearch 。Kibana可以用來搜索,查看和與存儲在 Elasticsearch 索引中的數(shù)據(jù)進行交互??梢暂p松地進行高級數(shù)據(jù)分析,并可在各種圖表,表格和地圖中顯示數(shù)據(jù)。

ES提供了基于JSON的query DSL查詢語言
es中保存的數(shù)據(jù)結(jié)構(gòu)

public class  Movie {

 String id;

     String name;

     Double doubanScore;

     List<Actor> actorList;

}

public class Actor{

String id;

String name;

}

這兩個對象如果放在關系型數(shù)據(jù)庫保存,會被拆成2張表,但是elasticsearch是用一個json來表示一個document。

所以它保存到es中應該是:

{

  “id”:”1”,

  “name”:”operation red sea”,

  “doubanScore”:”8.5”,

  “actorList”:[  

{“id”:”1”,”name”:”zhangyi”},

{“id”:”2”,”name”:”haiqing”},

{“id”:”3”,”name”:”zhanghanyu”}

]

}
es 的java 客戶端的選擇

目前市面上有兩類客戶端

一類是TransportClient 為代表的ES原生客戶端,不能執(zhí)行原生dsl語句必須使用它的Java api方法。

另外一種是以Rest Api為主的missing client,最典型的就是jest。 這種客戶端可以直接使用dsl語句拼成的字符串,直接傳給服務端,然后返回json字符串再解析。

兩種方式各有優(yōu)劣,但是最近elasticsearch官網(wǎng),宣布計劃在7.0以后的版本中廢除TransportClient。以RestClient為主。在官方的RestClient 基礎上,進行了簡單包裝的Jest客戶端,就成了首選,而且該客戶端也與springboot完美集成。
中文分詞

elasticsearch本身自帶的中文分詞,就是單純把中文一個字一個字的分開,根本沒有詞匯的概念。
問題:

1、 es大量的寫操作會影響es 性能,因為es需要更新索引,而且es不是內(nèi)存數(shù)據(jù)庫,會做相應的io操作。

2、而且修改某一個值,在高并發(fā)情況下會有沖突,造成更新丟失,需要加鎖,而es的樂觀鎖會惡化性能問題。
解決思路:

用redis做精確計數(shù)器,redis是內(nèi)存數(shù)據(jù)庫讀寫性能都非??欤胷edis的原子性的自增可以解決并發(fā)寫操作。

 redis每計100次數(shù)(可以被100整除)我們就更新一次es ,這樣寫操作就被稀釋了100倍,這個倍數(shù)可以根據(jù)業(yè)務情況靈活設定。
增量同步索引庫

推薦使用MQ(RabbitMQ)

原理:使用MQ做增量同步,即當修改數(shù)據(jù)之后就將此數(shù)據(jù)發(fā)送至MQ,由MQ將此數(shù)據(jù)同步到ES上
Nginx:

1、請解釋一下什么是Nginx?

nginx本是一個web服務器和反向代理服務器,但由于豐富的負載均衡策略,常常被用于客戶端可真實的服務器之間,作為負載均衡的實現(xiàn)。用于HTTP、HTTPS、SMTP、POP3和IMAP協(xié)議。

2、請列舉Nginx的一些特性?

1)反向代理/L7負載均衡器

2)嵌入式Perl解釋器

3)動態(tài)二進制升級

4)可用于重新編寫URL,具有非常好的PCRE支持

3、nginx和apache的區(qū)別?

1)輕量級,同樣起web 服務,比apache 占用更少的內(nèi)存及資源

2)抗并發(fā),nginx 處理請求是異步非阻塞的,而apache 則是阻塞型的,在高并發(fā)下nginx 能保持低資源低消耗高性能

3)高度模塊化的設計,編寫模塊相對簡單

4)最核心的區(qū)別在于apache是同步多進程模型,一個連接對應一個進程;nginx是異步的,多個連接(萬級別)可以對應一個進程

4.nginx是如何實現(xiàn)高并發(fā)的?

一個主進程,多個工作進程,每個工作進程可以處理多個請求,每進來一個request,會有一個worker進程去處理。但不是全程的處理,處理到可能發(fā)生阻塞的地方,比如向上游(后端)服務器轉(zhuǎn)發(fā)request,并等待請求返回。那么,這個處理的worker繼續(xù)處理其他請求,而一旦上游服務器返回了,就會觸發(fā)這個事件,worker才會來接手,這個request才會接著往下走。由于web server的工作性質(zhì)決定了每個request的大部份生命都是在網(wǎng)絡傳輸中,實際上花費在server機器上的時間片不多。這是幾個進程就解決高并發(fā)的秘密所在。即@skoo所說的webserver剛好屬于網(wǎng)絡io密集型應用,不算是計算密集型。

5、請解釋Nginx如何處理HTTP請求?

Nginx使用反應器模式。主事件循環(huán)等待操作系統(tǒng)發(fā)出準備事件的信號,這樣數(shù)據(jù)就可以從套接字讀取,在該實例中讀取到緩沖區(qū)并進行處理。單個線程可以提供數(shù)萬個并發(fā)連接。

6、在Nginx中,如何使用未定義的服務器名稱來阻止處理請求?

只需將請求刪除的服務器就可以定義為:Server {listen 80; server_name “ “ ;return 444;}這里,服務器名被保留為一個空字符串,它將在沒有“主機”頭字段的情況下匹配請求,而一個特殊的Nginx的非標準代碼444被返回,從而終止連接。7、 使用“反向代理服務器”的優(yōu)點是什么?答:反向代理服務器可以隱藏源服務器的存在和特征。它充當互聯(lián)網(wǎng)云和web服務器之間的中間層。這對于安全方面來說是很好的,特別是當您使用web托管服務時。

8、請列舉Nginx服務器的最佳用途?

Nginx服務器的最佳用法是在網(wǎng)絡上部署動態(tài)HTTP內(nèi)容,使用SCGI、WSGI應用程序服務器、用于腳本的FastCGI處理程序。它還可以作為負載均衡器。

9、請解釋Nginx服務器上的Master和Worker進程分別是什么?

Master進程:讀取及評估配置和維持Worker進程:處理請求

10、請解釋你如何通過不同于80的端口開啟Nginx?

為了通過一個不同的端口開啟Nginx,你必須進入/etc/Nginx/sites-enabled/,如果這是默認文件,那么你必須打開名為“default”的文件。編輯文件,并放置在你想要的端口:Like server {listen 81;}

11、請解釋是否有可能將Nginx的錯誤替換為502錯誤、503?

502 =錯誤網(wǎng)關 503 =服務器超載 有可能,但是您可以確保fastcgi_intercept_errors被設置為ON,并使用錯誤頁面指令。Location / { fastcgi_pass 127.0.01:9001; fastcgi_intercept_errors on; error_page 502 =503/error_page.html; #… }

12、在Nginx中,解釋如何在URL中保留雙斜線?答:要在URL中保留雙斜線,就必須使用merge_slashes_off;語法:merge_slashes [on/off]默認值: merge_slashes on環(huán)境: http,server

13、請解釋ngx_http_upstream_module的作用是什么?

ngx_http_upstream_module用于定義可通過fastcgi傳遞、proxy傳遞、uwsgi傳遞、memcached傳遞和scgi傳遞指令來引用的服務器組。

14、請解釋什么是C10K問題?C10K問題是指無法同時處理大量客戶端(10,000)的網(wǎng)絡套接字。

15、請陳述stub_status和sub_filter指令的作用是什么?

1)Stub_status指令:該指令用于了解Nginx當前狀態(tài)的當前狀態(tài),如當前的活動連接,接受和處理當前讀/寫/等待連接的總數(shù)   2)Sub_filter指令:它用于搜索和替換響應中的內(nèi)容,并快速修復陳舊的數(shù)據(jù)

16、解釋Nginx是否支持將請求壓縮到上游?

您可以使用Nginx模塊gunzip將請求壓縮到上游。gunzip模塊是一個過濾器,它可以對不支持“gzip”編碼方法的客戶機或服務器使用“內(nèi)容編碼:gzip”來解壓縮響應。

17、解釋如何在Nginx中獲得當前的時間?要獲得Nginx的當前時間,必須使用SSI模塊、$date_gmt和$date_local的變量。Proxy_set_header THE-TIME $date_gmt;

18、用Nginx服務器解釋-s的目的是什么?用于運行Nginx -s參數(shù)的可執(zhí)行文件。

19、解釋如何在Nginx服務器上添加模塊?在編譯過程中,必須選擇Nginx模塊,因為Nginx不支持模塊的運行時間選擇。

20、什么是反向代理和正向代理?

正向代理:被代理的是客戶端,比如通過XX代理訪問國外的某些網(wǎng)站,實際上客戶端沒有權限訪問國外的網(wǎng)站,客戶端請求XX代理服務器,XX代理服務器訪問國外網(wǎng)站,將國外網(wǎng)站返回的內(nèi)容傳給真正的用戶。用戶對于服務器是隱藏的,服務器并不知道真實的用戶。

反向代理:被代理的是服務器,也就是客戶端訪問了一個所謂的服務器,服務器會將請求轉(zhuǎn)發(fā)給后臺真實的服務器,真實的服務器做出響應,通過代理服務器將結(jié)果返給客戶端。服務器對于用戶來說是隱藏的,用戶不知道真實的服務器是哪個。

關于正向代理和反向代理,聽起來比較繞,仔細理解,體會也不難明白到底是什么意思。

用nginx做實現(xiàn)服務的高可用,nginx本身可能成為單點,遇見的兩種解決方案,一種是公司搭建自己的DNS,將請求解析到不同的NGINX,另一只是配合keepalive實現(xiàn)服務的存活檢測。
Fastdfs:

簡單介紹一下FastDFS?

1.開源的分布式文件系統(tǒng),主要對文件進行存儲、同步、上傳、下載,有自己的容災備份、負載均衡、線性擴容機制;

2.FastDFS架構(gòu)主要包含Tracker(跟蹤) server和Storage(組,卷) server。客戶端請求Tracker server進行文件上傳、下載的時候,通過Tracker server調(diào)度最終由Storage server完成文件上傳和下載。

3.Tracker server:跟蹤器或者調(diào)度器,主要起負載均衡和調(diào)度作用。通過Tracker server在文件上傳時可以根據(jù)一些策略找到Storage server提供文件上傳服務。

Storage server:存儲服務器,作用主要是文件存儲,完成文件管理的所有功能??蛻舳松蟼鞯奈募饕4嬖赟torage server上,Storage server沒有實現(xiàn)自己的文件系統(tǒng)而是利用操作系統(tǒng)的文件系統(tǒng)去管理文件。

存儲服務器采用了分組/分卷的組織方式。

整個系統(tǒng)由一個組或者多個組組成;

組與組之間的文件是相互獨立的;

所有組的文件容量累加就是整個存儲系統(tǒng)的文件容量;

一個組可以由多臺存儲服務器組成,一個組下的存儲服務器中的文件都是相同的,組中的多臺存儲服務器起到了冗余備份和負載均衡的作用;

在組內(nèi)增加服務器時,如果需要同步數(shù)據(jù),則由系統(tǒng)本身完成,同步完成之后,系統(tǒng)自動將新增的服務器切換到線上提供使用;

當存儲空間不足或者耗盡時,可以動態(tài)的添加組。只需要增加一臺服務器,并為他們配置一個新的組,即擴大了存儲系統(tǒng)的容量。

我們在項目中主要使用fastdfs來存儲整個項目的圖片。

為什么要使用FastDFS作為你們的圖片服務器?

首先基于fastDFS的特點:存儲空間可擴展、提供了統(tǒng)一的訪問方式、訪問效率高、容災性好  等特點,再結(jié)合我們項目中圖片的容量大、并發(fā)大等特點,因此我們選擇了FastDFS作為我們的圖片服務器;

Nginx也可以作為一臺圖片服務器來使用,因為nginx可以作為一臺http服務器來使用,作為網(wǎng)頁靜態(tài)服務器,通過location標簽配置;在公司中有的時候也用ftp作為圖片服務器來使用。

FastDFS中文件上傳下載的具體流程?

 

客戶端上傳文件后生成一個file_id,返回給客戶端,客戶端利用這個file_id結(jié)合ip地址,生成一個完成圖片的url,保存在數(shù)據(jù)庫中。生成的那個file_id用于以后訪問該文件的索引信息。

FastDFS文件下載的流程

 

ActiveMQ:

什么是activemq

activeMQ是一種開源的,面向消息的中間件,用來系統(tǒng)之間進行通信的

activemq的原理

 原理就是生產(chǎn)者生產(chǎn)消息, 把消息發(fā)送給activemq。 Activemq 接收到消息, 然后查看有多少個消費者, 然后把消息轉(zhuǎn)發(fā)給消費者, 此過程中生產(chǎn)者無需參與。 消費者接收到消息后做相應的處理和生產(chǎn)者沒有任何關系

對比RabbitMQ

RabbitMQ的協(xié)議是AMQP,而ActiveMQ使用的是JMS協(xié)議。顧名思義JMS是針對Java體系的傳輸協(xié)議,隊列兩端必須有JVM,所以如果開發(fā)環(huán)境都是java的話推薦使用ActiveMQ,可以用Java的一些對象進行傳遞比如Map、Blob(二進制大數(shù)據(jù))、Stream等。而AMQP通用行較強,非java環(huán)境經(jīng)常使用,傳輸內(nèi)容就是標準字符串。

另外一點就是RabbitMQ用Erlang開發(fā),安裝前要裝Erlang環(huán)境,比較麻煩。ActiveMQ解壓即可用不用任何安裝。

對比KafKa

Kafka性能超過ActiveMQ等傳統(tǒng)MQ工具,集群擴展性好。

弊端是:

在傳輸過程中可能會出現(xiàn)消息重復的情況,

不保證發(fā)送順序

一些傳統(tǒng)MQ的功能沒有,比如消息的事務功能。

 所以通常用Kafka處理大數(shù)據(jù)日志。

對比Redis

其實Redis本身利用List可以實現(xiàn)消息隊列的功能,但是功能很少,而且隊列體積較大時性能會急劇下降。對于數(shù)據(jù)量不大、業(yè)務簡單的場景可以使用。

如何解決消息重復問題

所謂消息重復,就是消費者接收到了重復的消息,一般來說我們對于這個問題的處理要把握下面幾點,

①.消息不丟失(上面已經(jīng)處理了)

②.消息不重復執(zhí)行

一般來說我們可以在業(yè)務段加一張表,用來存放消息是否執(zhí)行成功,每次業(yè)務事物commit之后,告知服務端,已經(jīng)處理過該消息,

這樣即使你消息重發(fā)了,也不會導致重復處理

大致流程如下:

        業(yè)務端的表記錄已經(jīng)處理消息的id,每次一個消息進來之前先判斷該消息是否執(zhí)行過,如果執(zhí)行過就放棄,如果沒有執(zhí)行就開始執(zhí)行消息,消息執(zhí)行完成之后存入這個消息的id

關于事務控制

獲取session鏈接的時候 設置參數(shù) 默認不開啟

 

持久化與非持久化

通過producer.setDeliveryMode(DeliveryMode.PERSISTENT) 進行設置

持久化的好處就是當activemq宕機的話,消息隊列中的消息不會丟失。非持久化會丟失。但是會消耗一定的性能。