成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

【PHP問(wèn)題定位】線上機(jī)器打日志混亂問(wèn)題定位分析

蘇丹 / 3123人閱讀

摘要:順風(fēng)車(chē)運(yùn)營(yíng)研發(fā)團(tuán)隊(duì)黃桃現(xiàn)象在線上腳本機(jī)器寫(xiě)入單條日志過(guò)長(zhǎng)時(shí)會(huì)出現(xiàn)交叉打印的現(xiàn)象被交叉的日志很有規(guī)律,都是單條日志過(guò)長(zhǎng)被截?cái)嗟?,建議優(yōu)化下此處寫(xiě)入日志的字符串長(zhǎng)度為原因分析腳本服務(wù)寫(xiě)入日志代碼如下在調(diào)用方法寫(xiě)入,為什么在寫(xiě)入超長(zhǎng)字符串是交叉

順風(fēng)車(chē)運(yùn)營(yíng)研發(fā)團(tuán)隊(duì) 黃桃

現(xiàn)象

在線上腳本機(jī)器寫(xiě)入單條日志過(guò)長(zhǎng)時(shí)會(huì)出現(xiàn)交叉打印的現(xiàn)象:


被交叉的日志很有規(guī)律,都是單條日志過(guò)長(zhǎng)被截?cái)嗟模ㄗh優(yōu)化下 /*/ruleanalysis.php:68 此處寫(xiě)入日志的字符串長(zhǎng)度為: int(25909)

原因分析

腳本服務(wù)寫(xiě)入日志代碼如下:

if ($this->isCli == true) {
    return file_put_contents($messageLogFile, $strLogMsg, FILE_APPEND);
    //在調(diào)用file_put_contents 方法寫(xiě)入,為什么在寫(xiě)入超長(zhǎng)字符串是交叉寫(xiě)呢?
    //跟進(jìn)下file_put_contents函數(shù)的實(shí)現(xiàn)?
}

查看file_put_contents 的源碼實(shí)現(xiàn),最終寫(xiě)文件會(huì)執(zhí)行到_php_stream_write_buffer 函數(shù),里面有這樣一處代碼:


明確幾個(gè)變量的含義:
count:需寫(xiě)入文件的字符串長(zhǎng)度
stream->chunk_size :默認(rèn)為8192 (8k)

從上面代碼可以看出,當(dāng)寫(xiě)入的字符串長(zhǎng)度 大于8192時(shí),則拆為多次<=8192的字符串,然后調(diào)用php_stdiop_write函數(shù)寫(xiě)入文件,php_stdiop_write函數(shù)實(shí)現(xiàn)如下:

static size_t php_stdiop_write(php_stream *stream, const char *buf, size_t count)
{
    php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract;
 
    assert(data != NULL);
 
    if (data->fd >= 0) {
#ifdef PHP_WIN32
        int bytes_written;
        if (ZEND_SIZE_T_UINT_OVFL(count)) {
            count = UINT_MAX;
        }
        bytes_written = _write(data->fd, buf, (unsigned int)count);
#else
        int bytes_written = write(data->fd, buf, count);
#endif
        if (bytes_written < 0) return 0;
        return (size_t) bytes_written;
    } else {
 
#if HAVE_FLUSHIO
        if (!data->is_pipe && data->last_op == "r") {
            zend_fseek(data->file, 0, SEEK_CUR);
        }
        data->last_op = "w";
#endif
 
        return fwrite(buf, 1, count, data->file);
    }
}

php_stdiop_write 則調(diào)用的 write函數(shù) 寫(xiě)入文件;write函數(shù)是能保證一次寫(xiě)入的完整的。

所以日志寫(xiě)串的原因也就能分析出來(lái)了,調(diào)用鏈接為:file_put_contents ->_php_stream_write_buffer ->php_stdiop_write(多次調(diào)用,每次最多寫(xiě)入8192字節(jié)) ->write(),是在 多次調(diào)用php_stdiop_write 函數(shù)時(shí)出的問(wèn)題;第一次寫(xiě)完,緊接著在高并發(fā)的情況下,被其他進(jìn)程的 write 函數(shù)追著寫(xiě),此時(shí)就出現(xiàn)寫(xiě)串,也就是前面示例中日志;

為了證實(shí)此觀點(diǎn),我對(duì)報(bào)錯(cuò)的代碼 /**/ruleanalysis.php:68 寫(xiě)了如下偽代碼:

