qileilove

blog已经转移至github,大家请访问 http://qaseven.github.io/

从Unix到Linux的迁移部署:移植、升级和测试

 从Unix迁移到Linux,在最初阶段,应该建立一个沙盘环境用于测试。也许您的整个团队都没有Linux方面的经验,有这样一个沙盘环境能帮上大忙(无需担心任何风险)。

  有关代码和编译的问题。你正在使用JAVA还是C?是否有第三方应用需要迁移?这些第三方软件能移植到Linux上吗?

  假设您正在使用C语言。假设您将会在Linux上编译代码。如果使用GNU(gcc)编译器,因为这是工业标准,而且这是Linux自己的编译器。那么所有在其它平台上编译过的应用程序都需要重新编译。

  对于编译,有两种方法供您使用。一个方法是在现有环境上重新编译您的程序,这种情况下,您必须确保在这个环境下有您需要的所有工具,其中包括源代码和生成文件。如果您想使用这个方法,请在您的测试环境中进行,永远不要在生产环境中实施。

  另一种方法是把所有数据和代码移植到新环境上,并且测试他们。同时,要测试一下硬件平台。如果您计划更新硬件平台,一些有关硬件的代码可能会给你制造些麻烦,最糟糕的情况是,您可能不得不重写所有代码。

  确保开发人员参与进来,不要假设任何事情。需要认真考虑的事情包括运行时API、系统调用、流和库的支持。确保您完全理解所要移植的内容。这时候你需要评估和核实所有的事情,如应用程序及其库文件和依赖性。您能快速确定产品是否能在Linux上运行和在哪里运行。

  毫无疑问,Java程序比C语言程序能更快地移植。此外,在移植过程中,您还需要核实测试环境、用户界面需求、平台可靠性限制、中间件产品和内部技能水平。每一个环境不仔细都可能在未来给您带来麻烦。

  应用程序升级

  应用程序是移植过程中最重要的一块。在某些情况下,您的应用程序可以直接被移植,但是这种情况很少发生。另一种情况是,您必须在新平台上重新编译它们。移植和编译过程都不复杂,然后需要做的就是测试以确认一切OK。

  应用程序的移植过程应该包括开发和测试。在进行移植的时候,您必须有可靠的办法来保证您的数据库正确移植。另外,应用程序所要求的内核扩展和准备驱动,在新的平台上并不一定能够得到满足,因为大多数的内核API并不严格遵循标准。

  应用程序是否正在使用第三方组件,如数据库工具、应用服务器或其它中间件呢?如果是,这会增加移植的复杂性。应用程序是32位还是64位?如果是从32位移植到64为,您将不得不付出更多的时间。应用程序如何和数据库通信呢?它们使用数据库接口吗,如ODBC或者编程语言,如C++?这些方面您都需要认真考虑。从人工的角度来讲,尽可能的让那些有各种移植项目经历的人加入您的团队。

  稳定性和性能评测

  通常在最初的几周内,各种应用程序问题会陆续出现,工程师们会第一时间想办法来解决它们。这时候您可能想重新审视您的项目计划并调整交货时间。

  测试应用的稳定、功能和性能非常关键。与其花费200万美元开发新系统,还不如花费2000美元测试。测试的顺序通常如下:

  迁移工程师对于需要移植的应用程序进行模块测试。

  应用工程师执行功能性测试。

  用户验收测试(UAT)。该阶段实际的商业用户进行测试。

  性能工程师进行性能测试

  在测试过程中,对要迁移的应用程序进行压力测试不可缺少,这样能确保新系统能够应付各种负载。此时,您应该已经完成了基本的测试,并且对于旧环境和新环下的应用程序性能,您该心中有数。

  对于稳定性和性能,也需要进行类似的测试。尝试击败你的系统。使用诸如惠普LoadRunner等工具来模拟正常量5倍的负载。

  现在是时候来发现Bug了,当然这不是在生产环境上。在进入生产环境之前,您就有机会调试问题。利用测试,不要让使用系统的人来核实是否有问题。业务内容也必须涉及,而且应该有独立的UAT计划。如果您的系统在旧环境上有很高的可用性,那么在新环境下,必须测试高可用性是否继续有效。

posted @ 2011-12-23 14:42 顺其自然EVO 阅读(144) | 评论 (0)编辑 收藏

开发效率与系统稳定性杂谈

互联网系统中,开发效率与系统稳定性与产品成败非常相关。开发效率在一定程度反映了团队的执行力,快速开发能力带来了产品的竞争优势。系统稳定性(包括安全及性能等)则是产品的后防线,稍有失误则会给产品带来很大伤害。因此开发效率与系统稳定性是衡量互联网系统开发成熟度最重要的两个指标。

  在软件开发周期不同阶段,这两者如何控制?

  在需求阶段,对开发效率的影响常见的是沟通理解偏差带来的技术风险,之外最常见的还有需求变更的风险。后者大多是来自市场环境的变化作出调整,技术主管更多的是积极心态去应对。但对前者沟通理解偏差导致效率问题也不罕见,更值得警惕。

  在技术设计阶段最大的风险是技术方案,找个无需多讲,考验团队的架构能力以及对当前系统的驾驭程度。

  开发阶段最大的风险是单元测试不到位或缺失。很多号称“敏捷”型项目依赖在线上测试及修改,当模块增多后,这样代码健壮性就会变得比较脆弱,不少团队也会越走越慢。

  Review阶段风险是简洁性及性能。除了压力测试能达标之外,警惕那些不易懂的代码,这些代码将来会成为事故多发地带。

  部署阶段最大的风险是上线计划把控,上线过程中操作错误的情况并不罕见,如去年Amazon EC2的故障就是由于操作失误造成。

  从宏观看来,技术方案的风险最大,由于模块很多,具有丰富经验的高手不可能参与每一个环节,这就会出现木桶的短板效应,架构师认为不重要的地方总是会出问题。给用户体验造成极大伤害。

  另外还有团队文化的风险。大部分团队很难形成书面交流的习惯。口头沟通需求、讨论方案对创业团队非常适合。在团队变大之后,这样的习惯会造成信息流动障碍,可能会给工作效率带来更多负面问题。同时大部分团队也对流程、模板、规范缺乏了解与重视,过多依赖参与人的内部驱动力及能力,无法依靠制度与流程来取胜。

