自动监控VPS负载并重启Web服务的脚本

483 views 五月 14, 11 by Timothy

VPS其实和一般的独立Linux服务器,在使用上基本没有区别,因为现在的虚拟化技术以及很成熟了,不过VPS和独服还是有一个很大的差异,那就是系统资源和性能上。通常,VPS都是由一个独立服务器划分出来的,所以在资源和性能优势上,远比不上独服。

就拿前段时间本VPS受到的DDOS攻击来说,其实DDOS也是利用大量发起的请求,导致被攻击VPS(或服务器)内存资源被耗尽,系统负载过高,而导致80端口的Http服务无响应,从而达到最终的攻击目的。DDOS虽然防不胜防,不过总还是有一些办法,能把DDOS的影响减小的。比如定时监控系统状态,然后自动重启Web服务,这也是本文要介绍的一种方法。 Read More

启用Lazy Load插件

71 views 六月 19, 10 by Timothy

Lazy Load是基于jQuery的插件,能让页面的加载更加有序。在遇到图片比较多的页面的时候,就更能派上用场了。由于Blog加载了jQuery,正好也可以用上这个。

具体的设置,可以参考A-Shun同学的相关文章。启用后试用了一下,效果还不错。推荐有兴趣的同学也试试。

Linq to Sql 之延迟加载与立即加载

404 views 十二月 20, 09 by Timothy

Linq的延迟加载

Linq to Sql中默认采用的模式就是延迟执行,所谓延迟执行,其实就是在获取对象本身时,并不会获取和其关联的其他对象,只有在访问其关联对象的时候,程序才会去加载关联对象的数据到内存中。这样的好处是程序不会在初次访问的时候,就加载大批量的数据,而是以一种延迟加载的方式进行处理,相对而言,对于系统和网络的性能开支会减小很多。对于一个默认的Linq to Sql查询,延迟加载就是其默认的设置,不过,在某些情况下,延迟加载并非完全“智能”,不但没有实现其本意,反而增大了网络流量和性能开支。下面我们以SQL Server中的演示数据库NorthWind来试验一下:

linq_context

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
LinqTestDataContext ctx = new LinqTestDataContext();
ctx.Log = Console.Out;
 
var result = ctx.Orders.Where(p => p.OrderID == 10251);
 
foreach (var t in result)
{
	Console.WriteLine("OrderID:" 
		+ t.OrderID 
		+ "-" 
		+ "OrderDate:" 
		+ t.OrderDate.Value.ToString("yyyy-MM-dd"));
}

通过Linq to sql查询所有OrderID为10251的订单信息,并输出订单编号和订单日期。通过显示Linq的日志输出,我们可以看到后台生成的SQL语句如下:

1
2
3
4
5
6
SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [
t0].[RequiredDate], [t0].[ShippedDate], [t0].[ShipVia], [t0].[Freight], [t0].[Sh
ipName], [t0].[ShipAddress], [t0].[ShipCity], [t0].[ShipRegion], [t0].[ShipPosta
lCode], [t0].[ShipCountry]
FROM [dbo].[Orders] AS [t0]
WHERE [t0].[OrderID] = @p0

输出的SQL看来还比较正常。下面我们再来改一下我们的程序:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 foreach (var t in result)
            {
                Console.WriteLine("OrderID:" + t.OrderID 
		+ "-OrderDate:" 
		+ t.OrderDate.Value.ToString("yyyy-MM-dd") 
		+"-CustomerName:"
		+ t.Customer.ContactName);
                foreach(var m in t.Order_Details)
                Console.WriteLine("ProductID:" 
		+ m.ProductID 
		+ "-Price:" 
		+ m.UnitPrice 
		+ "-Amount:" 
		+ m.Quantity);
            }

出了输出订单相关信息外,还输出其关联对象:客户姓名、订单中的产品编号、单价、数量

再来看看输出的SQL语句:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [
t0].[RequiredDate], [t0].[ShippedDate], [t0].[ShipVia], [t0].[Freight], [t0].[Sh
ipName], [t0].[ShipAddress], [t0].[ShipCity], [t0].[ShipRegion], [t0].[ShipPosta
lCode], [t0].[ShipCountry]
FROM [dbo].[Orders] AS [t0]
WHERE [t0].[OrderID] = @p0
 
 
SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactT
itle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Coun
try], [t0].[Phone], [t0].[Fax]
FROM [dbo].[Customers] AS [t0]
WHERE [t0].[CustomerID] = @p0
 
 
SELECT [t0].[OrderID], [t0].[ProductID], [t0].[UnitPrice], [t0].[Quantity], [t0]
.[Discount]
FROM [dbo].[Order Details] AS [t0]
WHERE [t0].[OrderID] = @p0

