大廠面試題:今天覆試百度PHP工程師

今天下午來到北京百度科技園進行復試PHP工程師崗位。

大廠面試題:今天覆試百度PHP工程師

面試官問了很多問題,我大概整理回憶下:

1.Redis秒殺實現?

redis隊列解決搶購高併發的原理:

在程序跟數據庫之前呢我們可以利用redis隊列做一個緩衝機制,讓所有用戶的請求進行排隊,稟行先進先出的原則(redis中的lpush和rpop),
lpush程序是把用戶的請求壓入redis隊列,然後用rpop做一個守護進程來取隊列中的數據,按規定的搶購名額寫好,
把所有搶購成功的用戶寫入redis並且生成訂單,在lpush程序中查看中獎的用戶並且給用戶及時提醒搶購結果!

  

大廠面試題:今天覆試百度PHP工程師

2.服務器定時器實現,crontab 、crontab -e區別,死循環如何結束?

大廠面試題:今天覆試百度PHP工程師

第一種:在/etc/crontab下設置,指定用戶名的
1、vim命令進入/etc/crontab
2、在最後一行加上
59 23 * * * root /root/catina/rm_8080lina.sh
3、重啟crontab,使配置生效
第二種:直接用crontab -e,不需要指定用戶


1、crontab -e進入
2、:wq退出保存
3、查看上面那個腳本是否有執行權限
4、還要看腳本里面的涉及的操作文件是否有權限
5、重啟crontab,使配置生效 
1.使用ctrl-c跳出死循環
2.ps -ef|grep 名稱 查詢進程號
3.kill 進程號

3.PHP如何運行shell腳本,配置文件在哪開啟

php給我們提供了system(),exec(),passthru()這三個函數來調用外部的命令.
雖然這三個命令都能執行linux系統的shell命令,但是其實他們是有區別的:
system() 輸出並返回最後一行shell結果。
exec() 不輸出結果,返回最後一行shell結果,所有結果可以保存到一個返回的數組裡面。
passthru() 只調用命令,把命令的運行結果原樣地直接輸出到標準輸出設備上。
相同點:都可以獲得命令執行的狀態碼
例子:system("/usr/a.sh");  
首先是 要關掉 安全模式 safe_mode = off
然後在看看 禁用函數列表
disable_functions = proc_open, popen, exec, system, shell_exec, passthru
這裡要把 exec 去掉


重啟 服務器 就OK了 

4.獲取HTTP頭文件

1獲取全部(客戶端)HTTP請求頭信息
#1 array apache_request_headers(void)
#2:通過$_SERVER獲取,每個http請求頭信息都以"HTTP_"開頭,在$_SERVER鍵中獲取if_modified_since的請求信息
$_SERVER['HTTP_IF_MODIFIED_SINCE']

2獲取服務器響應一個HTTP請求所發送的所有標頭array get_headers(string $url [, int $format = 0 ] )
  # url 請求的服務器的URL地址 # format 0:返回的頭部信息以索引數字形式,1:返回頭部信息以關聯數組形式
  $head_arr = get_headers("xwww.baidu.com");
  $head_arr_index = get_headers("xwww.baidu.com",1);

  

5.Nginx負載均衡實現,有幾種方式?

1、輪詢(默認)
每個請求按時間順序逐一分配到不同的後端服務器,如果後端服務器down掉,能自動剔除。
upstream backserver {
server 192.168.0.14;
server 192.168.0.15;
}
2、weight
指定輪詢幾率,weight和訪問比率成正比,用於後端服務器性能不均的


情況。
upstream backserver {
server 192.168.0.14 weight=3;
server 192.168.0.15 weight=7;
}
權重越高,在被訪問的概率越大,如上例,分別是30%,70%。
3、ip_hash
上述方式存在一個問題就是說,在負載均衡系統中,假如用戶在某臺服務器上登錄了,那麼該用戶第二次請求的時候,因為我們是負載均衡系統,每次請求都會重新定位到服務器集群中的某一個,那麼已經登錄某一個服務器的用戶再重新定位到另一個服務器,其登錄信息將會丟失,這樣顯然是不妥的。
我們可以採用ip_hash指令解決這個問題,如果客戶已經訪問了某個服務器,當用戶再次訪問時,會將該請求通過哈希算法,自動定位到該服務器。
每個請求按訪問ip的hash結果分配,這樣每個訪客固定訪問一個後端服務器,可以解決session的問題。
upstream backserver {
ip_hash;
server 192.168.0.14:88;
server 192.168.0.15:80;
}
4、fair(第三方)
按後端服務器的響應時間來分配請求,響應時間短的優先分配。
5、url_hash(第三方)
按訪問url的hash結果來分配請求,使每個url定向到同一個(對應的)後端服務器,後端服務器為緩存時比較有效。 