posted @ 2011-12-23 14:37 顺其自然EVO 阅读(162) | 评论 (0)编辑 收藏

从武侠门派的角度去解释域、域树、林的含义

从武侠门派的角度去解释域、域树、林的含义

  一直以来都想写一些关于活动目录技术的文章,但是一直没有一个好的切入点。有一天在博客专题中乱转,发现了宋杨的一篇老博文《省钱之道--图解域域树域林根域的含义》看了以后觉得不错。但是也有点想法。我不敢妄自评判文章的好坏,只是想有没有更通俗的解法来描述这些抽象、专业的概念呢?于是想到了我从小很喜欢的武侠小说,突然发现,原来这些东西就溶于我们的生活之中呀。废话少说,开始正文。

  自从WINDOWS 98系统出现之后,WINDOWS操作系统就不是孤立存在的,可以通过网络联机相互联系。当然,除非你只有一台计算机。默认安装的WINDOWS操作系统是以工作组模式运行。当然WINDOWS联机的模式只有两种:域模式和工作组模式。

  一、工作组

  很多专业的描述是工作组模式是由相互独立的计算机组成。他们再网络中的地位平等,各自独立、分散的维护和管理着自身。这个较抽象的描述是可以宏观表述的,看。在武侠世界里就体现着。就是金庸武侠小说中《笑傲江湖》里面五岳剑派。

(图1)

  五岳剑派最初是由上图的五个门派组成的。最初的目的是为了团结起来对抗少林,武当,日月神教等大派。五岳剑派由嵩山左冷禅提议组建,最后华山岳不群当上所谓的盟主。实际上这五个门派就组成了一个工作组。

  由5台计算机(五个门派)组成的一个工作组

  工作组(workgroup)=五岳剑派

  为什么是工作组呢?原来虽然这五个门派组成了所谓的五岳剑派,也有了所谓的盟主。但是五岳剑派实际上仍然是各自为政。比如恒山派掌门令狐冲(相当于华山这台机器的本地管理员)恒山派弟子(本地用户)的创建(招弟子)删除(逐出弟子)等问题仍然由令狐冲说的算,根本就不理睬盟主号令。另外恒山弟子(本地用户)也听令狐冲的号令。顶多是由嵩山派弟子来访(相当于来共享一个资源给他们访问)或者华山派被人揍了,请求恒山支援(可以想象成另一种资源的共享方式)。

  二、域

  什么是域?就是把我们企业IT环境中的所有资源在逻辑上进行统一集中管理的一种手段。还有什么逻辑组织最小单元呀,什么安全边界了,有点抽象了。好吧,我告诉你,域就是一个门派:就是少林,就是武当,就是明教。(以下所有以明教举例)明教就是宏观存在的逻辑组织,明教教众在明教教主的带领下进行轰轰烈烈的革命。

  关于域名和DNS命令等问题在这里不介绍了,估计比较容易明白。


(图2)

看图2当看到mingjiao.com这个表示一个单域的时候,你就可以想到明教。