我们可以看到,对于我们修改后的代码,程序向数据库请求了三条SQL语句,当然,这还不是最坏的情况,但是我们在这里的确看到延迟加载似乎“变了味道”,不但没有节省开支,反而增大了网络浏览。怎样才能改善这样的情况呢?

关于立即加载

其实我们知道,有很多扩展方法会导致延迟加载失效,而开始立即执行。当我们在调用诸如:ToList、ToDictionary、ToLookup或者ToArray之类的扩展方法之后,程序会将最终的结果存放到某个临时的变量集合中,并让所有的数据一次性的加载完成。

另外,还有一种方式,通过设置DataContext的DeferredLoadingEnabled属性为false,显示的关闭默认的延迟加载方式。

?View Code CSHARP
1
2
LinqTestDataContext ctx = new LinqTestDataContext();
ctx.DeferredLoadingEnabled = false;

 

这些方式虽然比较方便,但是还是有一定的局限性。例如,简单的使用ToList只能解决一些简单的查询问题,而对于复杂的查询需求,ToList还是不能解决延迟取得子对象所引发的多次查询问题。并且,在大量数据被加载到内存中的时候,对内存的需求也是很大的。不过,幸好Linq to sql给我们提供了另外一套不错的方法。

使用DataLoadOptions实现对加载对象的优化

Linq to Sql提供DataLoadOptions,用以立即加载关联的对象数据,其中包含两种方法:

LoadWith方法,用于立即加载与主对象相关联的数据

AssociateWith方法,用于对关联对象的数据进行筛选,并加载

有了DataLoadOptions,我们就可以用如下的方式优化我们的查询中需要加载的对象:

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
            LinqTestDataContext ctx = new LinqTestDataContext();
            ctx.Log = Console.Out;
 
            DataLoadOptions dl = new DataLoadOptions();
            dl.LoadWith<order>(p => p.Customer);
            dl.LoadWith<order>(p => p.Order_Details);
            ctx.LoadOptions = dl;
 
            var result = ctx.Orders.Where(p => p.OrderID == 10251).ToList();
 
            foreach (var t in result)
            {
                Console.WriteLine("OrderID:" + 
		t.OrderID 
		+ "-OrderDate:" 
		+ t.OrderDate.Value.ToString("yyyy-MM-dd") 
		+"-CustomerName:"
		+ t.Customer.ContactName);
                foreach(var m in t.Order_Details)
                Console.WriteLine("ProductID:" 
		+ m.ProductID 
		+ "-Price:" 
		+ m.UnitPrice 
		+ "-Amount:" 
		+ m.Quantity);
            }

对于我们开发者而言,需要注意的是,对于同一个DataContext实例,DataLoadOptions只能设定一次,并且一旦设定,就无法更改。

接下来,运行程序,看看优化后,程序向数据库服务器请求的的SQL:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [
t0].[RequiredDate], [t0].[ShippedDate], [t0].[ShipVia], [t0].[Freight], [t0].[Sh
ipName], [t0].[ShipAddress], [t0].[ShipCity], [t0].[ShipRegion], [t0].[ShipPosta
lCode], [t0].[ShipCountry], [t3].[OrderID] AS [OrderID2], [t3].[ProductID], [t3]
.[UnitPrice], [t3].[Quantity], [t3].[Discount], (
    SELECT COUNT(*)
    FROM [dbo].[Order Details] AS [t4]
    WHERE [t4].[OrderID] = [t0].[OrderID]
    ) AS [value], [t2].[test], [t2].[CustomerID] AS [CustomerID2], [t2].[Company
Name], [t2].[ContactName], [t2].[ContactTitle], [t2].[Address], [t2].[City], [t2
].[Region], [t2].[PostalCode], [t2].[Country], [t2].[Phone], [t2].[Fax]
FROM [dbo].[Orders] AS [t0]
LEFT OUTER JOIN (
    SELECT 1 AS [test], [t1].[CustomerID], [t1].[CompanyName], [t1].[ContactName
], [t1].[ContactTitle], [t1].[Address], [t1].[City], [t1].[Region], [t1].[Postal
Code], [t1].[Country], [t1].[Phone], [t1].[Fax]
    FROM [dbo].[Customers] AS [t1]
    ) AS [t2] ON [t2].[CustomerID] = [t0].[CustomerID]
