天天看點

維護人員應該掌握的代碼

很多公司在招聘進階系統維護人員的時候,希望應聘者有一些開發經驗或者要會寫程式,至少也要讀得懂用某些語言寫的程式并能作簡單修改。這并非是無事找事,故意擡高門檻。實際上,有的時候,為了能夠更好地監控我們的系統,或者驗證我們安裝的系統滿足應用的要求,我們必須要使用一些代碼。比如,我們的應用伺服器 運作正常嗎?我們的資料庫連接配接正常嗎?我們的伺服器把 HTTP request 正确地傳給了我們的應用伺服器嗎?我們的MySQL + Resin 能正常處理漢字嗎? 這些在實踐中都是常常遇到的問題,下面我們來仔細說說。

一. 應用伺服器運作正常嗎?

相對于其它應用來說,WEB 應用比較特殊,因為它需要放到應用伺服器或者說 WEB 容器裡面來運作。由于既有 WEB 應用,又有 WEB 應用伺服器,兩者交織在了一起,當出現問題的時候,可能就會出現不能快速準确定位到底是 WEB 應用的問題還是 WEB 應用伺服器的問題。所有,我們應該有相應的措施來區分問題到底出現在哪個身上。筆者在實踐中采取的措施是,用了一個簡單的 JSP 頁面來實時驗證 WEB 應用伺服器的狀況,當監控系統(比如what'sup)保障的時候,監控人員隻需要通過檢視 WEB 應用伺服器監控頁面,就知道到底是哪個的問題了,然後采取相應的措施。筆者所用的代碼可以說是再簡單不過了:

# cat $RESIN_HOME/webapps/ROOT/test_resin.jsp

<%= 1 + 1 %>

然後,在 What'sup 裡面進行配置,讓它去 GET 該頁面,如果能夠取到值2, 就顯示正常,否則,報警。

二. 資料庫連接配接正常嗎?

有一段時間,資料庫老出問題,監控人員分不清到底是系統問題還是資料庫問題,就老是“騷擾”我,比較痛苦。為此,筆者“湊”了下面的代碼,來監控資料庫:

# cat $RESIN_HOME/webapps/ROOT/test_oracle.jsp

<%@ page contentType="text/html;charset=gb2312" import="java.sql.*" %>

<%

   // define variables

   String CLASS="oracle.jdbc.driver.OracleDriver";

   String NODE1_AND_DB="jdbc:oracle:thin:@(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 172.17.1.3)(PORT = 1521))(CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME =RACDB.GLOBAL)))";

   String NODE2_AND_DB="jdbc:oracle:thin:@(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 172.17.1.4)(PORT = 1521))(CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME =RACDB.GLOBAL)))";

   String USER="<username>";

   String PASSWORD="<password>";

   String SQL="select count(*) from tab";

   // init

   Connection conn = null;

   Statement stmt = null;

   ResultSet rs = null;

      // check NODE1

   try

   {

      Class.forName(CLASS);

      conn = DriverManager.getConnection(NODE1_AND_DB,USER,PASSWORD);

      stmt = conn.createStatement();

      rs=stmt.executeQuery(SQL);

      out.println("<br>");

      out.println("172.17.1.3 is OK");

   }

   catch(SQLException e)

      out.println("172.17.1.3 is not OK");

   } 

   finally

      try

      {

         if(rs != null) rs.close();

         if(stmt != null) stmt.close();

         if(conn != null) conn.close();

      }

      catch(SQLException e)

         out.println("DB close error " + getClass());

   // check NODE2

      conn = DriverManager.getConnection(NODE2_AND_DB,USER,PASSWORD);

      out.println("172.17.1.4 is OK");

      out.println("172.17.1.4 is not OK");

%>

由于我們的資料庫都是 RAC 來的,是以需要監控兩個結點,從上面的代碼可以看出,該頁面能夠監控RAC的兩個結點。然後,在 What'sup 裡面配置,讓它去 GET 該頁面,如果傳回"is OK",則顯示正常,否則,報警。

注意,盡管該代碼是監控 ORACLE RAC 的,但是隻要經過簡單修改,就可以用來監控其它資料庫了。相信讀者有修改這點簡單代碼的功力,是以筆者就不具體闡述了。

三. 伺服器把 HTTP request 正确地傳給了我們的應用伺服器嗎?

