package test;
import java.rmi.RemoteException;
import javax.xml.namespace.QName;
import javax.xml.rpc.ServiceException;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
public class TstCall {
public static void main(String[] args) throws ServiceException, RemoteException {
//初始化参数
String chgKind = "1"; // 1:增加;2:变更
String workNo = "CY_yy" ;
String workNAme = "白莉";
String mobile = "15133333333";
String dealerId = "920301832";
String chgDate = "20160302";
String YGZurl = null ;
//创建服务
Service YGZservice = new Service();
//创建调用句柄
Call YGZcall = (Call) YGZservice.createCall();
//设置请求地址
YGZcall.setTargetEndpointAddress(YGZurl);
YGZcall.setOperationName(new QName(null, "IfService"));
try
{
Object o =YGZcall.invoke(new Object[] { "","123","Service","",
"<request><userlist><user><systemtype note=\"sour\">1</systemtype><kind note=\"chg\">"+chgKind+"</kind>"
+"<id note=\"num\">"+workNo+"</id><name note=\"numname\">"+workNAme+"</name><limit note=\"pp\">1</limit>"
+"<tel note=\"tel\">"+mobile+"</tel><belongfkid note=\"dealerID\">"+dealerId+"</belongfkid><starttime note=\"chgtime\">"+chgDate+"</starttime>"
+"</user></userlist></request>" });
}catch(Exception e) {
e.printStackTrace();
}
}
}
在window下执行都正常,但是在linux下执行报错:
执行语句:
java -jar -Djava.ext.dirs=/home/oracle/xf_everyday_check_p/javajar/lib/ test.jar
报错日志:
AxisFault
faultCode: {http://schemas.xmlsoap.org/soap/envelope...}Server.userException
faultSubcode:
faultString: java.lang.NullPointerException
faultActor:
faultNode:
faultDetail:
{http://xml.apache.org/axis/}stackTrace:java.lang.NullPointerException
at java.security.SecureRandom.nextBytes(SecureRandom.java:292)
at org.apache.axis.utils.SessionUtils.generateSessionId(SessionUtils.java:62)
at org.apache.axis.SOAPPart.<init>(SOAPPart.java:164)
at org.apache.axis.Message.setup(Message.java:377)
at org.apache.axis.Message.<init>(Message.java:246)
at org.apache.axis.client.Call.invoke(Call.java:2425)
at org.apache.axis.client.Call.invoke(Call.java:2366)
at org.apache.axis.client.Call.invoke(Call.java:1812)
at test.TstLinux.main(TstLinux.java:56)
{http://xml.apache.org/axis/}hostname:LN-CRM-APP
java.lang.NullPointerException
at org.apache.axis.AxisFault.makeFault(AxisFault.java:101)
at org.apache.axis.client.Call.invoke(Call.java:1828)
at test.TstLinux.main(TstLinux.java:56)
Caused by: java.lang.NullPointerException
at java.security.SecureRandom.nextBytes(SecureRandom.java:292)
at org.apache.axis.utils.SessionUtils.generateSessionId(SessionUtils.java:62)
at org.apache.axis.SOAPPart.<init>(SOAPPart.java:164)
at org.apache.axis.Message.setup(Message.java:377)
at org.apache.axis.Message.<init>(Message.java:246)
at org.apache.axis.client.Call.invoke(Call.java:2425)
at org.apache.axis.client.Call.invoke(Call.java:2366)
at org.apache.axis.client.Call.invoke(Call.java:1812)
... 1 more
由於java.security.SecureRandom在linux上依賴/dev/random (linux隨機數產生機制請參考這裡),因此在出現問題的伺服器上執行測試程式後執行測試腳本,結果如下:
[java] view plain copy
haitao-yao@haitaoyao-laptop:/data/develop/java/jre/lib/security$ jps && lsof /dev/random
7399 Jps
7382 TestRandom
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 7382 haitao-yao 4r CHR 1,8 0t0 4402 /dev/random
因此斷定是由於隨機數產生策略的問題。
google一下發現jetty的這個bug(Jetty HashSessionIdManager hangs on startup),也有人在jdk的bug database中提出過這個問題(參見這裡),簡單介紹一下:
java.security.SecureRandom依賴與/dev/random 生成隨機數,可能由於系統interrupt不足,導致在jdk在使用/dev/random時卡死。 jetty無法啟動,最後導致整個namenode啟動卡死。
解決方案在sun的bug database中也已經有人給出,即在java程式啟動參數中加入:-Djava.security.egd=file:/dev/urandom,使用/dev/urandom產生隨機數。
/dev/random和/dev/urandom的差異分析請參見這裡 , 不再多說。
總結:
hadoop透過http協定提供html頁面暴露系統內部狀態,這在分散式系統的設計上是個非常好的feature,但是由於整合了jetty,而整合的jetty在hadoop中可配置性又不強,才暴露了這個問題。非常不懂為什麼hadoop不使用獨立的線程去啟動內部的jetty,畢竟這並不是namenode的主要功能,因為這樣的附屬功能影響了系統的核心功能,未免有些得不償失。