`
jayjayjays
  • 浏览: 214688 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

探讨关于门户网站中的大型计数器问题解决方案(Inber原作)

    博客分类:
  • web
阅读更多

--  发布时间:2005-10-20 22:06:01

--  计数器系统

有一计数器系统要求如下: 
1性能要求:每天访问量要求符合100000/天  且有30-40  个站点统计  同时进行 
2刷新量,纯IP统计(0-24  每个时间段内)各自形成每天报表 
本人的解决方案:
第一次读数据库,之后的数据都存在APLICATION中进行加一操作定时更新数据库 三四十个站点同时进行。

问题:发现Aplication 有不稳定的情况(同一Aplication  有时候一会儿变成这个数据 一会儿变成那个数据,之间的差值会虽时间长而变大,但是还是最大的那个正确,就是检查不出来怀疑数据访问量大的时候Tomcat 没有处理好Aplication这个东西)如果把这个程序单独每个统计站布署一个就不会出现这种情况。注:我的程序不存在性能瓶经基本全在内存中操作速度很快服务器硬件也没有问题。

谁能用JAVA来实现统一计数实现我如上的条件,或者能解决一下我的问题所在,本人将以高分数表示感谢,希望写过大型计数器的朋友进入

本人写了一个Servlet  不怕大家见笑抛砖引玉:
以下是本人前100行代码(程序有不完善的地方见笑。。。)
import java.sql.*;
import javax.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.PageContext;

import java.io.*;
import java.util.Date;
import java.text.DateFormat;
import com.inberkong.util.DataBaseConnection;

public class CounterServlet extends HttpServlet
{
private String counterSite;
//private int count=0;

private  Connection con=null;

private String pString ="";


private final int WRITE_TIME=6;//定时写数据库的间隔时长以秒为单位

private ServletContext application=null;
  
public  void doGet(HttpServletRequest request,
                      HttpServletResponse response)
        throws IOException, ServletException
{

response.setContentType("text/html;charset=gb2312");
String theIP=request.getRemoteAddr();//得到访问者IP;
Date time1=new java.util.Date();//获得系统当前时间
    String Referer=request.getHeader("Referer");//得到来访者地址
   
    if(Referer==null)
    {
     System.out.print("No Referer value");
    }
   // String Referer="http://61.163.234.223/zhaotie/test1.htm";//\' target="_blank" >http://61.163.234.223/zhaotie/test1.htm";//摸拟得到来访者地址(检验数据开始要把此项打开)    

    

    String [] siteAddress=Referer.split("/");
counterSite=siteAddress[0]+"//"+siteAddress[2];//得到来访者的网址域名

PrintWriter out =response.getWriter();

String  sql="";

Date tm=new java.util.Date();//获得系统当前时间
String sqltm=new Timestamp(tm.getTime()).toString();//将当前时间转换成sql server可以识别的对象
String st2=sqltm;
st2=st2.substring(0,19);//2005-08-14 18:41:33
String d1=st2.substring(0,10);
     
application = getServletConfig().getServletContext();


try
{
 

  if(application.getAttribute(counterSite+"_checkAccount")==null)//初始计数器的状态.
  {

        
    //application.setAttribute(counterSite,new Integer(count));//计数器
   
    Statement stmt=null;
       try{
        //如果数据库缓冲池无连接则重新启动TOMCATE服务   
           stmt=con.createStatement();
       }catch(SQLException ee)
       {
        destroy();
        Runtime rn=Runtime.getRuntime();
        Process p=null;
        try{
        
        p=rn.exec("tomcat5.exe stop");
        for(int i=0;i<1999999999;i++)
        {
        ;
        }
        p=rn.exec("taskkill /F /IM tomcat5w.exe /T");
        p=rn.exec("taskkill /F /IM tomcat5.exe /T");
        for(int j=0;j<1999999999;j++)
        {
        ;
        }
        p=rn.exec("tomcat5.exe start");
      
       
        }catch(Exception e){
        System.out.println("Error exec notepad");
        }
       

以下为101-200行代码
       System.out.print(ee+""+new java.util.Date());
       
       
       }
    ResultSet rs=null;      
    application.setAttribute(counterSite+"Date1",new java.util.Date());//站点定时时间
     sql="select id,R_TODAY_SUM,R_TOM_SUM,R_THIS_MONTH_SUM,R_TOTAL_SUM,R_TOTAL_DAY,R_COUNT_DATE from inber_count_account where ACCOUNT_SIT_ADD like \'%"+counterSite+"%\'";
    
     //out.print(sql);
     rs=stmt.executeQuery(sql);
     if(rs.next())
     {

     
     application.setAttribute(counterSite+"_checkAccount",new String("ok"));
     application.setAttribute(counterSite+"_id",new Integer(rs.getInt(1)));
    
     application.setAttribute(counterSite+"_R_TODAY_SUM",new Integer(rs.getInt(2)));    
     application.setAttribute(counterSite+"_R_TOM_SUM",new Integer(rs.getInt(3)));    
     application.setAttribute(counterSite+"_R_THIS_MONTH_SUM",new Integer(rs.getInt(4)));    
     application.setAttribute(counterSite+"_R_TOTAL_SUM",new Integer(rs.getInt(5)));    
     application.setAttribute(counterSite+"_R_TOTAL_DAY",new Integer(rs.getInt(6)));    

//****
     application.setAttribute(counterSite+"_R_COUNT_DATE",new String(rs.getString("R_COUNT_DATE")));    

     }
     rs.close();
     stmt.close();
    
  }
        else
        {
        

   if((application.getAttribute(counterSite+"_checkAccount").toString()).equals("ok"))//校验此计数器账号引用是否存在
   {
   
    Date accessTime=null;   
  

//刷新率 start----------------------------------

       application.setAttribute(counterSite+"_R_TODAY_SUM",new Integer(Integer.parseInt((application.getAttribute(counterSite+"_R_TODAY_SUM").toString()))+1));    
       application.setAttribute(counterSite+"_R_THIS_MONTH_SUM",new Integer(Integer.parseInt((application.getAttribute(counterSite+"_R_THIS_MONTH_SUM").toString()))+1));    
       application.setAttribute(counterSite+"_R_TOTAL_SUM",new Integer(Integer.parseInt((application.getAttribute(counterSite+"_R_TOTAL_SUM").toString()))+1));
        
        
      
       String d2=application.getAttribute(counterSite+"_R_COUNT_DATE").toString();
       //当日期改变时,清除当天的计数
       String tYear,tMonth,tDay;
       tYear=d2.substring(0,4);
       tMonth=d2.substring(5,7);
       tDay=d2.substring(8,10);

       if(!(d1.equals(d2)))
       {


       int todaysum=Integer.parseInt((application.getAttribute(counterSite+"_R_TODAY_SUM").toString()));
       int totalday=Integer.parseInt((application.getAttribute(counterSite+"_R_TOTAL_DAY").toString()));

       application.setAttribute(counterSite+"_R_TOM_SUM",new Integer(todaysum));
       application.setAttribute(counterSite+"_R_TODAY_SUM",new Integer(0));
       application.setAttribute(counterSite+"_R_TOTAL_DAY",new Integer(totalday+1));   
       application.setAttribute(counterSite+"_R_COUNT_DATE",new String(d1));


      
      
try{
                    CallableStatement cstmt4=null;
              
         pString = "{call p_setDetailList3(\'"+tYear+"\', \'"+tMonth+"\', \'"+tDay+"\',"+todaysum+", \'"+d2+"\',"+Integer.parseInt((application.getAttribute(counterSite+"_id").toString()))+")}";
         cstmt4=con.prepareCall(pString);
         cstmt4.executeUpdate();
         cstmt4.close();     
      }
      catch(Exception ee)
      {
       System.out.println("call p_setDetailList3 is wrong:"+ee);
      }

      
       }
      
      
       String cMonth=d1.substring(5,7);
       //当月改变时清除当月的计数,并计数当月第一个浏览者.
       if(!(cMonth.equals(tMonth)))
       {
       application.setAttribute(counterSite+"_R_THIS_MONTH_SUM",new Integer(0));
       application.setAttribute(counterSite+"_R_COUNT_DATE",new String(d1));       
       }    
      
  


//刷新率 end----------------------------------
201-3百行以后的代码


   //count=Integer.parseInt((application.getAttribute(counterSite).toString()));
  


////////////////////////////////////////////定时写数据库同时 初始化数据 start/////////
   Date time2=new java.util.Date();//获得系统当前时间
   Date t1=(Date)application.getAttribute(counterSite+"Date1");
         int secondValue=(int)(((double)time2.getTime()-(double)t1.getTime())/1000);

 
          if(secondValue>=WRITE_TIME)//
          {//定时写数据库同时 初始化数据


          int siteid=Integer.parseInt((application.getAttribute(counterSite+"_id").toString()));
    int a1=Integer.parseInt((application.getAttribute(counterSite+"_R_TODAY_SUM").toString()));
    int a2=Integer.parseInt((application.getAttribute(counterSite+"_R_TOM_SUM").toString()));
    int a3=Integer.parseInt((application.getAttribute(counterSite+"_R_THIS_MONTH_SUM").toString()));
    int a4=Integer.parseInt((application.getAttribute(counterSite+"_R_TOTAL_SUM").toString()));
    int a5=Integer.parseInt((application.getAttribute(counterSite+"_R_TOTAL_DAY").toString()));
    String a6=application.getAttribute(counterSite+"_R_COUNT_DATE").toString();
   

try{
                    CallableStatement cstmt5=null;         
         
       pString = "{call p_INBER_COUNT_ACCOUNT_EDIT2("+siteid+","+a1+","+a2+","+a3+","+a4+","+a5+",\'"+a6+"\')}";
       cstmt5=con.prepareCall(pString);
       cstmt5.executeUpdate();
       cstmt5.close();
      }
      catch(Exception ee)
      {
       System.out.println("call p_INBER_COUNT_ACCOUNT_EDIT2 is wrong:"+ee);
      }


          //count=0;
        
    //application.setAttribute(counterSite,new Integer(count));//得到初始值,
    application.setAttribute(counterSite+"Date1",new java.util.Date());//初始时间为系统当前时间
    //application.setAttribute(counterSite,new Integer(count));//计数器
   
////////////////////////////////////////////定时写数据库同时 初始化数据 end//////////////////
      
          }
//////////////检验数据2开始///////////////////////////////////////////////////////////
/*out.print("secondValue="+secondValue+"<BR>");
    out.print("counter="+count+"<BR>"+"counterSite="+counterSite+"<BR>");  
   
*/
//////////////检验数据2结束///////////////////////////////////////////////////////////  
   }
  
   else
   {//校验此计数器账号引用是否存在
   }
     
        }

  //System.out.println(count+":"+counterSite+" "+theIP); 
  // count++;
  

   //application.setAttribute(counterSite,new Integer(count)); 
  
 


} catch(SQLException e)
{
   System.out.println("cc:"+e);

out.close();
   }
   

    /**
     *处理Post请求
     */

    /**
     *获得初始化参数
     */
    public void init() throws ServletException
    {
     try{
      int ss=0;
    
     con=DataBaseConnection.getConnection();

   
   
  }
  catch (Exception e)
  {

    System.out.println("Error(con error):"+e);
  }
    }
     public void destroy()
    {
    
    
          int siteid=Integer.parseInt((application.getAttribute(counterSite+"_id").toString()));
  
    int a1=Integer.parseInt((application.getAttribute(counterSite+"_R_TODAY_SUM").toString()));
    int a2=Integer.parseInt((application.getAttribute(counterSite+"_R_TOM_SUM").toString()));
    int a3=Integer.parseInt((application.getAttribute(counterSite+"_R_THIS_MONTH_SUM").toString()));
    int a4=Integer.parseInt((application.getAttribute(counterSite+"_R_TOTAL_SUM").toString()));
    int a5=Integer.parseInt((application.getAttribute(counterSite+"_R_TOTAL_DAY").toString()));
    String a6=application.getAttribute(counterSite+"_R_COUNT_DATE").toString();
  try{
                   CallableStatement cstmt6=null;   
         
       pString = "{call p_INBER_COUNT_ACCOUNT_EDIT2("+siteid+","+a1+","+a2+","+a3+","+a4+","+a5+",\'"+a6+"\')}";
       cstmt6=con.prepareCall(pString);
       cstmt6.executeUpdate();
       cstmt6.close();   
         
          System.out.println("when the programe stoped execute this code automatic!");
          con.close();

        }
  catch (SQLException e)
  {

  System.out.println("desdory error:"+e);
  }
    }
   

}

   
    
   =====================

天哪... 没看懂

大概你是遇上并发操作的问题了. 所有的应用服务器都有并发的问题, 主要还是看的应用怎么去处理了. 要注意一下几点

1. 数据库操作得用事务, 而且避免脏读. 如果想避免别人并发操作你的数据, 可以使用锁
2. 对象上注意是否线程安全, 避免多个线程同时写变量
3. 更新数据使用相对值, 不要用绝对值. 如: update table set a = a + @value where ...

100000/天访问不算大, 如果没有并发峰值限制. 不需要太特殊得处理方法

http://community.csdn.net/Expert/topic/4332/4332118.xml?temp=.1796991

 

分享到:
评论

相关推荐

    tables-3.6.1-cp39-cp39-win_amd64.whl

    tables-3.6.1-cp39-cp39-win_amd64.whl

    基于springboot大学生心理咨询平台源码数据库文档.zip

    基于springboot大学生心理咨询平台源码数据库文档.zip

    Javaweb仓库管理系统项目源码.zip

    基于Java web 实现的仓库管理系统源码,适用于初学者了解Java web的开发过程以及仓库管理系统的实现。

    基于springboot智能推荐旅游平台源码数据库文档.zip

    基于springboot智能推荐旅游平台源码数据库文档.zip

    Ruby语言教程:从基础知识到高级特性的全面指南

    内容概要:本文是一份详尽的Ruby语言教程,首先介绍了Ruby语言的基本信息和发展背景。接着详细讲解了Ruby的基础语法,如变量、数据类型、运算符、控制流等,并深入探讨了面向对象编程的关键概念,包括类、对象、继承、封装和多态。随后介绍了Ruby的一些高级特性,如模块、异常处理、迭代器和文件I/O操作。最后,讨论了Ruby在Web开发中的应用,尤其是与Rails框架的结合。每个部分都配有相应的代码示例,帮助读者更好地理解和实践。 适合人群:适用于初学者和有一定基础的程序员,特别是对Ruby语言感兴趣的人。 使用场景及目标:学习和掌握Ruby语言的各项基础知识和高级特性,为进一步进行Web开发或其他相关编程打下坚实的基础。 其他说明:教程中的每一部分内容都有详细的解释和代码示例,非常适合自学和教学使用。

    L7_NDVI_sd.txt

    GEE训练教程——Landsat5、8和Sentinel-2、DEM和各2哦想指数下载

    基于springboot在线问诊系统源码数据库文档.zip

    基于springboot在线问诊系统源码数据库文档.zip

    基于springboot的流浪猫狗救助系统源码数据库文档.zip

    基于springboot的流浪猫狗救助系统源码数据库文档.zip

    value_at_a_point.ipynb

    GEE训练教程

    毕业设计&课设_利用 WiFi 实现室内定位,含定位 APP 与数据采集 APP.zip

    该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过严格测试运行成功才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

    SQLite参考手册中文CHM版最新版本

    本教程帮助您了解什么是 SQLite,它与 SQL 之间的不同,为什么需要它,以及它的应用程序数据库处理方式。需要的朋友们可以参考看看! SQLite是一个软件库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite是一个增长最快的数据库引擎,这是在普及方面的增长,与它的尺寸大小无关。SQLite 源代码不受版权限制。 什么是 SQLite? SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库,这意味着与其他数据库一样,您不需要在系统中配置。 就像其他数据库,SQLite 引擎不是一个独立的进程,可以按应用程序需求进行静态或动态连接。SQLite 直接访问其存储文件。 为什么要用 SQLite? 不需要一个单独的服务器进程或操作的系统(无服务器的)。 SQLite 不需要配置,这意味着不需要安装或管理。 一个完整的 SQLite 数据库是存储在一个单一的跨平台的磁盘文件。 SQLite 是非常小的,是轻量级的,完全配置时小于 400KiB,省略可选功能配置时小于250K

    基于springboot学生选课系统源码数据库文档.zip

    基于springboot学生选课系统源码数据库文档.zip

    【Android UI】SurfaceView中使用 Canvas 绘制可缩放大图

    【Android UI】SurfaceView中使用 Canvas 绘制可缩放大图 ( 拖动和缩放相关的变量 | Canvas 绘图函数 | 手势识别 多点触控流程 | 拖动图片 | 缩放图片 ) 博客链接:https://blog.csdn.net/shulianghan/article/details/143950948 一、需求分析 和 核心要点 说明 1、需求说明 2、核心要点 - 拖动和缩放相关的变量 3、核心要点 - Canvas 绘图函数 4、核心要点 - 手势识别 多点触控流程 5、核心要点 - 拖动图片 6、核心要点 - 缩放图片 二、完整代码示例 1、环境说明 2、SurfaceView 完整代码 3、运行结果

    基于springboot+web的二手闲置交易系统源码数据库文档.zip

    基于springboot+web的二手闲置交易系统源码数据库文档.zip

    band_computations.ipynb

    GEE训练教程

    毕业设计&课设_众筹平台系统,基于基础语言开发,含功能流程与运行步骤,适合新手学习借鉴.zip

    该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过严格测试运行成功才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

    基于SpringBoot的宠物寄领养网站源码数据库文档.zip

    基于SpringBoot的宠物寄领养网站源码数据库文档.zip

    基于springboot的电影院售票管理系统源码数据库文档.zip

    基于springboot的电影院售票管理系统源码数据库文档.zip

    毕业设计&课设_含构建设置及相关操作,基于特定技术,具体功能未详细说明.zip

    该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过严格测试运行成功才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

    工具变量上市公司企业银行贷款数据(2019-2024年).txt

    数据存放网盘,txt文件内包含下载链接及提取码,永久有效。失效会第一时间进行补充。样例数据及详细介绍参见文章:https://blog.csdn.net/T0620514/article/details/143956923

Global site tag (gtag.js) - Google Analytics