LEFT OUTER JOIN [dbo].[Order Details] AS [t3] ON [t3].[OrderID] = [t0].[OrderID]
 
WHERE [t0].[OrderID] = @p0
ORDER BY [t0].[OrderID], [t2].[CustomerID], [t3].[ProductID]

可以看出,之前的分三次向数据库提交sql的情况,现在被程序优化为一条带LEFT JOIN的关联查询,而获取关联数据。三次SQL请求,被优化为一次,从而减少了数据库和网络流量开支,由此看来DataLoadOptions的好处不言而喻。

一点小结

延迟加载与立即加载,并无孰优孰劣之区别,在某些情况下,需要我们根据自己的需求和实际情况来选择来进行选择。

动态加载并显示图片

177 views 十二月 22, 04 by Timothy

HBITMAP hbitmap=(HBITMAP)::LoadImage(AfxGetInstanceHandle(),”**.bmp”, IMAGE_BITMAP,0,0, LR_CREATEDIBSECTION|LR_LOADFROMFILE);
if(hbitmap==NULL)
return FALSE;
CBitmap m_bitmap;
m_bitmap.Attach(hbitmap);
HBITMAP hbitmap;
//先用上面的方法动态的装载位图,然后把图片显示到Static控件上
//获得指向静态控件的指针
CStatic *pStatic=(CStatic *)GetDlgItem(IDC_SHOWBMP);
//获得位图句柄
HBITMAP Bitmap;
//设置静态控件的样式,使其可以使用位图,并试位标显示使居中
pStatic->ModifyStyle(0xF,SS_BITMAP|SS_CENTERIMAGE);
//设置静态控件显示位图
pStatic->SetBitmap(hBitmap);

动态加载位图

156 views 十二月 20, 04 by Timothy