6.Nginx.conf rewrite裡末尾符號問題 /path/to/photos /path/to/photos/區別?

當Web服務器接收到對某個末尾不含斜槓的url請求時,
例如:xx.com/product,這時服務器會搜索網站根目錄下有沒有名為“product”的文件,如果沒有就把product當做目錄處理,然後返回abc目錄下的默認首頁。
當Web服務器接收到的是末尾帶斜槓的請求時就會直接當做目錄處理。為了語義明確。當然現在很多應用程序是路由重寫路徑的。 

7.cookie會話攻擊防護?

什麼樣的Cookie信息可以被攻擊者利用
1. Cookie中包含了不應該讓除開發者之外的其他人看到的其他信息,如USERID=1000,USERSTATUS=ONLINE,ACCOUNT_ID=xxx等等這些信息。
2. Cookie信息進行了加密,但是很容易被攻擊者進行解密
3. 在對Cookie信息的時候沒有進行輸入驗證
如何防範利用Cookie進行的攻擊
1. 不要在Cookie中保存敏感信息
2. 不要在Cookie中保存沒有經過加密的或者容易被解密的敏感信息


3. 對從客戶端取得的Cookie信息進行嚴格校驗
4. 記錄非法的Cookie信息進行分析,並根據這些信息對系統進行改進。
5. 使用SSL/TLS來傳遞Cookie信息

8.PHP常用函數並說明?

9.PHP擴展文件安裝過程?

phpize安裝
//下載libevent擴展文件壓縮包(在當前系統哪個目錄下載隨意)
~# wget xxxx/get/libevent-0.1.0.tgz
//解壓文件
~# tar -zxvf libevent-0.1.0.tgz
//進入源碼目錄
~# cd libevent-0.1.0/
如 /usr/local/php7/bin/phpize //運行phpize命令,寫全phpize的路徑
~# ./configure --with-php-config=/usr/local/php/bin/php-config
//運行configure命令,配置時 要將php-config的路徑附上
~# make
~# make test
~# sudo make install
//修改php.ini,結尾加入:extension=libevent.so
//重啟對應的php-fpm

10.一個客戶端http請求從服務器server到nginx到php響應返回整個流程?

HTTP 事務執行過程

客戶端(瀏覽器)做出請求操作(輸入網址、點擊鏈接、提交表單)。
客戶端對域名進行解析,向設定的 DNS 服務器請求 IP 地址。
客戶端根據 DNS 服務器返回 IP 地址採用三次握手與服務端建立 TCP/IP 連接。
TCP/IP 連接成功後,客戶端向服務端發送 HTTP 請求。
服務端的 Web Server 會判斷 HTTP 請求的資源類型,進行內容分發處理;如果請求的資源為 PHP 文件,服務端軟件會啟動對應的 CGI 程序進行處理,並返回處理結果。
服務端將 Web Server 的處理結果響應給客戶端
客戶端接收服務端的響應,並渲染處理結果,如果響應內容需要請求其他靜態資源,通過 CDN 加速訪問所需資源。
客戶端將渲染好的視圖呈現出來並斷開 TCP/IP 連接

大廠面試題:今天覆試百度PHP工程師

11. CGI、FastCGI、PHP-CGI和PHP-FPM原理區別?

CGI:是公共網關接口 Web Server 與 Web Application 之間數據交換的一種協議。
FastCGI:FastCGI就像是一個常駐(long-live)型的CGI程序,它可以一直運行著。同 CGI,是一種通信協議,但比 CGI 在效率上做了一些優化。同樣,SCGI 協議與 FastCGI 類似。
PHP-CGI:是 PHP (Web Application)對 Web Server 提供的 CGI 協議的接口程序。
PHP-FPM:是 PHP(Web Application)對 Web Server 提供的 FastCGI 協議的接口程序,額外還提供了相對智能一些任務管理。

 

大廠面試題:今天覆試百度PHP工程師

