Joe Horn 的啟示錄
Joe Horn's Blog
  • LinkedIn
  • Facebook
  • Instagram
  • GitHub
  • Docker Hub
RSS
  • VPS Referrals
  • My Plurk
  • My Plurk Bot

7 月 24 2019

Logstash 筆記

為了分析某些儲存在 MySQL 的 log,敝單位在兩年前(2017)導入 Logstash;當時我們用最新的 5.5.1 版,運作狀況還不錯,所以就沒什麼人理它…
最近冒出問題,救完火後寫個紀錄。

第一個問題是這個:

[WARN ][logstash.inputs.jdbc ] Exception when executing JDBC query {:exception=>#<Sequel::DatabaseError: Java::ComMysqlJdbcExceptionsJdbc4::MySQLDataException: ‘2.147483727E9’ in column ‘1’ is outside valid range for the datatype INTEGER.>}

資料的第一個欄位是 auto-increment 的 ID,看到 ‘2.147483727E9’ 就聯想到是 32 位元正整數溢位問題。
我們先換 MySQL Connector/J (& 改用 OpenJDK);換完之後,看到的錯誤訊息變成這樣:

[WARN ][logstash.inputs.jdbc ] Exception when executing JDBC query {:exception=>#<Sequel::DatabaseError: Java::JavaSql::SQLDataException: Value ‘2147483727’ is outside of valid range for type java.lang.Integer>}

於是我們就開始升版 Logstash;目前最新的版本是 7.2.0,但 官方的 migration guide 說要先升版到 6.7。
最後我們順利升上 7.2.0,在過程中也發現 6.7.2 已無 32 位元正整數溢位問題。

第二個問題發生在升版後:
DATETIME 欄位存放的 ‘2019-07-23 14:18:59’ 抓成 ‘2019-07-23T19:18:59.000Z’。
沒人能保證系統/伺服器會跨多少時區,為免夜長夢多,我們的解決方式是轉成 UNIX timestamp。
(Year 2038 problem? 以後再說! XD )

By Joe Horn • Computer Software 0 • Tags: JDBC, Logstash, MySQL

5 月 30 2019

Toshiba KXG6AZNV512G on Lenovo T590

Toshiba KXG6AZNV512G 是 M.2 2280 規格的 NVMe SSD;官網可以查得 XG6 Series 產品資訊頁。

By Joe Horn • Computer Hardware 0 • Tags: KXG6AZNV512G, Lenovo, T590, Toshiba

5 月 26 2019

HTTP 壓縮的 workaround : ProgressEvent & Cache-Control

這幾個月前後經手處理兩個 HTTP 壓縮相關的問題,寫個紀錄…

第一個問題跟 ProgressEvent 有關。
敝單位有個 PWA ( Progressive Web Application ),幾個月前釋出一個新模組,讓 user 可獲取公司內部發佈的公告訊息。考量到訊息內容長度與行動裝置所在網路環境,我們便試著在訊息載入時加上進度條 (Progress Bar)。
實作期間,我們發現只能取得 ProgressEvent.loaded,抓不出 ProgressEvent.total,而且這個現象僅發生在 server response,瀏覽器發出請求/上傳檔案無此狀況。
確認這現象跟 HTTP 壓縮有關後,我們也發現 ProgressEvent.loaded 的值是未壓縮前的大小。
目前我們採用的解法是在讀取內容前先發個 HTTP request 取得內容長度,用該值取代 ProgressEvent.total。

第二個問題被發現時,我們正在調整 Cache-Control 設定;而且這問題只跟 Apache HTTPD 有關。
我們讓 HTTP server 壓縮 .js , .css , .htm 這類固定文字檔,也加上這串 HTTP header :

Cache-Control: public, max-age=86400, no-cache

但我們發現瀏覽器在 nginx 可正確獲得 304 Not Modified,但遇上 Apache HTTPD 永遠都是 200 OK。
花一堆時間測試/追蹤後發現兇手是 mod_deflate;原因是檔案被壓縮處理後,傳給瀏覽器的 HTTP ETag 後面被加上 “-gzip” 這串後綴。
目前的解法是參考這篇,用下面這段設定處理 .js , .css , .htm 這類固定文字檔的 Cache-Control:

RequestHeader edit "If-None-Match" "^\"(.*)-gzip\"$" "\"$1\""
Header edit "ETag" "^\"(.*[^g][^z][^i][^p])\"$" "\"$1-gzip\""

Apache HTTPD 2.5 版的 mod_deflate 應該會多個 DeflateAlterETag 供作調整;等吧… XD

By Joe Horn • WWW 0 • Tags: Apache HTTPD, Cache-Control, HTTP compression, mod_deflate, ProgressEvent

4 月 7 2019

Toshiba KBG30ZMT128G on Lenovo L580

Toshiba KBG30ZMT128G 是 M.2 2242 規格的 NVMe SSD。
在 Google 用這個型號查詢,得到的官網零售產品是 RC100;KBG30ZMT 應該是出貨給廠商裝機用的版本。

By Joe Horn • Computer Hardware 0 • Tags: KBG30ZMT128G, L580, Lenovo, Toshiba

3 月 16 2018

開始用 Let’s Encrypt 的 wildcard certificate

2016 年自己寫過 改用 Let’s Encrypt 的 certificates,文內提到的 dehydrated 也持續在使用。

這幾天看到 Let’s Encrypt 貼出 ACME v2 and Wildcard Certificate Support is Live。

Let’s Encrypt 的 wildcard certificate 實作大概要注意以下幾點:

  • 要用 ACME v2 compatible client(官方有提供列表: ACME Client Implementations)
  • 不能用 HTTP challenge,改用 DNS challenge

使用 dehydrated 進行 DNS challenge 可以參考這幾份文件:

  • dehydrated / docs / dns-verification.md
  • dehydrated Wiki : Examples for DNS 01 hooks

我選擇用 nsupdate 的方式(參考 dehydrated Wiki : example dns 01 nsupdate script),在 DNS master server 建立 _acme-challenge.{DOMAIN} 的 NS record,讓 hook script 透過 nsupdate 連線到指定的 name server 更新 TXT record 。

DNS 方面完成後,要記得佈署 hook script 與 nsupdate 使用的 key。
接著是調整語法,原本的語法:

/SOMEWHERE/dehydrated/dehydrated -c -d {網站hostname}

改為:

/SOMEWHERE/dehydrated/dehydrated \
    -c -d *.{DOMAIN} \
    -t dns-01 -k {HOOK_SCRIPT} \
    --alias wildcard.{DOMAIN}

( –alias 指定的 wildcard.{DOMAIN} 會成為目錄名稱,用來存放憑證 )

By Joe Horn • WWW 0 • Tags: certificate, dehydrated, DNS, HTTPS, Let's Encrypt, nsupdate, SSL

12 月 4 2017

PHP 的 MySQL driver/library 與記憶體耗用

再來還些債…

前陣子我們家在看一些 PHP 的版本差異,也順便拆一些地雷。
先說記憶體耗用,我們用下面這段程式在一些 PHP 版本上執行,觀察記憶體耗用:

<?php
$a = memory_get_usage();
echo "begin:\t$a" . PHP_EOL;

$arr = array();
for ( $i = 0; $i < 100000; $i++ ) {
    array_push($arr, $i);
}

$b = memory_get_usage();
echo "end:\t$b" . PHP_EOL;

echo "diff:\t" . ($b - $a) . PHP_EOL;

在 PHP 5.1 ( on 32-bit Linux ) 觀察到的記憶體差距值大約是 5.8 MB,在 PHP 5.3 ~ 5.6 ( on 64-bit Linux ) 觀察到的記憶體差距值大約是 14 MB,而 PHP 7.1 ~ 7.2 ( on 64-bit Linux ) 觀察到的記憶體差距值大約是 4 MB。

至於 PHP 的 MySQL driver/library 方面…
參考官方提供的 Overview of the MySQL PHP drivers : Buffered and Unbuffered queries ;PHP 的所有的 MySQL extensions 預設使用 buffered mode,所以在撈取大量資料時,PHP 執行完 SQL statement 就會耗用大量記憶體。
另外,在官方提供的 Overview of the MySQL PHP drivers : Choosing a library 可以看到,PHP 5.3 以前的預設 MySQL driver ( libmysqlclient ) 沒使用 PHP 的原生記憶體管理,PHP 5.3 之後的預設 MySQL driver ( mysqlnd; MySQL Native Driver) 才開始用。
對這些行為,我們另外生了一段測試程式:

<?php
$a = memory_get_usage();
echo "begin:\t\t$a" . PHP_EOL;

$dbConn = new PDO(.....);
$b = memory_get_usage();
echo "new PdoMySQL:\t$b\t\tDiff: " . ($b - $a) . PHP_EOL;

$st = $dbConn->query("SELECT * FROM testTable LIMIT 30000");

$b = memory_get_usage();
echo "get Stmt:\t$b\tDiff: " . ($b - $a) . PHP_EOL;

$row1 = $st->fetch();

$b = memory_get_usage();
echo "fetch once:\t$b\tDiff: " . ($b - $a) . PHP_EOL;

$row2 = $st->fetch();

$b = memory_get_usage();
echo "fetch twice:\t$b\tDiff: " . ($b - $a) . PHP_EOL;

$st->closeCursor();

$b = memory_get_usage();
echo "closeCursor:\t$b\t\tDiff: " . ($b - $a) . PHP_EOL;

$row3 = $st->fetch();
$b = memory_get_usage();
echo "fetch:\t\t$b\t\tDiff: " . ($b - $a) . PHP_EOL;

var_dump($row3);

在 PHP 7.1 ( with mysqlnd , 64-bit Linux ) 的數據如下:

begin:          355552
new PdoMySQL:   378784          Diff: 23232
get Stmt:       25866944        Diff: 25511392
fetch once:     25868752        Diff: 25513200
fetch twice:    25870568        Diff: 25515016
closeCursor:    384104          Diff: 28552
fetch:          384104          Diff: 28552
bool(false)

在 PHP 5.1 ( with libmysqlclient , 32-bit Linux ) 的數據則是:

begin:          50432
new PdoMySQL:   85752           Diff: 35320
get Stmt:       92184   Diff: 41752
fetch once:     93584   Diff: 43152
fetch twice:    95248   Diff: 44816
closeCursor:    95312           Diff: 44880
fetch:          95400           Diff: 44968
bool(false)

應該有為數不少的 PHP developers 曾經踩過這種記憶體相關的地雷… XD

By Joe Horn • PHP 0 • Tags: libmysqlclient, memory, MySQL, mysqlnd, PHP

11 月 30 2017

PHPExcel 的活頁簿標題 ( SheetTitle ) 處理

之前曾經使用 PHPExcel 踩到地雷,處理完之後一直忘記載這邊留個紀錄(拖稿?)。

Excel 的活頁簿標題有字元 & 長度限制,但 library ( PHPExcel ) 沒有特別判斷 & 處理,所以…

    // Excel 的活頁簿 title 不允許 * : / \ ? [ ]
    $currTitle = str_replace(
        array('*', ':', '/', '\\', '?', '[', ']'),
        "",
        $currTitle
    );

    // 字數上限 31,保守抓 30
    $maxByte = 90;
    $chars = mb_strlen($currTitle, 'UTF-8');
    while ( $chars > 30 ) {
        $currTitle = mb_strcut($currTitle, 0, $maxByte, 'UTF-8');
        $chars = mb_strlen($currTitle, 'UTF-8');
        $maxByte--;
    }

By Joe Horn • PHP 0 • Tags: PHP, PHPExcel

2 月 22 2016

改用 Let’s Encrypt 的 certificates

之前都在用 StartSSL 的免費 certificate,雖知道有 Let’s Encrypt,但因手邊幾乎都轉用 nginx,遲遲沒下手。

約莫一週前 zeroplex 丟了這個網頁:「Why I stopped using StartSSL (Hint: it involves a Chinese company)」,三、四天前 DK 大神也撰文提及,就決定趁週末沒什麼事來動工…

用 DK 大神在一個月前撰文提過的 dehydrated 這個 GitHub 專案可以輕鬆搞定,步驟大致如下…

  1. 找個自己喜歡的目錄(不是 /tmp …),把 dehydrated clone 出來
  2. 在 clone 出來的目錄之下建立 .acme-challenges 目錄
    mkdir dehydrated/.acme-challenges
  3. 在原本的 HTTP (80 port) 設定下建立 alias,把網站的 /.well-known/acme-challenge 指向剛建立好的目錄
  4. 讓 HTTP daemon 重讀設定
  5. 執行這個指令
    dehydrated/dehydrated -c -d {網站hostname}
  6. 完成 & 成功後就會在 dehydrated/certs 發現目錄,目錄下有數個檔案
  7. 我自己讓 nginx 使用 fullchain.pem 跟 privkey.pem,設定大致如下:
    server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
    
        ssl on;
        ssl_certificate /SOMEWHERE/dehydrated/certs/{網站hostname}/fullchain.pem;
        ssl_certificate_key /SOMEWHERE/dehydrated/certs/{網站hostname}/privkey.pem;
        ssl_trusted_certificate /SOMEWHERE/dehydrated/certs/{網站hostname}/fullchain.pem;
        ....
    }
    

我記得 Let’s Encrypt 的 certificate 要在 90 天內 renew,所以 cron job 這樣放:

0 0 1 */2 * /SOMEWHERE/dehydrated/letsencrypt.sh -c -d {網站hostname} &gt; /dev/null 2&gt;&amp;1

Updated : letsencrypt.sh 改為 dehydrated 。

By Joe Horn • WWW 0 • Tags: certificate, dehydrated, HTTPS, Let's Encrypt, letsencrypt.sh, nginx, SSL, StartSSL

12 月 10 2015

網頁相關技術的抉擇

以往的網頁純粹就是 HTML,之後的動態網頁技術 ( CGI、PHP、ASP、JSP、… )、CSS、VBScript、Javascript 雖讓網頁內容/效果愈來愈多元,網頁開發/維護難度的關鍵亦僅取決於語言的熟悉度。

近幾年則是冒出了不少網頁前端 frameworks。 node.js、io.js 與 React、Angular、Backbone、Ember、…,雖說是使用相同的程式語言,但各種 frameworks 的選用與導入著實讓不少網頁前端開發人員頭疼。

考量多螢、多裝置的兼容性, COSCOP 2015 就有人提出 “每18至24個月,前端技術的難度會增加一倍以上”。
但… 真只有網頁前端開發人員的日子愈來愈難熬嗎?
SQL Injection、XSS、CORS 等議題與考量呢?

我個人一直認為程式語言只是工具,沒特別去吹捧某特定程式語言;同理,我也把 frameworks 當作是工具。
我們看到的一些新技術/framework 固然很好,真有立即導入的必要性嗎?
若看到新的技術屏除跟風心態,先稍作觀望,讓環境的變化幫我們除強汰弱,另一方面加強人員的教育訓練,新技術導入前仔細評估,審慎抉擇,是否網頁開發人員就可以不必過得如此辛苦?

By Joe Horn • Thoughts, WWW 0 • Tags: framework, front-end developer, web, web developer

8 月 25 2015

調整 Apache HTTPD & Apache Tomcat & nginx 的 content cache & compression

前陣子調整了一些 Apache HTTPD & Tomcat & nginx 的 cache 機制與內容壓縮機制,稍微紀錄一下。

Apache HTTPD 的 cache:

<IfModule mod_expires.c>
  ExpiresActive On
  ExpiresByType image/gif "access plus 1 month"
  ExpiresByType image/jpeg "access plus 1 month"
  ExpiresByType image/png "access plus 1 month"
  ExpiresByType text/css "access plus 1 month"
</IfModule>

Apache HTTPD 的壓縮:

<IfModule mod_deflate.c>
  DeflateCompressionLevel 9
  AddOutputFilterByType DEFLATE text/html text/plain text/xml application/x-httpd-php
  AddOutputFilter DEFLATE js css
</IfModule>

Apache Tomcat 的 cache(在 application 的 web.xml 做調整):

  <filter>
    <filter-name>ExpiresFilter</filter-name>
    <filter-class>org.apache.catalina.filters.ExpiresFilter</filter-class>
    <init-param>
      <param-name>ExpiresByType image</param-name>
      <param-value>access plus 1 month</param-value>
    </init-param>
    <init-param>
      <param-name>ExpiresByType text/css</param-name>
      <param-value>access plus 1 month</param-value>
    </init-param>
    <init-param>
      <param-name>ExpiresByType application/javascript</param-name>
      <param-value>access plus 1 month</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>ExpiresFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
  </filter-mapping>

Apache Tomcat 的壓縮(在 conf/server.xml 做調整):

<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               compression="on" compressableMimeType="text/html,text/xml,text/plain,text/css,application/javascript"
               redirectPort="8443" />

nginx 的 cache(在 server tag 內做調整):

location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
    expires 1M;
}