void CCreateRandomBMPDlg::OnBtnTest()
{
// TODO: Add your control notification handler code here
HBITMAP hBmp;

CFileDialog dlg(TRUE, “bmp”, NULL, 0, “位图文件 (*.bmp)|*.bmp||”, this);

if (dlg.DoModal() != IDOK)
{
return;
}

hBmp = (HBITMAP) LoadImage(NULL, dlg.GetPathName(), IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE | LR_CREATEDIBSECTION);

if (hBmp == NULL)
{
return;
}

BITMAP bm;
PBITMAPINFO bmpInf;

if (GetObject(hBmp, sizeof(bm), &bm) == 0)
return ;

int nPaletteSize = 0;

if (bm.bmBitsPixel < 16)
nPaletteSize = (int) pow(2, bm.bmBitsPixel);

bmpInf = (PBITMAPINFO) LocalAlloc(LPTR,
sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * nPaletteSize);

//-----------------------------------------------
bmpInf->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInf->bmiHeader.biWidth = bm.bmWidth;
bmpInf->bmiHeader.biHeight = bm.bmHeight;
bmpInf->bmiHeader.biPlanes = bm.bmPlanes;
bmpInf->bmiHeader.biBitCount = bm.bmBitsPixel;
bmpInf->bmiHeader.biCompression = BI_RGB;
bmpInf->bmiHeader.biSizeImage = (bm.bmWidth + 7) /
8 * bm.bmHeight * bm.bmBitsPixel;
bmpInf->bmiHeader.biXPelsPerMeter = 0;
bmpInf->bmiHeader.biYPelsPerMeter = 0;
bmpInf->bmiHeader.biClrUsed = 0;
bmpInf->bmiHeader.biClrImportant = 0;
//———————————————–

HDC hDC = ::GetWindowDC(NULL);
if (!::GetDIBits(hDC, hBmp, 0, (WORD) bm.bmHeight, NULL, bmpInf,
DIB_RGB_COLORS))
{
LocalFree(bmpInf);
::ReleaseDC(NULL, hDC);
return ;
}

void* buf = (void*) new char[bmpInf->bmiHeader.biSizeImage];
if (buf == NULL)
{
::ReleaseDC(NULL, hDC);
LocalFree(bmpInf);
return ;
}

if (!::GetDIBits(hDC, hBmp, 0, (UINT) bm.bmHeight, buf, bmpInf,
DIB_RGB_COLORS))
{
::ReleaseDC(NULL, hDC);
delete[]buf;
LocalFree(bmpInf);
return ;
}

::ReleaseDC(NULL, hDC);

CString sMsg;
sMsg.Format(“BitsPixel:%d,width:%d,height:%d”, bm.bmBitsPixel, bm.bmWidth,
bm.bmHeight);

AfxMessageBox(sMsg);

CClientDC dc(this);

if (bm.bmBitsPixel == 8) {
BYTE* pData = (BYTE*) buf;

int nWidth = bm.bmWidth;
while (nWidth % 4 != 0)
{
//Bmp每行数据都是4个字节的整数倍。
nWidth++;
}

for (int i = 0; i < bm.bmHeight; i++)
{
for (int j = 0; j < bm.bmWidth; j++)
{
RGBQUAD rgbQ;
rgbQ = bmpInf->bmiColors[pData[i * nWidth + j]];
dc.SetPixel(j, bm.bmHeight – i,
RGB(rgbQ.rgbRed, rgbQ.rgbGreen, rgbQ.rgbBlue));
}
}
}
else if (bm.bmBitsPixel == 16)
{
BYTE* pData = (BYTE*) buf;

int nWidth = bm.bmWidth*2;
while (nWidth % 4 != 0)
{
nWidth++;
}

BYTE red, green, blue;

for (int i = 0; i < bm.bmHeight; i++)
{
for (int j = 0; j < bm.bmWidth; j++)
{
blue = pData[i * nWidth + j * 2] & 0x1F;
green = pData[i * nWidth + j * 2] >> 5;
green |= (pData[i * nWidth + j * 2 + 1] & 0×03) << 3;
red = (pData[i * nWidth + j * 2 + 1] >> 2) & 0x1F;

WORD wRed = red*8;
WORD wBlue = blue*8;
WORD wGreen = green*8;

red = min(255, wRed);
blue = min(255, wBlue);
green = min(255, wGreen);

dc.SetPixel(j, bm.bmHeight – i, RGB(red, green, blue));
}
}
}
else if (bm.bmBitsPixel == 24)
{
BYTE* pData = (BYTE*) buf;

int nWidth = bm.bmWidth*3;
while (nWidth % 4 != 0)
{
nWidth++;
}

for (int i = 0; i < bm.bmHeight; i++)
{
for (int j = 0; j < bm.bmWidth; j++)
{
dc.SetPixel(j, bm.bmHeight -
i,
RGB(pData[i * nWidth + j * 3 + 2],
pData[i * nWidth + j * 3 + 1],
pData[i * nWidth + j * 3]));
}
}
}
else if (bm.bmBitsPixel == 32)
{
BYTE* pData = (BYTE*) buf;

int nWidth = bm.bmWidth*4;

for (int i = 0; i < bm.bmHeight; i++)
{
for (int j = 0; j < bm.bmWidth; j++)
{
dc.SetPixel(j, bm.bmHeight -
i,
RGB(pData[i * nWidth + j * 4 + 2],
pData[i * nWidth + j * 4 + 1],
pData[i * nWidth + j * 4]));
}
}
}

delete[]buf;

DeleteObject(hBmp);
LocalFree(bmpInf);
}

从文件装载图象

96 views 十月 26, 04 by Timothy

*******************************************************************
* 这是从文件里装放位图
*
*******************************************************************/
BOOL CXxxView::OnDraw(CDC* pDC)
{
HBITMAP bitmap,OldBitmap;
bitmap = (HBITMAP)LoadImage(NULL,”xxx.bmp”,IMAGE_BITMAP,
0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
CDC MemDC;
MemDC.CreateCompatibleDC(pDC);
OldBitmap=(HBITMAP)MemDC.SelectObject(bitmap);
pDC->BitBlt(0,0,400,300,&MemDC,0,0,SRCCOPY);
MemDC.SelectObject(OldBitmap);
return TRUE;
}

动态加载DLL

153 views 十月 26, 04 by Timothy

核心代码片断:

void CLoadLibraryTestDlg::OnLoad()
{
typedef int (WINAPI * MyFun)(HWND,LPCTSTR,LPCTSTR,UINT);
MyFun fun=NULL;
HINSTANCE hHandle;
hHandle=LoadLibrary(“user32.dll”);
fun=(int (WINAPI *)(HWND,LPCTSTR,LPCTSTR,UINT))::GetProcAddress(hHandle,”MessageBoxA”);
if(fun!=NULL)
{
fun(NULL,”hahahahahahahaha”,”success :) ”,MB_OK);
}
}