(图3)

  请大家认真看图3,我来解释一下这张图。域的实体是由计算机和人员组成的。我们先看几个转化公式

  明教教主=域管理员

  明教弟子=域用户

  加入域的成员计算机=丁家大院

  加入域的成员服务器=明教钱庄

  域控制器(DC)=光明顶

  在域中要添加用户账户,就是域账户。而这里普通域用户账户就相当于明教弟子。

  在域中计算机分别担任三种角色。

  第一种,是安装WINDOWS操作系统的计算机。比如WIN XP和WIN 7。加入域后这种计算机叫成员计算机。在这里我们可以想象明教是一个大派,全国各地都有人有地盘。由于我们是人去操作计算机,所以这里的计算机就可以想象成一个地盘(一个具体的实物,比如房屋)我这里叫做丁家大院。等于丁家大院就是明教的产业了。默认情况下,任何明教弟子(普通域用户)在登录验证后都可以进入丁家大院了。可以在里面休息,下棋等。(访问资源)不过名教弟子毕竟不是丁家大院的所有者.所以不可以拆墙,建楼等行为(相对修改计算机系统) 那么谁是丁家大院的所有者呢? 有两个.一个就是原丁家大院的主人(本地管理员),一个就是明教教主(域管理员)想想都是明教的产业了,当然是所有者了。当然假如有一天丁家大院不再是明教的产业了. 被变卖了.这个行为就相当于WINDOWS计算机退出域.只有上面的2个所有者有这个能力.当然明教教主(域管理员)可以委派一个明教弟子(域用户)成为丁家大院主人(本地管理员)

  第二种,是安装WINDOWS SERVER操作系统的计算机.比如WIN 2003 SERVER 、WIN2008 SERVER。加入域的这类计算机叫成员服务器。同样,这种机器也相当于明教的一个地盘或者叫产业。与上面相同的是,这个产业也有主人(本地管理员)。明教弟子(域普通用户)也可以进入这个产业(登录到该机器上)但是也有不同的,服务器一般都是提供共享资源应用的服务器。比如做一个文件服务器,一个WEB服务器。所以这个产业中存放的是域用户的共用资源,在这里相当于明教的一个钱庄(明教弟子把钱都放在这里,可以存取)

  第三种,是安装WINDOWS SERVER操作系统的计算机安装了AD(活动目录)这时候这台计算机就成了域控制器。活动目录是什么?活动目录就相当于一个数据库,一个明教的账本。这个账本记录了哪些是明教的产业(加入域的计算机)谁是明教弟子(域用户账户)甚至还有 明教钱庄的钱(共享资源)等。所以域控制器就相当于明教之圣地-光明顶。每一个加入明教的弟子(新建用户)每一个归入明教的产业(加入成员计算机)都要到光明顶的账本中登记(记录到活动目录中)不过,光明顶与上面的丁家大院与明教钱庄不同。光明顶不归入明教的产业,也就没有主人(本地账户)其次光明顶是神圣的地方,一般明教弟子是不准进入的(默认域用户无法登陆到域控中)当然,明教教主(域管理员)是可以进去,管理这个账本(活动目录)。也可以修改这个条例(修改默认域控策略)允许指定的明教弟子进入(登陆域控)。

  好了,上面的图解释完了,下面解释一个比较重要的问题。域用户登陆域的问题。

  其实就好比明教弟子要进入自己的地盘一样。首先你是明教弟子(拥有域用户账号),其次你进入的是明教的地盘或叫产业(加入域的计算机)。否则,一个明教弟子跑到少林寺去非要进人家的藏经阁(非明教的产业)不被打出来才怪呢。再者你说你是明教弟子,你就是明教弟子了?别着急,明教有验证的办法。比如明教弟子王小五,要进入丁家大院。(用户王小五,要利用成员计算机登陆到域)首先报告给大院管家(计算机系统)大院管家收到信息后无法验证,这个时候把这个信息飞鸽传书到光明顶(域控制器)光明顶管家(DC计算机系统)查看账本(活动目录)验证是否存在此人,确认后飞鸽传书一个腰牌给王小五。从此王小五就可以进入到丁家大院了。这个腰牌上面有一个特殊的信息,就是标明了王小五的身份,王小五在丁家大院能干什么不能干什么就靠这个了。当然王小五拿这个腰牌也可以直接在去明教钱庄。拿属于自己的钱(授权访问的资源)如果王小五出了明教的地盘(退出登录,注销等)腰牌自动收回。

  当然这个过程有一个关键,就是如果丁家大院与光明顶在飞鸽传书的过程中不顺利,比如鸽子没找到路,(相当于成员计算机无法找到域控)要么王小五就不能进丁家大院了。不过俗话说,一回生,二回熟。当王小五第二次进丁家大院的时候,会发生一点点变化。假如还是上面的过程,飞鸽传书换腰牌,但是没成功,但是王小五因为上次进了丁家大院,在六角亭摆了一牌棋自己和自己下,没下完就走了。这次王小五告诉丁家大院管家(计算机系统)他上面在哪牌棋,多少子,棋局如何。。管家一看,对呀。他是明教弟子,进来吧。(这就是利用当域控无法联系,但是用户之前登陆过,利用缓存凭证来登陆)有一个叫王小六的弟子是第一次进丁家大院,那么因为没有留下什么东西,谁也不知道他这鸟是不是明教弟子,自然无法进丁家大院(无法登陆)

posted @ 2011-12-22 11:14 顺其自然EVO 阅读(163) | 评论 (0)编辑 收藏