曾經遇到過一個怪事情,筆者維護的一台伺服器的 RESIN 不能正常處理 HTTP GET 請求,但是 telnet 8080 端口又沒有問題。開發人員懷疑,是不是筆者的伺服器有沒有把 HTTP GET 請求正确地發給 RESIN,或者是 RESIN 不能正确處理 HTTP GET 請求。于是,筆者搞了下面的代碼,來表明自己的“清白”,呵呵呵呵。

# cat $RESIN_HOME/webapps/ROOT/disp_http_request_header.jsp

<%@ page contentType="text/html; charset=gb2312" language="java" import="java.sql.*,java.util.*"%>

   out.print("1.Local Address:   " + request.getLocalAddr()  + "<br>");

   out.print("2.Local Name:      " + request.getLocalName()  + "<br>");

   out.print("3.Server Name:     " + request.getServerName() + "<br>");

   out.print("4.Server Port:       " + request.getServerPort() + "<br>");

   out.print("5.Remote Host:     " + request.getRemoteHost() + "<br>");

   out.print("6.User Agent:        " + request.getHeader("user-agent") + "<br>");

   out.print("7.User Agent:        " + request.getHeader("referer")    + "<br>");

   out.print("8.Protocol:            " + request.getProtocol()   + "<br>");

   out.print("9.Method:             " + request.getMethod()     + "<br>");

   out.print("10.Request URI:    " + request.getRequestURI() + "<br>");

   out.print("11.Servlet Path:     " + request.getServletPath()+ "<br>");

   out.print("12.Path Info:         " + request.getPathInfo()   + "<br>");

   out.print("13.Real Path:         " + request.getRealPath("/")+ "<br>");

然後,再從浏覽器裡面請求該頁面,一切正常。看來,不是筆者伺服器或者 RESIN 的問題。後來,經過開發的反複折騰,重要找到了問題,都是 filter 惹的禍 !!!

四. MySQL + Resin 能正常處理漢字嗎?

擺弄過 MySQL 5.0.x + Resin 3.0.x 的讀者可能遇到過,這種比較優秀的搭配,有時候在處理漢字的時候會“鬧鬼”,不能正常處理漢字。是以,我們在安裝了這個配置之後,最好是用代碼來驗證一下,自己的安裝配置有沒有問題。當然,首先你得保證,你的 LINUX 系統的字元集沒有問題,這樣配置 i18n 檔案可以保證你的 LINUX 系統字元集沒問題。

# cat /etc/sysconfig/i18n

LANG="zh_CN.GB18030"

LANGUAGE="zh_CN.GB18030:zh_CN.GB2312:zh_CN"

SUPPORTED="zh_CN.UTF-8:zh_CN:zh:en_US.UTF-8:en_US:en"

SYSFONT="lat0-sun16"

接下來,在安裝MySQL 5.0.x 的時候,選擇預設字元集為 gb2312。然後,就可以用下面的代碼來驗證了,

# cat $RESIN_HOME/webapps/ROOT/test_resin_mysql_cn.jsp

   String CLASS="com.mysql.jdbc.Driver";

   // note: default character set of mysql is gb2312

   //       version of connectorJ is greater 5.0 

   String dbString = "jdbc:mysql://localhost/test?user=admin&password=password&useUnicode=true&characterEncoding=gb2312";

   String SQL_create_table = "create table test.cn(col1 varchar(10))";

   String SQL_insert_cn = "insert into test.cn values('中文')";

   String SQL_select_cn = "select * from test.cn";

   // check

      conn = DriverManager.getConnection(dbString);

      stmt.execute(SQL_create_table);

      stmt.execute(SQL_insert_cn);

      rs = stmt.executeQuery(SQL_select_cn);

      while(rs.next())

         out.println(rs.getString("col1"));

         out.println("<br>");

      out.println("DB operation error " + getClass());

然後,用浏覽器去請求該頁面,如果你看到了“中文”這兩個字,恭喜你,你的安裝配置沒問題。

總之,上面的這些代碼并不複雜。但是,在實踐中,它們确實有用,所有,學學還是有好處的。

注意,盡管筆者是在 RESIN 裡面使用這些代碼,但是,毫無疑問,隻要稍做改變(甚至不需做任何改變),這些代碼也可以用在其它 WEB 應用伺服器裡面。

<a href="http://down.51cto.com/data/2349223" target="_blank">附件:http://down.51cto.com/data/2349223</a>

本文轉自zkjian517 51CTO部落格,原文連結:http://blog.51cto.com/zoukejian/58640