12.服務器狀態碼200 300 400 500各代表的什麼?

1.200-成功
2.300-307表示要完成請求,需要進一步操作,代碼狀態通常為重定向
3.400-417表示請求可能出錯了,妨礙服務器處理
400-服務器不理解的請求語法
401-身份驗證錯誤
403-服務器拒絕請求
404-未找到網頁(最常見的了服務器狀態)
405-方法禁用
406-不接受(無法使用請求的內容特性響應請求的網頁)
407-需要代理授權
408-請求超時(服務器等待請求超時)
4.500-505表示:服務器在嘗試請求處理時發生內部錯誤,是服務器的錯,不是請求的錯
500-服務器內部錯誤(例如測試環境的服務器掛了)
501-服務器不具備完成請求的功能
502-錯誤網管
503-服務器不可用(超載或者停機維護,暫停的狀態)
504-網關超時
505-http版本不受支持(請求使用的http協議版本服務器不支持)


13.linux中把.c .h的文件編譯成.so文件,gcc瞭解嗎?

以下以編譯mylib.c為例講如何編譯.so文件。
首先,編譯mylib.c:
$gcc -c -fPIC -o mylib.o mylib.c
-c表示只編譯(compile),而不連接。-o選項用於說明輸出(output)文件名。gcc將生成一個目標(object)文件mylib.o。
注意-fPIC選項。PIC指Position Independent Code。共享庫要求有此選項,以便實現動態連接(dynamic linking)。
生成共享庫:
$gcc -shared -o mylib.so mylib.o
庫文件以lib開始。共享庫文件以.so為後綴。-shared表示生成一個共享庫。

14.Redis內存回收機制? 

volatile-lru:從已設置過期時間的數據集(server.db[i].expires)中挑選最近最少使用的數據淘汰
volatile-ttl:從已設置過期時間的數據集(server.db[i].expires)中挑選將要過期的數據淘汰
volatile-random:從已設置過期時間的數據集(server.db[i].expires)中任意選擇數據淘汰
allkeys-lru:從數據集(server.db[i].dict)中挑選最近最少使用的數據淘汰
allkeys-random:從數據集(server.db[i].dict)中任意選擇數據淘汰
no-enviction(驅逐):禁止驅逐數據


 Redis 在默認情況下會採用 noeviction 策略。換句話說,如果內存己滿 , 則不再提供寫入操作 , 而只提供讀取操作 。 顯然這往往並不能滿足我們的要求,因為對於互聯網系統而言 , 常常會涉及數以百萬甚至更多的用戶 , 所以往往需要設置回收策略。 需要指出的是 : LRU 算法或者 TTL 算法都是不是很精確算法,而是一個近似的算法。 Redis 不會通過對全部的鍵值對進行比較來確定最精確的時間值,從而確定刪除哪個鍵值對 , 因為這將消耗太多的時間 , 導致回收垃圾執行的時間太長 , 造成服務停頓。
15.爬蟲模擬登陸,如何跳過驗證碼?

1、爬取網站時經常會遇到需要登錄的問題,這是就需要用到模擬登錄的相關方法。python提供了強大的url庫,想做到這個並不難。
2、首先得明白cookie的作用,cookie是某些網站為了辨別用戶身份、進行session跟蹤而儲存在用戶本地終端上的數據。因此我們需要用Cookielib模塊來保持網站的cookie。
3、這個是要登陸的地址 1 和驗證碼地址 2
4、可以發現這個驗證碼是動態更新的每次打開都不一樣,一般這種驗證碼和cookie是同步的。其次想識別驗證碼肯定是吃力不討好的事,因此我們的思路是首先訪問驗證碼頁面,保存驗證碼、獲取cookie用於登錄,然後再直接向登錄地址post數據。


5、首先通過抓包工具或者火狐或者谷歌瀏覽器分析登錄頁面需要post的request和header信息。模擬登錄
驗證碼地址和post地址
將cookies綁定自動管理
使用用戶名和密碼
用代碼訪問驗證碼地址,獲取cookie
保存驗證碼到本地
打開保存的驗證碼圖片輸入
根據抓包信息 構造表單
根據抓包信息 構造headers
生成post數據 ?key1=value1&key2=value2的形式
構造request請求
打印登錄後的頁面
登錄成功後便可以利用該cookie訪問其他需要登錄才能訪問的頁面。

  


分享到:


相關文章: