#1 問題描述# 用 Hessian 實現 web service 過程當中,須要建立對象時,是使用 HTTP POST 方法來傳遞數據的。可是在有反向代理 (nginx)
的狀況下,會拋出異常 (com.caucho.hessian.client.HessianConnectionException: 411:java.io.IOException: Server returned HTTP response code: 411 for URL:http://xxxx/xxx/xxxService) 。java
首先來看下 HTTP 411 錯誤的解釋: Length Required 服務器不能處理請求,除非客戶發送一個 Content-Length 頭
。( HTTP 1.1 新)這是由於Hessian 與服務端通訊默認是採起分塊的方式 (chunked encoding) 發送數據,而反向代理要得到 Content-Length 這個頭,才能處理請求,可是 Hessian 的請求中並無加入這個參數
。nginx
#2 排查過程#git
#3 解決問題# com.caucho.hessian.client.HessianProxyFactory 類中,有一個 boolean _chunckedPost 的域成員,其默認值爲 true
。這個值就是規定 Hessian 是否以分塊發送的方式與服務端交換數據的參數,所以在建立 com.caucho.hessian.client.HessianProxyFactory 的對象後(假設爲 factory ),只要調用其上的 setChunckedPost() 方法,把這個屬性設置爲 false 便可。即 factory.setChunkedPost(false);github
#4 問題總結# 分塊編碼 (chunked encoding) 傳輸方式
是 HTTP 1.1 協議中定義的 Web 用戶向服務器提交數據的一種方法,當服務器收到 chunked 編碼方式的數據時會分配一個緩衝區存放之,若是提交的數據大小未知,客戶端會以一個協商好的分塊大小向服務器提交數據。web
若是不使用 Chunked encoding 傳輸方式,須要將要發送的數據緩存下來,計算出 content-length ,從而知足反向代理( Nginx )須要 content-length 的要求
。緩存
該問題還能夠經過修改 nginx 配置,使得 nginx 能夠處理分塊編碼 (chunked encoding) 傳輸方式。在使用Nginx 1.3.9如下版本,都存在當用戶POST一個帶有文件的請求的時候,出現HTTP 411錯誤。 這個是Nginx的問題,須要打一個補丁。服務器
#下載chunkin模塊 git clone https://github.com/agentzh/chunkin-nginx-module.git #編譯nginx,使用chunkin模塊 wget http://nginx.org/download/nginx-1.2.7.tar.gz tar xvzf nginx-1.2.7.tar.gz cd nginx-1.2.7 ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-http_gzip_static_module --with-google_perftools_module --with-http_realip_module --add-module=../chunkin-nginx-module make -j8 make install
添加 HttpChunkinModule 解決。因爲這個模塊已經內置到了 nginx 1.3.9 之後的 nginx 核心了,因此原來的 nginx 1.4.x 沒有這個問題。模塊介紹和具體安裝過程見:http://wiki.nginx.org/HttpChunkinModule,把這個模塊編譯進去後給 server 節點添加一個配置就能夠了:ui
server { chunkin on; error_page 411 = @my_411_error; location @my_411_error { chunkin_resume; } }
以後重啓nginx就能夠了。google