仿牛客网论坛项目
項目本身
項目的背景,解決了一個什么樣的問題
這個項目的整體結構來源于??途W,主要使用了Springboot、Mybatis、MySQL、Redis、Kafka、等工具。主要實現了用戶的注冊、登錄、發帖、點贊、系統通知、按熱度排序、搜索等功能。另外引入了redis數據庫來提升網站的整體性能,實現了用戶憑證的存取、點贊關注的功能。基于 Kafka 實現了系統通知:當用戶獲得點贊、評論后得到通知。利用定時任務定期計算帖子的分數,并在頁面上展現熱帖排行榜。
項目中的職責是什么
1、完成軟件系統代碼的實現,編寫代碼注釋和開發文檔; 2、輔助進行系統的功能定義,程序設計; 3、根據設計文檔或需求說明完成代碼編寫,調試,測試和維護;
項目中使用的技術棧是什么?項目架構是怎么樣的?使用微服務了嘛?
服務器分為表現層/業務層/數據層,其中Spring MVC是工作在表現層,作用是接收/解析用戶發送的請求,調用對應的業務類,根據業務類返回的結果(ModelAndView),調用view進行視圖渲染,并將渲染后的View返回給請求者。具體分為以下8步:
客戶端(瀏覽器)發送請求給前端處理器(DispatcherServlet)(發送請求,響應結果);
DispatcherServlet根據請求信息調用HandlerMapping,查找到對應的Handler;
查找到對應的Handler(也就是Controller)后,由HandlerAdapter適配器處理;
HandlerAdapter根據Handler來調用真正的Controller;
Controller進行業務處理,返回ModelAndView對象,Model是數據對象,View是邏輯上的View;
ViewResolver根據邏輯view找到實際view;
DispatcherServlet把Model傳給view進行視圖渲染,然后返回給請求者。
mvc三層架構:
C - Controller:控制器。接受用戶請求,調用 Model 處理,然后選擇合適的View給客戶。
M - Model:模型。業務處理模型,接受Controller的調遣,處理業務,處理數據。
V - View:視圖。返回給客戶看的結果。
對Spring IoC的理解:
IoC的意思是控制反轉,是一種設計思想,把需要在程序中手動創建對象的控制權交給了Spring框架。IoC的載體是IoC容器,本質是一個工廠,數據結構上來看是一個Map,用來存放著各種對象。當我們創建一個對象時,只需要配置好配置文件/注解,而不用擔心對象是怎么被創建出來的。
IoC的優點:降低耦合,對象被容器管理需要兩份數據:你的對象定義 + 配置文件,對象間的關系體現在配置文件,不會直接產生耦合。
項目是怎么搭建的,機器配置是怎么樣的,有做分布式嘛?
項目的具體功能細節,如論壇項目中的評論如何存儲?怎么展示所有的評論?
user_id對應的是發評論的用戶,entity_type是指評論的類型,論壇部分,有兩種類型,對帖子的評論和對評論的評論,為了方便區分,對評論的評論我們成為回復,entity_id對應回復的實體的id,target_id也就是回復的對象,這個主要是在回復的時候需要顯示回復的誰。
private int id;private int userId;private int entityType;private int entityId;private int targetId;private String content;private int status;private Date createTime;一個是查詢評論,一個是查詢評論數量,這里也需要用到分頁查詢,用了offset和limit
-
之前這個方法返回了帖子和作者的數據,因為評論需要分頁,所以傳入page對象。
-
對page對象進行配置,一頁顯示5條,page的路徑和總的評論數
-
首先用上面寫的方法查詢評論,放到list里,然后還需要進行一些處理。查詢到的評論里只有user_id,沒有用戶名,同時評論下還有回復。
-
VO代表顯示對象,用來顯示在頁面上的對象。
-
整個邏輯就是查出當前帖子下的所有評論,遍歷所有評論,處理用戶名等信息,查詢評論下的回復,遍歷每個回復,處理用戶名等信息。
怎么實現注冊功能的?
根據請求來拆解功能 1,打開注冊網頁 2,把注冊的信息發送給服務器(點注冊) 3,把激活郵件發送給郵箱 4,利用激活鏈接打開網頁
每一次請求都是先開發數據訪問層,在開發業務層,最后開發視圖層(三層架構),但是每一次請求不一定要用到這三層
項目中的框架或者中間件的使用細節。(項目中如何使用ES,ES怎么支持搜索?redis和DB是如何配合使用的)
redis的使用
概念:redis是一個非關系型數據庫,數據存儲在內存中,讀寫速度快??梢源鎯︽I和五種不同類型值的映射。只能以字符串為鍵,值支持:字符串,列表,無序集合,有序集合,hash散列表。
使用redis存儲驗證碼:
因為驗證碼需要頻繁的進行訪問與刷新,因此對性能的要求較高; 驗證碼不需要永久保存,通常在很短的時間后就會失效; 分布式部署的時候,存在session共享的問題。
使用redis存儲登錄憑證:因為后臺在每次處理請求的時候都要查詢用戶的登錄憑證,訪問的頻率非常高,因此需要使用redis存儲。
使用redis緩存用戶信息: 因為后臺在每次處理請求的時候都要根據用戶的憑證查詢用戶信息,訪問的頻率非常高。
Redis可以使用zset對需要排序的數據進行自定義的排序。
怎樣存儲的點贊/關注/緩存用戶數據:
-
點贊:點贊key是實體類型實體id,vlaue存的是登錄者的用戶id,使用的數據類型是set無序集合存儲
-
關注:使用zSet類型存儲,key為被關注者,value保存關注者以及關注時間為score
-
緩存用戶數據:使用Value類型,key為用userID得到的key,value為user對象(設置過期時間,且數據修改時需要清除緩存)
一般我們來使用redis做緩存,那么redis如何與數據庫配合,使得我們的項目質量更高呢。我們一般將用戶訪問頻繁,且修改頻度低的數據放在緩存中,以提高響應速度。在前端發來訪問請求時,我們一般進行以下邏輯操作:
查詢操作:
前端發來請求時,先進行緩存的查詢,如果緩存存在要查詢的數據,則返回。否則去數據庫中查詢,并添加到緩存中,再返回數據,這樣在下次查詢時,便可直接從緩存中取。
添加操作:
添加操作我們直接添加到數據庫即可,也可以在添加到緩存的同時添加到數據庫。但在數據量較大時,推薦的做法是先將數據添加到緩存,在另一個線程中將數據同步到數據庫。
修改操作:
修改操作先修改數據庫,再將緩存的數據刪除即可,不要直接更新緩存,效率太低。
注意:本文僅僅適用于普通web項目,對于高并發項目,需考慮數據同步問題。
kafka的使用
Kafka簡介:Kafka是一種消息隊列,主要用來處理大量數據狀態下的消息隊列,一般用來做日志的處理,是一個分布式、支持分區的(partition)、多副本的(replica),基于zookeeper協調的分布式消息系統,它的最大的特性就是可以實時的處理大量數據以滿足各種需求場景。
當有點贊,評論,關注請求時,會發送系統通知點贊,評論,關注的對象。在處理系統信息時,使用到了Kafka。
具體來說,先定義了生產者類和消費者類,其中生產者被點贊/評論/關注功能對應的Controller使用,產生消息。而消費者負責消息(message)到來時,把消息存到數據庫內。
ES的使用
項目擴展在進行帖子搜索時,使用到了ES。可用Repository和Template兩種方式,由于Repository搜索到的結果(直接返回的post類,方便)沒有高亮標簽(why),所以使用了template方式重寫了mapResults函數,獲得了帶有高亮標簽的post。 搜索:定義SearchQuery,確定搜素內容,排序方式,高亮等。接著使用elasticTemplate.queryForPage方法,需要重寫mapResults函數,得到高亮數據。
項目中存在的問題及解決方案
是怎樣實現統一捕獲異常的? 在SpringBoot的項目某一路徑下,加上對應的錯誤頁面,發生錯誤時自動會跳轉。服務器的三層結構中,錯誤會層層向上傳遞,所以只需要在表現層(controller)統一處理錯誤即可。 方法:在controller中加上advice包,并通過注解@ControllerAdvice和@ExceptionHandler,統一捕獲異常。
是怎樣實現統一記錄日志的? 使用了AOP技術(面向切面編程),這里使用到的是SpringAOP。 AOP技術能夠將哪些與業務,但是為業務模塊共同調用的邏輯或責任(比如事務處理,日志記錄,權限控制等),封裝起來,便于減少系統的重復代碼,降低模塊間的耦合度,并有利于未來的擴展性和維護性。
SpringAOP本質上基于動態代理,當要代理的對象實現了某接口,會使用JDK動態代理,在運行時通過創建接口的代理實例,織入代碼。當要代理的對象沒有實現接口,則使用Cglib技術(編譯時增強),通過子類代理織入代碼。
項目的具體功能點如何優化(查詢評論是在DB中掃表查詢嗎?想要查詢的更快需要做哪些優化?)
1、使用索引 盡量避免全表掃描,首先應考慮在where及order by,group by涉及的列上建立索引。
2、優化SQL語句 通過explain來查看SQL語句的執行效果,可以幫助選擇更好的索引和優化查詢語句。例如:
explain select * from news;不要返回用不到的字段 ,不在索引列做運算或者使用函數 ,查詢盡可能使用limit減少返回的行數,減少數據傳輸時間和帶寬浪費。
3、優化數據庫對象 優化表的數據類型
select * from 表名 procedure analyse();對表進行拆分: 可以提高表的訪問效率。有兩種拆分方法: 垂直拆分:把主鍵和一些列放在一個表中,然后把主鍵和另外的列放在另一個表中。 使用場景:如果一個表中某些列常用,另外一些不常用,就可以垂直拆分。 水平拆分:根據一列或者多列數據的值把數據行放到兩個獨立的表中。 使用中間表來提高查詢速度: 創建中間表,表結構和源表結構完全相同,轉移要統計的數據到中間表,然后在中間表上進行統計,得出想要的結果。
項目中最有挑戰的模塊,怎么解決的
點贊、關注、緩存用戶的信息,通過redis這一個非關系型數據庫,將數據存儲在內存中,讀寫速度快,滿足高性能的要求。
項目中使用spring框架的原因
spring有很多模塊組成,利用這些模塊可以方便開發工作。
這些模塊是:核心容器(spring core)/數據訪問和集成(Spring JDBC)/Web(Spring Web/MVC)/AOP(Spring Aop)/消息模塊/測試模塊(Spring Test)等。
項目要增大10倍的qps,你會怎么設計?
-
QPS(TPS):每秒鐘request/事務 數量
-
并發數: 系統同時處理的request/事務數
-
響應時間: 一般取平均響應時間
由公式:QPS(TPS)= 并發數/平均響應時間 可以看出,要提高qps,我們必須做2個方面努力
增加并發數:
1.比如增加tomcat并發的線程數,開喝服務器性能匹配的線程數,可以更多滿足服務請求。
2.增加數據庫的連接數,預建立合適數量的TCP連接數。
3.后端服務盡量無狀態話,可以更好支持橫向擴容,滿足更大流量要求。
4.調用鏈路上的各個系統和服務盡量不要單點,要從頭到尾都是能力對等的,不能讓其中某一點成為瓶頸。
5.RPC調用的盡量使用線程池,預先建立合適的連接數。
減少平均響應時間:
1.請求盡量越前結束,越好,這樣壓力就不要穿透到后面的系統上,可以在各個層上加上緩存
2.流量消峰。放行適當的流量,處理不了的請求直接返回錯誤或者其他提示。和水壩道理很類似
3.減少調用鏈
4.優化程序
5.減少網絡開銷,適當使用長連接
6.優化數據庫,建立索引
項目上線后出現線上問題怎么解決?比如頻繁fullGC,定時任務失敗怎么辦?
總結
- 上一篇: linux重新mac,用 Linux 让
- 下一篇: 使用 Nginx 部署前后端分离项目,解