Java精确截取字符串

 Java精确截取字符串,取得字符串前面指定长度字符函数

  用java取得字符串的前面部分内容的函数contentStr = contenttemp.substring(0, 150);其中要保证最大长度不能超过字符串的长度。下面是我的实现部分代码,以及网上搜索的相关代码:

  • /* 
  • * content内容过长可能会导致xml文件过大,加载太慢。 
  • * 但从seo的角度考虑全部输出有利于搜索引擎,但一般情况下内容也不会太多 
  • * 为防止空格换行css无法控制撑大页面,用正则表达式替换掉空格,所以截取前面100个字符,页面显示的内容多少用css控制 
  •  *zdz的作品,流风的作品 
  • */ 
  • //str.trim().replaceAll("\\s+"," ");  
  • String contenttemp = rs.getString(contentName).trim().replaceAll("\\s+","");  
  • //NpfDebug.print(contenttemp.length()); 
  • if(contenttemp.length()>100){//如果长度大于100则截取 
  •  contenttemp = contenttemp.substring(0100);  
  •  //NpfDebug.print("contenttemp.length()>100 ? "+contenttemp.length()+"\n"+contentStr); 
  • }  
  • rsbody.append(beforCONTENT);  
  • rsbody.append(contenttemp);  
  • rsbody.append(endCONTENT);
  •   开发中经常遇到,字符串过长,无法完全显示的问题

      这时候就需要截取我们所需要的长度,后面显示省略号或其他字符。

      由于中文字符占两个字节,而英文字符占用一个字节,所以,单纯地判断字符数,效果往往不尽如人意

      下面的方法通过判断字符的类型来进行截取,效果还算可以:)

      如果大家有其他的解决方法欢迎贴出来,共同学习:)

  • private String str;  
  • private int counterOfDoubleByte;  
  • private byte b[];  
  • /** 
  • * 设置需要被限制长度的字符串 
  • * @param str 需要被限制长度的字符串 
  • */ 
  • public void setLimitLengthString(String str){  
  •    this.str = str;  
  • }  
  • /** 
  • * @param len 需要显示的长度(<font color="red">注意:长度是以byte为单位的,一个汉字是2个byte</font>) 
  • * @param symbol 用于表示省略的信息的字符,如“...”,“>>>”等。 
  • * @return 返回处理后的字符串 
  • */ 
  • public String getLimitLengthString(int len, String symbol) throws UnsupportedEncodingException {  
  •    counterOfDoubleByte = 0;  
  •    b = str.getBytes("GBK");  
  •    if(b.length <= len)  
  •      return str;  
  •    for(int i = 0; i < len; i++){  
  •      if(b[i] < 0)  
  •        counterOfDoubleByte++;  
  •    }  
  •    if(counterOfDoubleByte % 2 == 0)  
  •      return new String(b, 0, len, "GBK") + symbol;  
  •    else 
  •      return new String(b, 0, len - 1"GBK") + symbol;  
  • }  
  •    
  •    
  •    
  • -------------------  
  •    
  • /** *//** 
  •     * 按字节长度截取字符串 
  •     * @param str 将要截取的字符串参数 
  •     * @param toCount 截取的字节长度 
  •     * @param more 字符串末尾补上的字符串 
  •     * @return 返回截取后的字符串 
  •     */ 
  •    public String substring(String str, int toCount, String more) ...{  
  •      int reInt = 0;  
  •      String reStr = "";  
  •      if (str == null)  
  •        return "";  
  •      char[] tempChar = str.toCharArray();  
  •      for (int kk = 0; (kk < tempChar.length && toCount > reInt); kk++) ...{  
  •        String s1 = str.valueOf(tempChar[kk]);  
  •        byte[] b = s1.getBytes();  
  •        reInt += b.length;  
  •        reStr += tempChar[kk];  
  •      }  
  •      if (toCount == reInt || (toCount == reInt - 1))  
  •        reStr += more;  
  •      return reStr;  
  •    }  
  •    
  • =================  
  •    
  • /** 
  •      * 取字符串的前toCount个字符 
  •      * 
  •      * @param str 被处理字符串 
  •      * @param toCount 截取长度 
  •      * @param more 后缀字符串 
  •      * @version 2004.11.24 
  •      * @author zhulx 
  •      * @return String 
  •      */ 
  •     public static String substring(String str, int toCount,String more)  
  •     {  
  •       int reInt = 0;  
  •       String reStr = "";  
  •       if (str == null)  
  •         return "";  
  •       char[] tempChar = str.toCharArray();  
  •       for (int kk = 0; (kk < tempChar.length && toCount > reInt); kk++) {  
  •         String s1 = str.valueOf(tempChar[kk]);  
  •         byte[] b = s1.getBytes();  
  •         reInt += b.length;  
  •         reStr += tempChar[kk];  
  •       }  
  •       if (toCount == reInt || (toCount == reInt - 1))  
  •         reStr += more;  
  •       return reStr;  
  •     }
  •   得到字符串真实长度和取固定长度的字符串函数

  • // 截取固定长度子字符串 sSource为字符串iLen为长度  
  • function getInterceptedStr(sSource, iLen)   
  • {   
  •     if(sSource.replace(/[^\x00-\xff]/g,"xx").length <= iLen)   
  •     {   
  •         return sSource;   
  •     }   
  •     var ELIDED = "";   
  •        
  •     var str = "";   
  •     var l = 0;   
  •     var schar;   
  •     for(var i=0; schar=sSource.charAt(i); i++)   
  •     {   
  •         str += schar;   
  •         l += (schar.match(/[^\x00-\xff]/) != null ? 2 : 1);   
  •         if(l >= iLen - ELIDED.length)   
  •         {   
  •             break;   
  •         }   
  •     }   
  •     str += ELIDED;   
  •        
  •     return str;   
  • }
  • posted @ 2011-12-22 11:12 顺其自然EVO 阅读(302) | 评论 (0)编辑 收藏

    MySQL支撑百万级流量高并发的网站部署详解

     MySQL支撑百万级流量高并发的网站的部署方法是本文我们主要要介绍的内容,了解了这部分内容我们自己就能用MySQL来支撑百万级流量高并发的网站了,接下来我们就开始介绍这部分内容。

      1、MySQL服务器集群

      由于是小公司在资金和成本上都有所限制,而且在技术上也没有几个技术员接触过,所以这个方法自然就让大伙否决了。

      这里说说我个人的理解!做集群不但添加资费的开销,而且在技术上也有很大的挑战,对于我们公司目前的情况是不大现实的。集群无非就是把一台服务器的压力转接到两台或是多台服务器上,我是这么理解的,也许我理解有误,还请大家指教。

      2、分而治之

      这个方法和集群差不多,不过是把统计的代码放在不同的服务器上跑,由于公司有不少配置低的服务器跑几万到几十万IP还是没有问题的,我们可以把几百万流量分成十来个几十万的量分而统计。

      优点:充分的利用了现在的资源,解决了目前的问题。

      缺点:这样的方法不是长久之计,迟早还是会出问题的。而且在统计数据的时候比较麻烦。

      3、统计代码的修改

      由于之前采用的是在插入数据之前加以判断,这个IP是否存在,来路等的处理,无形中增加了服务器的压力,所以大伙把统计代码改成来一个就插入数据库,不管三七二十一等以后在处理。

      这个方法基本上把当天的数据保留下来了,可是在处理的时候由于数据量的庞大,来来回回还是把服务器跑死了,而且在插入的时候由于当时设计数据结构的时候留有的索引,也大大的消耗了不少的服务器资源。

      那么把索引去掉到最后处理的时候又是老慢的,得不偿失。

      4、统计方式的修改

      最后这一个方法,效果非常的明显。那是什么方法呢!

      这里就主要介绍这个方法:

      A、保留原用的数据结构不变,并把所有的数据按一定的结构存入文件

      结构:可以是xml,json,也可以是你自己想的任何有规律的数据排放。

      例如:

      1)221.2.70.52,http://www.baidu.com,windowxp\r\n

      2)221.2.70.52,http://www.baidu.com,windowxp\r\n

      写入文件:fopen,fwrite??no 这里介绍一个非常好用的技巧,也许大家都知道,但是像我这样的菜鸟大概都不知道,那就是用error_log,这不是写错误日志的吗?对就是他,非常方便。

      格式:

      1 error_log("内容", 3, "/date.dat");

      这里我就不说他的具体用了,不明白的朋友可以查一下手册。

     B、数据文件的命名

      为什么这里要讲文件的命名呢?如果就一味的把数据的写入文件不作任何的处理那么他和直接插入数据库有多大的区别呢?那么我们所作的一切都是无用功了。

      首先是在时间的利用上:date(‘YmdH’)得到的值是如:2008121112这有什么好入,这样一来这个数据就是一个小时一个文件必免了文件过大,而且不用去判断自动生成。

      IP的应用:由于在很多数据上都是一个IP操作的,所以把相同IP的数据放在一个文件里在后面的处理就非常方便处理。请看后面的介绍,这里我们取IP成三位为文件名字的一部分。

      C、数据的导入处理

      通过以上两位的操作当天的数据会一个不少的保留下来,接下来怎么处理其实并不是很重要了。但是这里还是讲讲我的想法。

      入库前处理:

      前面讲到把IP三位相同的放一个文件就是为了入库前到它们进行处理,首先可以用最笨的方法把数据拆成N个数据。在进行重复数据的删除。

      如果一个IP浏览多页那么PV在这里就可以得到统计,并把访问的页面进行处理,组成新的数据。

      导入方法:

      这里要介绍一下数据的导入方法:1 $sql="LOAD DATA INFILE '".$file."' INTO TABLE `test` FIELDS TERMINATED BY ', ' LINES TERMINATED BY '\r\n'(2 3 `time` , `md5`4 5 )";就这一个语句,在导入几十万数据的时候可以说是十分快速的,用法我这里也不过多介绍了,大家有不明白的可以查手册,所以说解决数据库的瓶颈的办法不定要加设备,也不一定要换数据库,只要换一个思路就能解决不少问题。

      以上就是MySQL支撑百万级流量高并发的网站的部署方法,本文就介绍到这里了,希望本次的介绍能够对您有所收获!

    posted @ 2011-12-21 12:01 顺其自然EVO 阅读(258) | 评论 (0)编辑 收藏

    如何检查MySQL数据库的主从延时?

     MySQL数据库主从延时如何去判断呢?本文我们介绍了两种判断方法:1. Seconds_Behind_Master vs 2. mk-heartbeat,接下来我们就分别介绍这些内容。

      日常工作中,对于MySQL主从复制检查,一方面我们要保证复制的整体结构是否正常,另一方面需要检查主从数据是否保持一致。对于前者我们可以通过监控复制线程是否工作正常以及主从延时是否在容忍范围内,对于后者则可以通过分别校验主从表中数据的md5码是否一致,来保证数据一致,可以使用Maatkit工具包中的mk-table- checksum工具去检查。

      方法1:

      通过监控show slave status\G命令输出的Seconds_Behind_Master参数的值来判断,是否有发生主从延时。其值有这么几种:

      NULL — 表示io_thread或是sql_thread有任何一个发生故障,也就是该线程的Running状态是No,而非Yes。

      0 — 该值为零,是我们极为渴望看到的情况,表示主从复制良好,可以认为lag不存在。

      正值 — 表示主从已经出现延时,数字越大表示从库落后主库越多。

      负值 — 几乎很少见,我只是听一些资深的DBA说见过,其实,这是一个BUG值,该参数是不支持负值的,也就是不应该出现。

      show slave status\G,该命令的输出结果非常丰厚,给我们的监控提供了很多有意义的参数,比如:Slave_IO_Running该参数可作为 io_thread的监控项,Yes表示io_thread的和主库连接正常并能实施复制工作,No则说明与主库通讯异常,多数情况是由主从间网络引起的问题;Slave_SQL_Running该参数代表sql_thread是否正常,具体就是语句是否执行通过,常会遇到主键重复或是某个表不存在。下面就说到今天的重点Seconds_Behind_Master,该值作为判断主从延时的指标,那么它又是怎么得到这个值的呢,同时,它为什么又受到很多人的质疑?

      Seconds_Behind_Master是通过比较sql_thread执行的event的timestamp和 io_thread复制好的event的timestamp(简写为ts)进行比较,而得到的这么一个差值。我们都知道的relay-log和主库的 bin-log里面的内容完全一样,在记录sql语句的同时会被记录上当时的ts,所以比较参考的值来自于binlog,其实主从没有必要与NTP进行同步,也就是说无需保证主从时钟的一致。

      你也会发现,其实比较真正是发生在io_thread与sql_thread之间,而io_thread才真正与主库有关联,于是,问题就出来了,当主库I/O负载很大或是网络阻塞,io_thread不能及时复制binlog(没有中断,也在复制),而 sql_thread一直都能跟上io_thread的脚本,这时Seconds_Behind_Master的值是0,也就是我们认为的无延时,但是,实际上不是,你懂得。这也就是为什么大家要批判用这个参数来监控数据库是否发生延时不准的原因,但是这个值并不是总是不准,如果当io_thread与 master网络很好的情况下,那么该值也是很有价值的。

      之前,提到Seconds_Behind_Master这个参数会有负值出现,我们已经知道该值是io_thread的最近跟新的ts与sql_thread执行到的ts差值,前者始终是大于后者的,唯一的肯能就是某个event的ts发生了错误,比之前的小了,那么当这种情况发生时,负值出现就成为可能。

      方法2:

      mk-heartbeat,Maatkit万能工具包中的一个工具,被认为可以准确判断复制延时的方法。

      mk-heartbeat的实现也是借助timestmp的比较实现的,它首先需要保证主从服务器必须要保持一致,通过与相同的一个NTP server同步时钟。它需要在主库上创建一个heartbeat的表,里面至少有id与ts两个字段,id为server_id,ts就是当前的时间戳 now(),该结构也会被复制到从库上。

      表建好以后,会在主库上以后台进程的模式去执行一行更新操作的命令,定期去向表中的插入数据,这个周期默认为1 秒,同时从库也会在后台执行一个监控命令,与主库保持一致的周期去比较,复制过来记录的ts值与主库上的同一条ts值,差值为0表示无延时,差值越大表示延时的秒数越多。

      我们都知道复制是异步的ts不肯完全一致,所以该工具允许半秒的差距,在这之内的差异都可忽略认为无延时。这个工具就是通过实打实的复制,巧妙的借用timestamp来检查延时,非常好用!

      关于检查MySQL数据库的主从延时的两种方法就介绍到这里了,希望本次的介绍能够对您有所收获!

    posted @ 2011-12-20 14:29 顺其自然EVO 阅读(333) | 评论 (0)编辑 收藏

    Java字符编码根本原理

     Java开发中,常常会遇到乱码的问题,一旦遇到这种问题,常常就很扯蛋,每个人都不愿意承认是自己的代码有问题。其实编码问题并没有那么神秘,那么不可捉摸,搞清Java的编码本质过程就真相大白了。

      先看个图:

      其实,编码问题存在两个方面:JVM之内和JVM之外。

      1、Java文件编译后形成class

      这里Java文件的编码可能有多种多样,但Java编译器会自动将这些编码按照Java文件的编码格式正确读取后产生class文件,这里的class文件编码是Unicode编码(具体说是UTF-16编码)。

      因此,在Java代码中定义一个字符串:

      String s="汉字";

      不管在编译前java文件使用何种编码,在编译后成class后,他们都是一样的----Unicode编码表示。

      2、JVM中的编码

      JVM加载class文件读取时候使用Unicode编码方式正确读取class文件,那么原来定义的String s="汉字";在内存中的表现形式是Unicode编码。

      当调用String.getBytes()的时候,其实已经为乱码买下了祸根。因为此方法使用平台默认的字符集来获取字符串对应的字节数组。在WindowsXP中文版中,使用的默认编码是GBK,不信运行下:

  • public class Test {   
  • public static void main(String[] args) {   
  • System.out.println("当前JRE:" + System.getProperty("java.version"));   
  • System.out.println("当前JVM的默认字符集:" + Charset.defaultCharset());   
  • }   
  • }
  •   当前JRE:1.6.0_16

      当前JVM的默认字符集:GBK

      当不同的系统、数据库经过多次编码后,如果对其中的原理不理解,就容易导致乱码。因此,在一个系统中,有必要对字符串的编码做一个统一,这个统一模糊点说,就是对外统一。比如方法字符串参数,IO流,在中文系统中,可以统一使用GBK、GB13080、UTF-8、UTF-16等等都可以,只是要选择有些更大字符集,以保证任何可能用到的字符都可以正常显示,避免乱码的问题。(假设对所有的文件都用ASCII码)那么就无法实现双向转换了。

     要特别注意的是,UTF-8并非能容纳了所有的中文字符集编码,因此,在特殊情况下,UTF-8转GB18030可能会出现乱码,然而一群傻B常常在做中文系统喜欢用UTF-8编码而不说不出个所以然出来!最傻B的是,一个系统多个人做,源代码文件有的人用GBK编码,有人用UTF-8,还有人用GB18030。FK,都是中国人,也不是外包项目,用什么UTF-8啊,神经!源代码统统都用GBK18030就OK了,免得ANT脚本编译时候提示不可认的字符编码。

      因此,对于中文系统来说,最好选择GBK或GB18030编码(其实GBK是GB18030的子集),以便最大限度的避免乱码现象。

      3、内存中字符串的编码

      内存中的字符串不仅仅局限于从class代码中直接加载而来的字符串,还有一些字符串是从文本文件中读取的,还有的是通过数据库读取的,还有可能是从字节数组构建的,然而他们基本上都不是Unicode编码的,原因很简单,存储优化。

      因此就需要处理各种各样的编码问题,在处理之前,必须明确“源”的编码,然后用指定的编码方式正确读取到内存中。如果是一个方法的参数,实际上必须明确该字符串参数的编码,因为这个参数可能是另外一个日文系统传递过来的。当明确了字符串编码时候,就可以按照要求正确处理字符串,以避免乱码。

      在对字符串进行解码编码的时候,应该调用下面的方法:

  • getBytes(String charsetName)   
  • String(byte[] bytes, String charsetName)
  •   而不要使用那些不带字符集名称的方法签名,通过上面两个方法,可以对内存中的字符进行重新编码。

    posted @ 2011-12-20 14:26 顺其自然EVO 阅读(219) | 评论 (0)编辑 收藏

    Tomcat运行Java Web内存溢出总结

     如果JVM里运行的程序, 它的内存堆和持久存储区域的都满了,这个时候程序还想创建对象实例的话,垃圾收集器就会启动,试图释放足够的内存来创建这个对象。这个时候如果垃圾收集器 没有能力释放出足够的内存,它就会抛出OutOfMemoryError内存溢出错误。

      SUN JVM的内存管理方式:

      SUN的JVM是类似人类家族,也就是在一个地方创建对象,在它长期占据空间之前给它多次死亡的机会,SUN JVM会划分为:

      1、年轻的一代(Young generation),包括EDEN和2个幸存者空间(出发地和目的地the From space and the To space)

      2、老一代(Old generation)

      3、永久的一代(Permanent generation)

      Java虚拟机的运行时数据区一般分类如下(不一定是物理划分):

      1、堆:主要存放对象实例,线程共享

      2、栈:主要存储特定线程的方法调用状态,线程独占

      3、本地方法栈:存储本地方法的调用状态,线程独占

      4、PC寄存器:学过操作系统课程的都知道,线程独占

      5、方法区:主要存储了类型信息,线程共享

      因此,在抛出内存溢出错误的时候,一般都会提示内存泄露的种类,一般也都是按照区域进行划分:

      1、堆(heap)内存泄漏java.lang.OutOfMemoryError: Javaheap space:大家都比较熟悉 ,通过设置-Xms2048m -Xmx4096m可以解决

      2、栈(stack)内存泄漏:当前线程运行期间维护的中间变量等信息过多,例如常见的死循环引起stack over flow

      3、方法区(permanent heap)内存泄漏,即java.lang.OutOfMemoryError: PermGen space:发生的原因和类型装载、类型卸载有直接的关系,通过设置-XX:MaxNewSize=256m -XX:MaxPermSize=256m可以解决。

      一般情况下,当服务器内存过小,而提供了大量的访问服务时,可能会缓存过多的数据对象造成堆内存溢出,当web应用不断扩大,加载的lib库达到一定大小(4M)后,就容易报PermGen OOM,也就是方法区溢出。

      在Linux服务器中将参数写入环境变量:

  • export CATALINA_OPTS="-Xms2048m -Xmx4096m" 
  • export JAVA_OPTS="-XX:MaxNewSize=256m -XX:MaxPermSize=256m"
  •   Xmx 最大不要超过服务器物理内存的80%

    posted @ 2011-12-19 17:15 顺其自然EVO 阅读(158) | 评论 (0)编辑 收藏

    Linux中crontab-定时任务命令

      有些东西很久不用就会忘记,所以为了不至于总是找资料,干脆就做一次深刻的笔记,这样既能加深记忆,又能深入理解。

      linux服务器很久没接触了,出了一些新的版本,Ubuntu已经出了11.10了,之前对于Ubuntu的了解只是出于对桌面版的好奇,可以跟win7一样炫,现在的Ubuntu已正式进入了Liunx爱好者的视线,应用用于后台大型服务器,选择它的主要原因还是出于对稳定性的考虑。用习惯了Centos,突然转移到Ubuntu上还是有些不习惯,毕竟Centos与传统的Redhat没什么区别。不过,总归命令还是一样的,多用用就熟悉了。

      关于任务定时的命令crontab,在Linux中应用还算常见,这次为了配合开发完成一些辅助功能,以及一些备份更新等脚本,就需要crontab来完成,在windows下也就是一个批处理,linux只是多了一些命令而已。先来看看crontab的介绍:

      crontab命令常见于Unix和类Unix的操作系统之中,用于设置周期性被执行的指令。该命令从标准输入设备读取指令,并将其存放于“crontab”文件中,以供之后读取和执行。通常,crontab储存的指令被守护进程激活, crond常常在后台运行,每一分钟检查是否有预定的作业需要执行。这类作业一般称为cron jobs。crontab文件包含送交cron守护进程的一系列作业和指令。每个用户可以拥有自己的crontab文件;同时,操作系统保存一个针对整个系统的crontab文件,该文件通常存放于/etc或者/etc之下的子目录中,而这个文件只能由系统管理员来修改。crontab文件的每一行均遵守特定的格式,由空格或tab分隔为数个领域,每个领域可以放置单一或多个数值。

      在Ubuntu中,crontab的命令如下:

      -e 表示编辑当前的crontab

      -l  表示列表显示当前的crontab任务

      -r  表示删除当前用户的crontab

      -i  表示删除crontab时给予提示信息

      注意,user's crontab这个表示是每个用户都有自己的crontab,所以如果需要全局执行,必须定制root用户的crontab,非全局的,就根据各个用户自己的crontab来执行,在执行编辑crontab操作时,我们需要设置编辑工具,否则默认是crontab的编辑,对于习惯vi编辑的用户,我们需要在用户目录下设置.profile配置文件,如root的配置文件.prifile,就如下目录:

      带.的文件都是隐藏文件,所以需要ls -a才能列出来,vi .profile在文件中加入如下配置:

      EDITOR=vi; export EDITOR

      表示,当前root用户以vi作为默认编辑器,此时直接使用crontab -e,可以进行编辑任务列表,如下所示:

      上面以#号开头的表示是注释说明的信息,红色标记的是任务列表。

      对于crontab的任务配置说明;

      分钟 小时 日 月 星期 命令

      *    *    *  *  *    *

      这样就一目了然了,我们红色标记的表示的意义是每天3点钟执行脚本run.sh,并将执行日志自动输出到log.log文件中。

      */1 * * * * root  /opt/bin/test-cron.sh //表示每隔一分钟执行一次脚本

      注:crontab任务是被定制在系统后台运行的cron进程,所以用户书无法查看到cron的进程状态的。设置开机启动cron进程,命令如下:

      chkconfig --add crond,把它加入到系统的服务列表中。

      当然,crontab命令用多了,会越来越喜欢它的,因为它能简化我们日常的很多工作,特别是数据库备份、检测服务器运行状态等一些经常做的工作,都可以根据你的需求来定制,在合理的时间运行执行合适的工作任务,既不影响服务器的性能,又可以节约平时的工作时间,大大提高功能效率。

    posted @ 2011-12-19 17:12 顺其自然EVO 阅读(266) | 评论 (0)编辑 收藏

    注意那些容易被忽略的SQL注入技巧

    注意那些容易被忽略的SQL注入技巧

     下面我要谈到一些Sqlserver新的Bug(注入),这些都是从长期的工作中总结出来的经验,现在拿出来与大家一起分享,希望能够对大家有所帮助。

      1、关于Openrowset和Opendatasource

      可能这个技巧早有人已经会了,就是利用openrowset发送本地命令。通常我们的用法是(包括MSDN的列子)如下:

    以下是代码片段:
    select * from openrowset('sqloledb','myserver';'sa';'','select * from table')

      可见(即使从字面意义上看)openrowset只是作为一个快捷的远程数据库访问,它必须跟在select后面,也就是说需要返回一个recordset 。

      那么我们能不能利用它调用XP_cmdshell呢?答案是肯定的!

    以下是代码片段:
        select * from openrowset('sqloledb','server';'sa';'','set fmtonly off
      exec master.dbo.XP_cmdshel l ''dir c:\''')

      必须加上setfmtonlyoff用来屏蔽默认的只返回列信息的设置,这样XP_cmdshell返回的output集合就会提交给前面的select显示,如果采用默认设置,会返回空集合导致select出错,命令也就无法执行了。

      那么如果我们要调用sp_addlogin呢,他不会像XP_cmdshell返回任何集合的,我们就不能再依靠fmtonly设置了,可以如下操作:

    以下是代码片段:
        select * from openrowset('sqloledb','server';'sa';'','select ''OK!''
      exec master.dbo.sp_addlogin Hectic')

      这样,命令至少会返回select OK!'的集合,你的机器商会显示OK!,同时对方的数据库内也会增加一个Hectic的账号,也就是说,我们利用select 'OK!'的返回集合欺骗了本地的select请求,是命令能够正常执行,通理sp_addsrvrolemember和opendatasource也可以如此操作!至于这个方法真正的用处,大家慢慢想吧。

      2、关于Msdasql两次请求的问题

      不知道大家有没有试过用msdasql连接远程数据库,当然这个api必须是sqlserver的管理员才可以调用,那么如下:

    以下是代码片段:
        select * from openrowset('msdasql','driver={sql server};server=server;address=server,1433;uid=sa;pwd=;database=master;network=dbmssocn','s
      elect * from table1 select * from table2')

      当table1和table2的字段数目不相同时,你会发现对方的sqlserver崩溃了,连本地连接都会失败,而系统资源占用一切正常,用pskill杀死 sqlserver进程后,如果不重启机器,sqlserver要么无法正常启动,要么时常出现非法操作,我也只是碰巧找到这个bug的,具体原因我还没有摸透,而且很奇怪的是这个现象只出现在msdasql上,sqloledb就没有这个问题,看来问题不是在于请求集合数目和返回集合数目不匹配上,应该还是msdasql本身的问题,具体原因,大家一起慢慢研究吧。

      3、可怕的后门

      以前在网上看到有人说在 sqlserver上留后门可以通过添加triger、jobs或改写sp_addlogin和sp_addsrvrolemember做到,这些方法当然可行,但是很容易会被发现。不知道大家有没有想过sqloledb的本地连接映射。呵呵,比如你在对方的sqlserver上用sqlserver的管理员账号执行如下的命令:

    以下是代码片段:
    select * from openrowset('sqloledb','trusted_connection=yes;data source=Hectic','set fmtonly off exec master..XP_cmdshell ''dir c:\''')

      这样在对方的sqlserver上建立了一个名为Hectic的本地连接映射,只要sqlserver不重启,这个映射会一直存在下去,至少我现在还不知道如何发现别人放置的连接映射,好了,以上的命令运行过后,你会发现哪怕是sqlserver没有任何权限的guest用户,运行以上这条命令也一样能通过!而且权限是 localsystem!(默认安装)呵呵!这个方法可以用来在以被入侵过获得管理员权限的sqlserver上留下一个后门了。以上的方法在 sqlserver2000 sqlserver2000SP1上通过!

      另外还有一个猜测,不知道大家有没有注意过windows默认附带的两个dsn,一个是localserver一个是msqi,这两个在建立的时候是本地管理员账号连接sqlserver的,如果对方的 sqlserver是通过自定义的power user启动,那么sa的权限就和power user一样,很难有所大作为,但是我们通过如下的命令:

    以下是代码片段:
        select * from openrowset
      ('msdasql','dsn=locaserver;trusted_connection=yes','set fmtonly off execmaster..XP_cmdshell ''dir c:\''')

      应该可以利用localserver的管理员账号连接本地sqlserver然后再以这个账号的权限执行本地命令了,这是后我想应该能突破sa那个power user权限了。现在的问题是sqloledb无法调用dsn连接,而msdasql非管理员不让调用,所以我现在正在寻找guest调用msdasql 的方法。

      上文中我给大家介绍的可能只是SQL注入技巧的一部分,如果大家有更好的有关SQL注入的技巧,也要拿出来和我们分享哦,好东西大家要一起分享。

    posted @ 2011-12-19 17:11 顺其自然EVO 阅读(157) | 评论 (0)编辑 收藏

    仅列出标题
    共394页: First 上一页 346 347 348 349 350 351 352 353 354 下一页 Last 
    <2024年11月>
    272829303112
    3456789
    10111213141516
    17181920212223
    24252627282930
    1234567

    导航

    统计

    常用链接

    留言簿(55)

    随笔分类

    随笔档案

    文章分类

    文章档案

    搜索

    最新评论

    阅读排行榜

    评论排行榜