nginx 的壓縮(在 http tag 內做調整):

gzip_vary on;
gzip_proxied any;
gzip_comp_level 9;
gzip_buffers 8 32k;
gzip_http_version 1.0;
gzip_types text/plain text/css application/json
           application/javascript application/x-javascript text/javascript
           text/xml application/xml application/rss+xml application/atom+xml application/rdf+xml;

大概就調這些,其他多媒體檔案就看需求了…

By Joe Horn • WWW 0 • Tags: Apache HTTPD, Apache Tomcat, cache, compression, deflate, gzip, nginx

«‹ 2 3 4 5›»

Site Info

All content on this Blog is licensed under CC BY-NC-SA 4.0

About Me

profile for Joe Horn at Stack Overflow, Q&A for professional and enthusiast programmers


My mail!

獅子座

Coffee Powered!

F1 fans

motoGP fans

Linkin Park

I am a Taiwanese!

Recent Comments

  • Avatar of johnpupu johnpupu: PHP 還有這個 phpsavant.c……
  • Avatar of Jerry Jerry: 这个不是foreach的问题。 0 ==……
  • Avatar of Joe Horn Joe Horn: 看來問題在 if ... else ..……
  • Avatar of jnlin jnlin: 因為 'b' 被轉型成 0 了…
  • Avatar of 路人 路人: 跟 foreach 沒有關係 ?…
  • Avatar of bill bill: 註冊表那裡要設定 BasicAuthLe……
  • Avatar of 虫 虫: .svn 的檔案減少可以增加在 wind……
  • Avatar of mars mars: 如果說寫程式是理性極致的話,那寫小說就是……
  • Avatar of Joe Horn Joe Horn: 已更新文章。…
  • Avatar of jackcal jackcal: joehorn.idv.tw關於轉貼 h……

Post Categories

  • About My Sites (16)
  • Computer Hardware (28)
  • Computer Software (45)
  • Database (23)
  • FreeBSD (21)
  • Funny (14)
  • Life (23)
  • Linux (5)
  • Mail (19)
  • Network (12)
  • Programing (40)
    • .NET (5)
    • JAVA (2)
    • Javascript (6)
    • PHP (29)
  • Thoughts (34)
  • Windows (13)
  • WWW (79)
    • phpBB (7)
    • WordPress (18)

Blogroll

  • 這裡沒有美食

Tags Cloud

AMD Apache benchmarking Bloglines Coppermine DNSBL eAccelerator fio Firefox free FreeBSD Gmail Google HDD Hsin-chu HTTPS IE Intel Javascript Lenovo Longhorn Microsoft MSN MySQL Office Percona XtraBackup performance PHP phpBB pirate Postfix restaurant RSS security sendmail software SpamAssassin SSL Subversion Taiwan theme translation Windows WordPress Yahoo

Ads

↑

© Joe Horn 的啟示錄 2025
Powered by WordPress • Themify WordPress Themes