需求:分析服務接口的調用次數和平均響應時長待分析的服務日志:http://www.izuiyou.com/download/server_access.log.tgz下載并解壓,解壓后有一個文件server_access.log, 文件每一行記錄一次服務接口的調用信息,日志格式如下: 15/Nov/2016:03:20:01 /post/httpapi/get_member_like_data 0.004 該行包含三個字段,字段間以空格區分, 第一個字段是訪問時間,第二個字段是接口名字,第三個字段是調用的響應時長(單位毫秒)。 請做如下分析:
1.計算每個接口的訪問次數,并按次數的倒序排序 答: 該問關鍵點有兩個: 1)對于重復接口字符串的判定 這里我想到兩種方案,一是通過直接對比兩個接口的字符串來對比是否是同一接口,二是通過哈希算法為每個接口生成唯一的標記位然后存儲到類集合中 建立接口對象
public static class XCInterface{ String mName; String visitTime; double responseTime; public XCInterface(String mName, String visitTime, Double responseTime) { this.mName = mName; this.visitTime = visitTime; this.responseTime = responseTime; } }第一種方案的實現及復雜度: 建立對象數組A,遍歷日志文件,若接口的字串S不被包含在數組A中則向A中添加字串S對應的接口Node,否則僅在訪問次數上+1即可。
for("遍歷獲取接口字符串值"){ int k=0; //mName接口字串,visitTime 訪問時間,responseTime響應時間,visitNumber 訪問累計次數 if("對象數組A中沒有接口s對應的接口Node"){ xcInterfaces[k] = new XCInterface(mName,visitTime,responseTime,0); k+=1; }else { xcInterfaces["匹配位置"].visitNumber+=1; } }假設m:不同接口字串的總數 n:日志總數 x:所有接口字串個數的平均數 該方案最差情況下n中的每個日志每輪都需要與m中的所有已積累字串進行對比,且每次都要對比x次,那么該方案的復雜度是O(m*n*x)即O(mnx)。
第二種方案的實現及復雜度: 對n個日志進行一輪遍歷,在遍歷的過程中通過預先設定好的hash函數為每個不同的接口字串生成在數組中唯一的標記值
//這里假設共有1000個以內的訪問接口 XCInterface[] xcInterfaces = new XCInterface[1000]; for ("遍歷獲取接口字符串值") { //mName接口字串,visitTime 訪問時間,responseTime響應時間 if(xcInterfaces["生成唯一的hash值"] !=null){//這一步省去了接口字符的對比過程,較少m倍 xcInterfaces["生成唯一的hash值"].visitNumber+=1; }else { xcInterfaces["生成唯一的hash值"] = new XCInterface(mName, visitTime, responseTime,0); } }2)判定后數據的存取及排序 這里把前面所有非null的值提取到ArrayList中進行排序操作
PRivate static void quick_sort(ArrayList<XCInterface> mList,int l,int r){ if(l<r){ int i=l,j=r; double temp = mList.get(0).responseTime; while(i<j){ while(i<j&&mList.get(i).responseTime<=temp){ j--; } if(i<j){ mList.get(i++).responseTime = mList.get(j).responseTime; } while(i<j&&mList.get(i).responseTime>=temp){ i++; } if(i<j){ mList.get(j--).responseTime = mList.get(i).responseTime; } } mList.get(i).responseTime = temp; quick_sort(mList,l,i-1); quick_sort(mList,i+1,r); } }OK,對于每個接口的倒序排列就搞定了
2.計算每個接口的平均響應時長 這里O(N)即可實現,在原有的對象中添加一個totalTime屬性
public static class XCInterface { //省略... int totalTime; public XCInterface(String mName, String visitTime, Double responseTime, int visitNumber ,int totalTime) { this.totalTime = totalTime; //省略... } }平均響應時長 = totalTime/visitNumber;
3.計算每個接口響應時長超過100ms的次數 同樣的添加一個屬性overTimeCount累計個數即可,復雜度O(N),不再過多敘說
最后,我們完全可以把這么大的數據量劃分為多個文件,并通過多線程來并發實現計算,最后對結果統一處理即可。
最右App的核心操作之一就是通過刷新推薦出帖子進行消費,每時每刻都有大量的新帖子產生,而每次刷新能推薦給你的帖子數是非常有限的(比如一次刷新推薦12條帖子),那么此時就需要在服務器端對于待推薦的帖子進行排序,排在前面的帖子會優先被推薦出來,用戶通過刷新顯示到最右APP中。 那么問題來了,如何對這些待推薦的帖子進行排序呢? 1.帖子排序依賴于每個帖子的權重值(Rank) 2.帖子權重和很多因素有關,例如發帖時間,帖子類型,帖子得到的行為等 3.帖子得到的行為有查看、贊、踩,分享等,你可以通過使用最右App了解更多的用戶行為。 4.甚至你的算法可以針對不同的用戶給出完全不同的排序結果(最終給出的算法中可以不考慮這一點)。 最后,給出你的算法思路和描述,最好能給出偽碼實現。
++關于這個問題啊,,貌似更像是產品同學的問題吧,既然有此一問,這里給出琢磨的思路及其實現。++
對于帖子的推薦順序在確定每個帖子針對每個用戶的權重之后還是比較簡單的,而權重的獲取大致可以參考faceBook的edgerank算法。
EdgeRank 用于當某個用戶查看他的新鮮事時,決定這些新鮮事先后順序的一個排序算法. 算法核心是每個事件對這個用戶而言的權重 E, 其計算公式是 E = u*w*d, 其中 u, 事件生產者和觀察者之間的親密度 w, 邊權重 (主要是事件的類型) d, 時間衰減因子
我個人的看法是針對實際應用涉及到的每一項會影響用戶對帖子感覺的因素設定不同的值用以表示該因素對整體權重產生的影響(可能的因素特別多,比如帖子類型,點贊,親密度,被舉報等等),然后通過累加累減變動的產生的一個針對具體用戶的帖子權重值,根據該值響應用戶的數據獲取請求即可。
大體上就是這樣了,希望沒有白忙活吧,哈哈
新聞熱點
疑難解答