public function run()
    {
        $this->mysqlConnect();
        $sql = "select * from  *** where ***=1";
        $pidRet = $this->db->run($sql);
        UtilsLogger::notice("tiger_project_info:".json_encode($pidRet));
        die;
}
vim   ~/*****/logger.php
if ($this->isCli == true) {
    var_dump(substr($strLogMsg ,16084 ,400 ));  //在字符串的8192倍數(shù)的位置打出附近的字符串  16384 = 8192 * 2 
    return file_put_contents($messageLogFile, $strLogMsg, FILE_APPEND);
}

執(zhí)行代碼看打串日志的地方是否為8192倍數(shù)的位置,結(jié)果如下:

截?cái)嗟奈恢梅浅=咏?192的倍數(shù)值;但因?yàn)槎ㄎ粫r(shí)間不是當(dāng)時(shí)的時(shí)間點(diǎn),期間數(shù)據(jù)庫(kù)存在部分改動(dòng),所以出現(xiàn)偏移,那么也能驗(yàn)證我們之前的猜想,正是file_put_contents 多次調(diào)用write函數(shù)的時(shí)候出現(xiàn)交叉打印。

問(wèn)題解決:

1、修改打日志處代碼,這么巨大的日志寫(xiě)入文件是否合理?
2、需要寫(xiě)入巨大日志又不希望不被交叉打印,加上LOCK_EX 標(biāo)識(shí);

file_put_contents函數(shù)相關(guān)的知識(shí)點(diǎn)問(wèn)答 1、file_put_contents(filename,msg ,FILE_APPEND ) 末尾追加實(shí)現(xiàn)?

FILE_APPEND文件追加的形式,這個(gè)是怎么實(shí)現(xiàn)的呢?
先標(biāo)識(shí) mode[0] =‘a(chǎn)’

緊接著轉(zhuǎn)換成:O_CREAT|O_APPEND

調(diào)用 open函數(shù) ,fd = open(realpath, open_flags, 0666);

通過(guò) C底層函數(shù)保證,寫(xiě)入默認(rèn)追加寫(xiě);

2、file_put_contents(filename,msg ,FILE_APPEND|LOCK_EX ) 中的 LOCK_EX實(shí)現(xiàn)?作用?

file_put_contents在調(diào)用_php_stream_write_buffer 前加一個(gè)鎖 php_stream_supports_lock(stream) ->flock()
得到文件鎖定后 調(diào)用_php_stream_write_buffer->多次 write();

寫(xiě)完后釋放文件鎖

php_stream_close(stream)->close(data->fd); //直接關(guān)閉

總結(jié):LOCK_EX 保證了一個(gè)巨大字符串的完整,不會(huì)被寫(xiě)串;

3、多進(jìn)程,file_put_contents()數(shù)據(jù)覆蓋嗎?

write調(diào)用路徑:file_put_contents ->_php_stream_write_buffer ->php_stdiop_write(多次調(diào)用,每次最多寫(xiě)入8192字節(jié)) ->write()
file_put_contents($messageLogFile, $strLogMsg, FILE_APPEND);
write函數(shù)在O_APPEND模式下,偏移到文件末尾與寫(xiě)文件是原子性的,不存在被覆蓋的情況;

4、以O(shè)_APPEND方式打開(kāi)文件,然后使用lseek,定位到文件首部,然后調(diào)用write會(huì)怎樣?是寫(xiě)在文件結(jié)尾嗎?

還是寫(xiě)在文件尾部,參考文章:https://blog.csdn.net/dog250/...

write函數(shù)代碼如下:

+static inline loff_t file_pos_read_lock(struct file *file)
{
    + if (file->f_mode & FMODE_LSEEK)
    + mutex_lock(&file->f_pos_lock);
    return file->f_pos;
}
+static inline void file_pos_write_unlock(struct file *file, loff_t pos)
{
    file->f_pos = pos;
    + if (file->f_mode & FMODE_LSEEK)
    + mutex_unlock(&file->f_pos_lock);
}
修改sys_write系統(tǒng)調(diào)用:
file = fget_light(fd, &fput_needed);
if (file) {
    - loff_t pos = file_pos_read(file);
    + loff_t pos = file_pos_read_lock(file);
    ret = vfs_write(file, buf, count, &pos);
    - file_pos_write(file, pos);
    + file_pos_write_unlock(file, pos);
    fput_light(file, fput_needed);
}
5、進(jìn)程內(nèi)多次file_put_contents,open和close只有一次還是多次?

