为完成网站访问计数器可是伤透脑筋,今天完成了第一个版本,记录信息如下:
1、记录每天的访问用户数
2、记录每天的点击次数
就为实现这两个简单功能,也让我着实头痛,暂时没有太多考虑性能,只是实现。
简单说明一下:
由于为了精确实现计数器,那么要么简单使用Application.Lock锁定线程,要么自己写多线程的程序,他们都会造成系统性能的严重影响,因此,在锁定线程期间做的事情越少越好,因此不能频繁的往数据库写用户访问的计数统计信息,我使用了间隔一段时间写一次的方法,可以减少往数据库记录数据的次数,下面的代码在Application_EndRequest中检查用户上次记录数据的时间到现在是否超过了设定的时间间隔,如果是,那么再次记录,这样就极大的减少了写数据库的次数,对性能的影响和数据库服务器的影响也小一些。
如果服务器停止,那么最后一次时间间隔内的用户访问可能不会被记录,因此在Application_End事件中进行记录。
往数据库中传递的参数为:当前日期(yyyy-MM-dd格式),计数类别:用户数/页面点击数,计数。在存储过程中首先以日期参数为主键更新数据,如果更新失败(当天还没有记录过),那么插入新数据。数据库中该表有三个字段:TodayDate(Date),TodayVisitCNT(number),TodayClickCNT(number)。TodayDate为主键。
Option Explicit On
Option Strict On
Imports System
Imports System.Web
Imports System.Web.SessionState
Imports System.Runtime.Remoting
Imports System.IO
Imports Microsoft.VisualBasic
Namespace MyWeb
Public Class Global
Inherits System.Web.HttpApplication
' 保存访问计数
Private Shared _visitCount As New Hashtable
' 记录最后一次更新计数信息的时间
Private Shared _lastUpdate As DateTime
#Region " 组件设计器生成的代码 "
Public Sub New()
MyBase.New()
'该调用是组件设计器所必需的。
InitializeComponent()
'在 InitializeComponent() 调用之后添加任何初始化
End Sub
'组件设计器所必需的
Private components As System.ComponentModel.IContainer
'注意:以下过程是组件设计器所必需的
'可以使用组件设计器修改此过程。
'不要使用代码编辑器修改它。
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
components = New System.ComponentModel.Container
End Sub
#End Region
#Region "系统事件"
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
' 系统启动时间定为最后一次更新时间
_lastUpdate = DateTime.Now
End Sub
Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
' 当前日期访问用户数加1
Application.Lock()
Dim Key As String = Now.ToString("yyyy-MM-dd") & "_USERCOUNT"
_visitCount(Key) = CInt(_visitCount(Key)) + 1
Application.UnLock()
End Sub
Sub Application_EndRequest(ByVal sender As Object, ByVal e As EventArgs)
' 用户日期页面请求次数增加1,到一定访问量以后记录到数据库
Application.Lock()
Dim Key As String = Now.ToString("yyyy-MM-dd") & "_PAGECOUNT"
Dim count As Integer
count = CInt(_visitCount(Key))
count += 1
_visitCount(Key) = count
' 如果上次记录时间超过了指定的时间间隔,那么再次记录计数器
If DateTime.Now.Subtract(_lastUpdate).TotalSeconds > 60 Then
' 1、往数据库记录所有访问信息
Dim item As String
Dim mDate As Date
Dim mType As String
Dim mCount As Integer
For Each item In _visitCount.Keys
mCount = CInt(_visitCount(item))
mDate = CDate(Split(item, "_")(0))
mType = CStr(Split(item, "_")(1))
' 往数据库写数据
With New BusinessFacade.PagesSystem
.VisitCountLog(mDate, mType, mCount)
End With
Next
' 2、将计数器归零
_visitCount.Clear()
' 将记录时间更新
_lastUpdate = DateTime.Now
End If
Application.UnLock()
End Sub
Sub Application_End(ByVal sender As Object, ByVal e As EventArgs)
' 在应用程序结束时激发
' 1、往数据库记录所有访问信息
Dim item As String
Dim mDate As Date
Dim mType As String
Dim mCount As Integer
For Each item In _visitCount.Keys
mCount = CInt(_visitCount(item))
mDate = CDate(Split(item, "_")(0))
mType = CStr(Split(item, "_")(1))
With New BusinessFacade.PagesSystem
.VisitCountLog(mDate, mType, mCount)
End With
Next
' 2、将计数器归零
_visitCount.Clear()
End Sub
#End Region
End Class
End Namespace