open調(diào)用路徑:file_put_contents->php_stream_open_wrapper_ex->php_plain_files_stream_opener->php_stream_fopen_rel->fd = open(realpath, open_flags, 0666);
close調(diào)用路徑:file_put_contents->php_stream_close->php_stdiop_close->ret = close(data->fd);

每次都會(huì)執(zhí)行 open和close

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/28905.html

相關(guān)文章

  • PHP問(wèn)題定位】2018-07-02 fpm掉底分析

    摘要:順風(fēng)車(chē)運(yùn)營(yíng)研發(fā)團(tuán)隊(duì)黃桃問(wèn)題現(xiàn)象某機(jī)器這段時(shí)間出現(xiàn)掉地的報(bào)警如圖原因分析查看當(dāng)時(shí)的監(jiān)控,等今天出現(xiàn)兩次突降,一次是點(diǎn)左右,一次是左右,查看整周也經(jīng)常出現(xiàn)突降,如圖在分時(shí)突然升高也在時(shí)出現(xiàn)大量寫(xiě)當(dāng)時(shí)短暫出現(xiàn)降低,之后出現(xiàn)徒 順風(fēng)車(chē)運(yùn)營(yíng)研發(fā)團(tuán)隊(duì) 黃桃 問(wèn)題現(xiàn)象某機(jī)器這段時(shí)間出現(xiàn)cpu-idle掉地的報(bào)警 如圖: showImg(https://segmentfault.com/img/bVb...

    Code4App 評(píng)論0 收藏0
  • 不改一行代碼定位線上性能問(wèn)題

    摘要:背景最近時(shí)運(yùn)不佳,幾乎天天被線上問(wèn)題騷擾。工具分析所以最好的方式就是不改動(dòng)一行代碼把這個(gè)問(wèn)題分析出來(lái)。我們選用了阿里以前開(kāi)源的來(lái)使用。因?yàn)檫@個(gè)項(xiàng)目阿里多年沒(méi)有維護(hù)了,還殘留一些我在它原有的基礎(chǔ)上修復(fù)了個(gè)影響使用的,同時(shí)做了一些優(yōu)化。 showImg(https://segmentfault.com/img/remote/1460000016978923?w=1920&h=1080); ...

    DangoSky 評(píng)論0 收藏0
  • 企業(yè)互聯(lián)網(wǎng)應(yīng)用高性能解決之道

    摘要:本文介紹了企業(yè)互聯(lián)網(wǎng)開(kāi)發(fā)及運(yùn)維的一些實(shí)踐,深入剖析了互聯(lián)網(wǎng)項(xiàng)目開(kāi)發(fā)及上線過(guò)程中的各種痛點(diǎn)及解決之道。線上出錯(cuò),我們通過(guò)收集服務(wù)器端應(yīng)用性能數(shù)據(jù)的方式,實(shí)時(shí)展示應(yīng)用的調(diào)用拓?fù)鋱D,并根據(jù)出現(xiàn)異常的請(qǐng)求,進(jìn)行下鉆,定位出具體出現(xiàn)問(wèn)題的代碼。 本文介紹了企業(yè)互聯(lián)網(wǎng)開(kāi)發(fā)及運(yùn)維的一些實(shí)踐,深入剖析了互聯(lián)網(wǎng)項(xiàng)目開(kāi)發(fā)及上線過(guò)程中的各種痛點(diǎn)及解決之道。一個(gè)互聯(lián)網(wǎng)項(xiàng)目的上線并不是那么容易,需要經(jīng)過(guò)很多的環(huán)...

    Alan 評(píng)論0 收藏0
  • 線上系統(tǒng)性問(wèn)題定位與方法論

    摘要:很顯然對(duì)于不同規(guī)模,不同功能的系統(tǒng),這個(gè)問(wèn)題無(wú)法一概而論。生產(chǎn)事件上報(bào)客服上報(bào)此類(lèi)問(wèn)題往往來(lái)自用戶投訴,最重要的就是問(wèn)題現(xiàn)象的復(fù)現(xiàn)。線上問(wèn)題處理的核心是快速修復(fù)。以上說(shuō)的都是問(wèn)題發(fā)生后的消極應(yīng)對(duì)措施。 前言一線程序員在工作中經(jīng)常需要處理線上的問(wèn)題或者故障,但工作幾年下來(lái)發(fā)現(xiàn),有些同事其實(shí)并不知道該如何去分析和解決這些問(wèn)題,毫無(wú)章法的猜測(cè)和嘗試,雖然在很多時(shí)候可以最終解決問(wèn)題,但往往也會(huì)浪費(fèi)大...

    leonardofed 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<