C# 出来也有些日子了,最近由于编程的需要,对 C# 的类型转换做了一些研究,其内容涉及 C# 的装箱/拆箱/别名、数值类型间相互转换、字符的 ASCII 码和 Unicode 码、数值字符串和数值之间的转换、字符串和字符数组/字节数组之间的转换、各种数值类型和字节数组之间的转换、十六进制数输出以及日期型数据的一些转换处理,在这里与大家分享——

1. 装箱、拆箱还是别名

    许多 C#.NET 的书上都有介绍 int -> Int32 是一个装箱的过程,反之则是拆箱的过程。许多其它变量类型也是如此,如:short <-> Int16,long <-> Int64 等。对于一般的程序员来说,大可不必去了解这一过程,因为这些装箱和拆箱的动作都是可以自动完成的,不需要写代码进行干预。但是我们需要记住这些类型之间的关系,所以,我们使用“别名”来记忆它们之间的关系。
    C# 是全面向对象的语言,比 Java 的面向对象都还彻底——它把简单数据类型通过默认的装箱动作封装成了类。Int32、Int16、Int64 等就是相应的类名,而那些我们熟悉的、简单易记的名称,如 int、short、long 等,我们就可以把它称作是 Int32、Int16、Int64 等类型的别名。
    那么除了这三种类型之外,还有哪些类有“别名”呢?常用的有如下一些:

    bool -> System.Boolean (布尔型,其值为 true 或者 false)
    char -> System.Char (字符型,占有两个字节,表示 1 个 Unicode 字符)
    byte -> System.Byte (字节型,占 1 字节,表示 8 位正整数,范围 0 ~ 255)
    sbyte -> System.SByte (带符号字节型,占 1 字节,表示 8 位整数,范围 -128 ~ 127)
    ushort -> System.UInt16 (无符号短整型,占 2 字节,表示 16 位正整数,范围 0 ~ 65,535)
    uint -> System.UInt32 (无符号整型,占 4 字节,表示 32 位正整数,范围 0 ~ 4,294,967,295)
    ulong -> System.UInt64 (无符号长整型,占 8 字节,表示 64 位正整数,范围 0 ~ 大约 10 的 20 次方)
    short -> System.Int16 (短整型,占 2 字节,表示 16 位整数,范围 -32,768 ~ 32,767)
    int -> System.Int32 (整型,占 4 字节,表示 32 位整数,范围 -2,147,483,648 到 2,147,483,647)
    long -> System.Int64  (长整型,占 8 字节,表示 64 位整数,范围大约 -(10 的 19) 次方 到 10 的 19 次方)
    float -> System.Single (单精度浮点型,占 4 个字节)
    double -> System.Double (双精度浮点型,占 8 个字节)

    我们可以用下列代码做一个实验

    private void TestAlias() {
        // this.textBox1 是一个文本框,类型为 System.Windows.Forms.TextBox
        // 设计中已经将其 Multiline 属性设置为 true
        byte a = 1; char b = ‘a‘; short c = 1;
        int d = 2; long e = 3; uint f = 4; bool g = true;
        this.textBox1.Text = ;
        this.textBox1.AppendText(byte -> + a.GetType().FullName +
);

        this.textBox1.AppendText(char -> + b.GetType().FullName +
);

        this.textBox1.AppendText(short -> + c.GetType().FullName +
);

        this.textBox1.AppendText(int -> + d.GetType().FullName +
);

        this.textBox1.AppendText(long -> + e.GetType().FullName +
);

        this.textBox1.AppendText(uint -> + f.GetType().FullName +
);

        this.textBox1.AppendText(bool -> + g.GetType().FullName +
);

    }

    在窗体中新建一个按钮,并在它的单击事件中调用该 TestAlias() 函数,我们将看到运行结果如下:

    byte -> System.Byte
    char -> System.Char
    short -> System.Int16
    int -> System.Int32
    long -> System.Int64
    uint -> System.UInt32
    bool -> System.Boolean

    这足以说明各别名对应的类!

2. 数值类型之间的相互转换

    这里所说的数值类型包括 byte, short, int, long, fload, double 等,根据这个排列顺序,各种类型的值依次可以向后自动进行转换。举个例来说,把一个 short 型的数据赋值给一个 int 型的变量,short 值会自动行转换成 int 型值,再赋给 int 型变量。如下例:

    private void TestBasic() {
        byte a = 1; short b = a; int c = b;
        long d = c; float e = d; double f = e;
        this.textBox1.Text = ;
        this.textBox1.AppendText(byte a = + a.ToString() +
);

        this.textBox1.AppendText(short b = + b.ToString() +
);

        this.textBox1.AppendText(int c = + c.ToString() +
);

        this.textBox1.AppendText(long d = + d.ToString() +
);

        this.textBox1.AppendText(float e = + e.ToString() +
);

        this.textBox1.AppendText(double f = + f.ToString() +
);

    }

    编译顺利通过,运行结果是各变量的值均为 1;当然,它们的类型分别还是 System.Byte 型……System.Double 型。现在我们来试试,如果把赋值的顺序反过来会怎么样呢?在 TestBasic() 函数中追加如下语句:

        int g = 1;
        short h = g;
        this.textBox1.AppendText(h = + h.ToString() +
);

    结果编译报错:
    G:ProjectsVisual C#ConvertForm1.cs(118): 无法将类型“int”隐式转换为“short”
    其中,Form1.cs 的 118 行即 short h = g 所在行。

    这个时候,如果我们坚持要进行转换,就应该使用强制类型转换,这在 C 语言中常有提及,就是使用“(类型名) 变量名”形式的语句来对数据进行强制转换。如上例修改如下:

        short g = 1;
        byte h = (byte) g;  // 将 short 型的 g 的值强制转换成 short 型后再赋给变量 h
        this.textBox1.AppendText(h = + h.ToString() +
);

    编译通过,运行结果输出了 h = 1,转换成功。
    但是,如果我们使用强制转换,就不得不再考虑一个问题:short 型的范围是 -32768 ~ 23767,而 byte 型的范围是 0 ~ 255,那么,如果变量 g 的大小超过了 byte 型的范围又会出现什么样的情况呢?我们不妨再一次改写代码,将值改为 265,比 255 大 10

        short g = 265; //265 = 255 + 10
        byte h = (byte) g;
        this.textBox1.AppendText(h = + h.ToString() +
);

    编译没有出错,运行结果却不是 h = 265,而是 h = 9。
    因此,我们在进行转换的时候,应当注意被转换的数据不能超出目标类型的范围。这不仅体现在多字节数据类型(相对,如上例的 short) 转换为少字节类型(相对,如上例的 byte) 时,也体现在字节数相同的有符号类型和无符号类型之间,如将 byte 的 129 转换为 sbyte 就会溢出。这方面的例子大同小异,就不详细说明了。

3. 字符的 ASCII 码和 Unicode 码

    很多时候我们需要得到一个英文字符的 ASCII 码,或者一个汉字字符的 Unicode 码,或者从相关的编码查询它是哪一个字符的编码。很多人,尤其是从 VB 程序序转过来学 C# 的人,会报怨 C# 里为什么没有提供现成的函数来做这个事情——因为在 VB 中有 Asc() 函数和 Chr() 函数用于这类转换。
    但是如果你学过 C,你就会清楚,我们只需要将英文字符型数据强制转换成合适的数值型数据,就可以得到相应的 ASCII 码;反之,如果将一个合适的数值型数据强制转换成字符型数据,就可以得到相应的字符。
    C# 中字符的范围扩大了,不仅包含了单字节字符,也可以包含双字节字符,如中文字符等。而在字符和编码之间的转换,则仍延用了 C 语言的做法——强制转换。不妨看看下面的例子

    private void TestChar() {
        char ch = ‘a‘; short ii = 65;
        this.textBox1.Text = ;
        this.textBox1.AppendText(The ASCII code of ‘ + ch + ‘ is: + (short) ch +
);

        this.textBox1.AppendText(ASCII is + ii.ToString() + , the char is: + (char) ii +
);

        char cn = ‘中‘; short uc = 22478;
        this.textBox1.AppendText(The Unicode of ‘ + cn + ‘ is: + (short) cn +
);

        this.textBox1.AppendText(Unicode is + uc.ToString() + , the char is: + (char) uc +
);

    }

    它的运行结果是

    The ASCII code of ‘a‘ is: 97
    ASCII is 65, the char is: A
    The Unicode of ‘中‘ is: 20013
    Unicode is 22478, the char is: 城

    从这个例子中,我们便能非常清楚的了解——通过强制转换,可以得以字符的编码,或者得到编码表示的字符。如果你需要的不是 short 型的编码,请参考第 1 条进行转换,即可得到 int 等类型的编码值。

4. 数值字符串和数值之间的转换

    首先,我们得搞明白,什么是数值字符串。我们知道,在 C# 中,字符串是用一对双引号包含的若干字符来表示的,如 123。而 123 又相对特殊,因为组成该字符串的字符都是数字,这样的字符串,就是数值字符串。在我们的眼中,这即是一串字符,也是一个数,但计算机却只认为它是一个字符串,不是数。因此,我们在某些时候,比如输入数值的时候,把字符串转换成数值;而在另一些时候,我们需要相反的转换。
    将数值转换成字符串非常简单,因为每一个类都有一个 void ToString() 方法。所有数值型的 void ToString() 方法都能将数据转换为数值字符串。如 123.ToSting() 就将得到字符串 123。
    那么反过来,将数值型字符串转换成数值又该怎么办呢?我们仔细查找一下,会发现 short, int, float 等数值类型均有一个 static Parse() 函数。这个函数就是用来将字符串转换为相应数值的。我们以一个 float 类型的转换为例: float f = float.Parse(543.21); 其结果 f 的值为 543.21F。当然,其它的数值类型也可以使用同样的方法进行转换,下面的例子可以更明确的说明转换的方法:

    private void TestStringValue() {
        float f = 54.321F;
        string str = 123;
        this.textBox1.Text = ;
        this.textBox1.AppendText(f = + f.ToString() +
);

        if (int.Parse(str) == 123) {
            this.textBox1.AppendText(str convert to int successfully.);
        } else {
            this.textBox1.AppendText(str convert to int failed.);
        }
    }

    运行结果:

    f = 54.321
    str convert to int successfully.

5. 字符串和字符数组之间的转换

    字符串类 System.String 提供了一个 void ToCharArray() 方法,该方法可以实现字符串到字符数组的转换。如下例:

    private void TestStringChars() {
        string str = mytest;
        char[] chars = str.ToCharArray();
        this.textBox1.Text = ;
        this.textBox1.AppendText(Length of mytest is + str.Length +
);

        this.textBox1.AppendText(Length of char array is + chars.Length +
);

        this.textBox1.AppendText(char[2] = + chars[2] +
);

    }

    例中以对转换转换到的字符数组长度和它的一个元素进行了测试,结果如下:

    Length of mytest is 6
    Length of char array is 6
    char[2] = t

    可以看出,结果完全正确,这说明转换成功。那么反过来,要把字符数组转换成字符串又该如何呢?
    我们可以使用 System.String 类的构造函数来解决这个问题。System.String 类有两个构造函数是通过字符数组来构造的,即 String(char[]) 和 String[char[], int, int)。后者之所以多两个参数,是因为可以指定用字符数组中的哪一部分来构造字符串。而前者则是用字符数组的全部元素来构造字符串。我们以前者为例,在 TestStringChars() 函数中输入如下语句:

        char[] tcs = {‘t‘, ‘e‘, ‘s‘, ‘t‘, ‘ ‘, ‘m‘, ‘e‘};
        string tstr = new String(tcs);
        this.textBox1.AppendText(tstr = + tstr + \n);

    运行结果输入 tstr = test me,测试说明转换成功。
    实际上,我们在很多时候需要把字符串转换成字符数组只是为了得到该字符串中的某个字符。如果只是为了这个目的,那大可不必兴师动众的去进行转换,我们只需要使用 System.String 的 [] 运算符就可以达到目的。请看下例,再在 TestStringChars() 函数中加入如如下语名:

        char ch = tstr[3];
        this.textBox1.AppendText( + tstr + [3] = + ch.ToString());

    正确的输出是 test me[3] = t,经测试,输出正确。

6. 字符串和字节数组之间的转换

    如果还想从 System.String 类中找到方法进行字符串和字节数组之间的转换,恐怕你会失望了。为了进行这样的转换,我们不得不借助另一个类:System.Text.Encoding。该类提供了 bye[] GetBytes(string) 方法将字符串转换成字节数组,还提供了 string GetString(byte[]) 方法将字节数组转换成字符串。
    System.Text.Encoding 类似乎没有可用的构造函数,但我们可以找到几个默认的 Encoding,即 Encoding.Default(获取系统的当前 ANSI 代码页的编码)、Encoding.ASCII(获取 7 位 ASCII 字符集的编码)、Encoding.Unicode(获取采用 Little-Endian 字节顺序的 Unicode 格式的编码)、Encoding.UTF7(获取 UTF-7 格式的编码)、Encoding.UTF8(获取 UTF-8 格式的编码) 等。这里主要说说 Encoding.Default 和 Encoding.Unicode 用于转换的区别。
    在字符串转换到字节数组的过程中,Encoding.Default 会将每个单字节字符,如半角英文,转换成 1 个字节,而把每个双字节字符,如汉字,转换成 2 个字节。而 Encoding.Unicode 则会将它们都转换成两个字节。我们可以通过下列简单的了解一下转换的方法,以及使用 Encoding.Default 和 Encodeing.Unicode 的区别:

    private void TestStringBytes() {
        string s = C#语言;
        byte[] b1 = System.Text.Encoding.Default.GetBytes(s);
        byte[] b2 = System.Text.Encoding.Unicode.GetBytes(s);
        string t1 = , t2 = ;
        foreach (byte b in b1) {
            t1 += b.ToString() + ;
        }
        foreach (byte b in b2) {
            t2 += b.ToString() + ;
        }
        this.textBox1.Text = ;
        this.textBox1.AppendText(b1.Length = + b1.Length +
);
        this.textBox1.AppendText(t1 +
);
        this.textBox1.AppendText(b2.Length = + b2.Length +
);
        this.textBox1.AppendText(t2 +
);
    }

    运行结果如下,不说详述,相信大家已经明白了。

    b1.Length = 6
    67 35 211 239 209 212
    b2.Length = 8
    67 0 35 0 237 139 0 138

    将字节数组转换成字符串,使用 Encoding 类的 string GetString(byte[]) 或 string GetString(byte[], int, int) 方法,具体使用何种 Encoding 还是由编码决定。在 TestStringBytes() 函数中添加如下语句作为实例:

        byte[] bs = {97, 98, 99, 100, 101, 102};
        string ss = System.Text.Encoding.ASCII.GetString(bs);
        this.textBox1.AppendText(The string is: + ss +
);

    运行结果为:The string is: abcdef

7. 各种数值类型和字节数组之间的转换

    在第 1 条中我们可以查到各种数值型需要使用多少字节的空间来保存数据。将某种数值类型的数据转换成字节数组的时候,得到的一定是相应大小的字节数组;同样,需要把字节数组转换成数值类型,也需要这个字节数组大于相应数值类型的字节数。
    现在介绍此类转换的主角:System.BitConverter。该类提供了 byte[] GetBytes(…) 方法将各种数值类型转换成字节数组,也提供了 ToInt32、ToInt16、ToInt64、ToUInt32、ToSignle、ToBoolean 等方法将字节数组转换成相应的数值类型。

    由于这类转换通常只是在需要进行较细微的编码/解码操作时才会用到,所以这里就不详细叙述了,仅把 System.BitConverter 类介绍给大家。

8. 转换成十六进制

    任何数据在计算机内部都是以二进制保存的,所以进制与数据的存储无关,只与输入输出有关。所以,对于进制转换,我们只关心字符串中的结果。
    在上面的第 4 条中提到了 ToString() 方法可以将数值转换成字符串,不过在字符串中,结果是以十进制显示的。现在我们带给它加一些参数,就可以将其转换成十六进制——使用 ToString(string) 方法。
    这里需要一个 string 类型的参数,这就是格式说明符。十六进制的格式说明符是 x 或者 X,使用这两种格式说明符的区别主要在于 A-F 六个数字:x 代表 a-f 使用小写字母表示,而 X 而表示 A-F 使用大字字母表示。如下例:

    private void TestHex() {
        int a = 188;
        this.textBox1.Text = ;
        this.textBox1.AppendText(a(10) = + a.ToString() +
);
        this.textBox1.AppendText(a(16) = + a.ToString(x) +
);
        this.textBox1.AppendText(a(16) = + a.ToString(X) +
);
    }

    运行结果如下:

    a(10) = 188
    a(16) = bc
    a(16) = BC

    这时候,我们可能有另一种需求,即为了显示结果的整齐,我们需要控制十六进制表示的长度,如果长度不够,用前导的 0 填补。解决这个问题,我们只需要在格式说明符“x”或者“X”后写上表示长度的数字就行了。比如,要限制在 4 个字符的长度,可以写成“X4”。在上例中追加一句:

        this.textBox1.AppendText(a(16) = + a.ToString(X4) +
);

    其结果将输出 a(16) = 00BC。
    现在,我们还要说一说如何将一个表示十六进制数的字符串转换成整型。这一转换,同样需要借助于 Parse() 方法。这里,我需要 Parse(string, System.Globalization.NumberStyles) 方法。第一个参数是表示十六进制数的字符串,如“AB”、“20”(表示十进制的 32) 等。第二个参数 System.Globalization.NumberStyles 是一个枚举类型,用来表示十六进制的枚举值是 HexNumber。因此,如果我们要将“AB”转换成整型,就应该这样写:int b = int.Parse(AB, System.Globalization.NumberStyles.HexNumber),最后得到的 b 的值是 171。

9. 日期型数据和长整型数据之间的转换

    为什么要将日期型数据转换为长整型数据呢?原因很多,但就我个人来说,经常将它用于数据库的日期存储。由于各种数据库对日期型的定义和处理是不一样的,各种语言对日期型数据的定义的处理也各不相同,因为,我宁愿将日期型数据转换成长整型再保存到数据库中。虽然也可以使用字符串来保存,但使用字符串也会涉及到许多问题,如区域等问题,而且,它需要比保存长整型数据更多的空间。
    日期型数据,在 C# 中的参与运算的时候,应该也是转换为长整型数据来运算的。它的长整型值是自 0001 年 1 月 1 日午夜 12:00 以来所经过时间以 100 毫微秒为间隔表示时的数字。这个数在 C# 的 DateTime 中被称为 Ticks(刻度)。DateTime 类型有一个名为 Ticks 的长整型只读属性,就保存着这个值。如此,要从一个 DataTime 型数据得到 long 型值就非常简单了,只需要读出 DataTime 对象的 Ticks 值即可,如:

    long longDate = DateTime.Now.Ticks;

    DateTime 的构造函数中也提供了相应的,从长整型数据构造 DateTime 型数据的函数:DateTime(long)。如:

    DateTime theDate = new DateTime(longDate);

    但这样对于很多 VB6 程序员来说,是给他们出了一道难题,因为 VB6 中的日期型数据内部是以 Double 型表示的,将其转换为长整型后得到的仅仅是日期,而没有时间。如何协调这两种日期类型呢?
     System.DateTime 提供了 double ToOADate() 和 static DateTime FromOADate(double) 两个函数来解决这个问题。前者将当前对象按原来的 double 值输出,后者则从一个 double 值获得一个 System.DateTime 对象。举例如下:

    private void TestDateTimeLong() {
        double doubleDate = DateTime.Now.ToOADate();
        DateTime theDate = DateTime.FromOADate(doubleDate);
        this.textBox1.Text = ;
        this.textBox1.AppendText(Double value of now: + doubleDate.ToString() +
);
        this.textBox1.AppendText(DateTime from double value: + theDate.ToString() +
);
    }

    运行结果:

    Double value of now: 37494.661541713
    DateTime from double value: 2002-8-26 15:52:37 

10. 格式化日期型数据

    编程的过程中,通常需要将日期型数据按照一定的格式输出,当然,输出结果肯定是字符串。为此,我们需要使用 System.DateTime 类的 ToString() 方法,并为其指定格式字符串。
    MSDN 中,System.Globalization.DateTimeFormatInfo 类的概述里对模式字符串有非常详细的说明,因此,这里我只对常用的一些格式进行说明,首先请看下表:

    d       月中的某一天。一位数的日期没有前导零。
    dd      月中的某一天。一位数的日期有一个前导零。
    ddd     周中某天的缩写名称,在 AbbreviatedDayNames 中定义。
    dddd    周中某天的完整名称,在 DayNames 中定义。
    M       月份数字。一位数的月份没有前导零。
    MM      月份数字。一位数的月份有一个前导零。
    MMM     月份的缩写名称,在 AbbreviatedMonthNames 中定义。
    MMMM    月份的完整名称,在 MonthNames 中定义。
    y       不包含纪元的年份。如果不包含纪元的年份小于 10,则显示不具有前导零的年份。
    yy      不包含纪元的年份。如果不包含纪元的年份小于 10,则显示具有前导零的年份。
    yyyy    包括纪元的四位数的年份。
    h       12 小时制的小时。一位数的小时数没有前导零。
    hh      12 小时制的小时。一位数的小时数有前导零。
    H       24 小时制的小时。一位数的小时数没有前导零。
    HH      24 小时制的小时。一位数的小时数有前导零。
    m       分钟。一位数的分钟数没有前导零。
    mm      分钟。一位数的分钟数有一个前导零。
    s       秒。一位数的秒数没有前导零。
    ss      秒。一位数的秒数有一个前导零。

    为了便于大家的理解,不妨试试下面的程序:

    private void TestDateTimeToString() {
        DateTime now = DateTime.Now;
        string format;
        this.textBox1.Text = ;
        format = yyyy-MM-dd HH:mm:ss;
        this.textBox1.AppendText(format + : + now.ToString(format) +
);
        format = yy年M日d日;
        this.textBox1.AppendText(format + : + now.ToString(format) +
);
    }

    这段程序将输出结果:

    yyyy-MM-dd HH:mm:ss: 2002-08-26 17:03:04
    yy年M日d日: 02年8日26日

    这时候,又出现一个问题,如果要输出的文本信息中包含格式字符怎么办?如

        format = year: yyyy, month: MM, day: dd;
        this.textBox1.AppendText(now.ToString(format) +
);

    将输出:

    2ear: 2002, 4on下5: 08, 26a2: 26

    这并不是我想要的结果,怎么办呢?有办法——

        format = year: yyyy, ‘month‘: MM, ‘day‘: dd;
        this.textBox1.AppendText(now.ToString(format) +
);

    看,这次运行结果对了:

    year: 2002, month: 08, day: 26

    可以看出,只需要使用单引号或者双引号将文本信息括起来就好。
    如果文本信息中包含双引号或者单引号又怎么办呢?这个问题,请读者们动动脑筋吧!

好消息啊!今天下午在Taobao上把CPU卖了。庆祝一下!是一位昭通的买家。

在确认打款以后我马上就把CPU通过全一快递(www.apex100.com)发出去了。本来打算通过大图快递来发的,只要五元的运费。但是大图不上门取货,没办法,和买家商量了一下。让他多出十元钱的运费,我出剩下的,然后让全一快递的来取货。但是全一快递的来了以后说,昭通没有他们的分公司,所以必须加五元的快递费,这样快递费就变成了20元!郁闷,5元就这样变成了20元……

已经好久没在网上卖东西了,上次卖MX400的显卡是很久以前的事了。现在在Taobao上卖东西还是方便了许多了。有即时聊天工具--淘宝旺旺,的确买家和卖家交流方便多了。不像原来在eachnet上只有拍下来以后才能用电话,邮件等进行交流。而且感觉在网上买东西的人多了很多。自从我上个礼拜六下午把卖CPU的消息贴出去。到目前卖出去为止,已经有将近4~5个人和我联系了。

就目前的形势看来,在网上做做倒买倒卖也是一个很不错的赚钱方式。买我CPU的这个人就是在昭通开电脑商店的,他在网上淘淘好东西,然后再拿出来卖。不错的赚钱方式~ 是不是我也想想找时间来倒买倒卖?呵呵

复制的概念
  
  复制是将一组数据从一个数据源拷贝到多个数据源的技术,是将一份数据发布到多个存储站点上的有效方式。使用复制技术,用户可以将一份数据发布到多台服务器上,从而使不同的服务器用户都可以在权限的许可的范围内共享这份数据。复制技术可以确保分布在不同地点的数据自动同步更新,从而保证数据的一致性。
  
  SQL复制的基本元素包括
  
  出版服务器、订阅服务器、分发服务器、出版物、文章
  
  SQL复制的工作原理
  
  SQL SERVER 主要采用出版物、订阅的方式来处理复制。源数据所在的服务器是出版服务器,负责发表数据。出版服务器把要发表的数据的所有改变情况的拷贝复制到分发服务器,分发服务器包含有一个分发数据库,可接收数据的所有改变,并保存这些改变,再把这些改变分发给订阅服务器
  
  SQL SERVER复制技术类型
  
  SQL SERVER提供了三种复制技术,分别是:
  
  1、快照复制(呆会我们就使用这个)
  2、事务复制
  3、合并复制
  
  只要把上面这些概念弄清楚了那么对复制也就有了一定的理解。接下来我们就一步一步来实现复制的步骤。
  
  第一先来配置出版服务器
  
  (1)选中指定[服务器]节点
  (2)从[工具]下拉菜单的[复制]子菜单中选择[发布、订阅服务器和分发]命令
  (3)系统弹出一个对话框点[下一步]然后看着提示一直操作到完成。
  (4)当完成了出版服务器的设置以后系统会为该服务器的树形结构中添加一个复制监视器。同时也生成一个分发数据库(distribution)
  
  第二创建出版物
  
  (1)选中指定的服务器
  (2)从[工具]菜单的[复制]子菜单中选择[创建和管理发布]命令。此时系统会弹出一个对话框
  (3)选择要创建出版物的数据库,然后单击[创建发布]
  (4)在[创建发布向导]的提示对话框中单击[下一步]系统就会弹出一个对话框。对话框上的内容是复制的三个类型。我们现在选第一个也就是默认的快照发布(其他两个大家可以去看看帮助)
  (5)单击[下一步]系统要求指定可以订阅该发布的数据库服务器类型,SQLSERVER允许在不同的数据库如 ORACLE或ACCESS之间进行数据复制。但是在这里我们选择运行"SQL SERVER 2000"的数据库服务器
  (6)单击[下一步]系统就弹出一个定义文章的对话框也就是选择要出版的表
  (7)然后[下一步]直到操作完成。当完成出版物的创建后创建出版物的数据库也就变成了一个共享数据库。
  
  第三设计订阅
  
  (1)选中指定的订阅服务器
  (2)从[工具]下拉菜单中选择[复制]子菜单的[请求订阅]
  (3)按照单击[下一步]操作直到系统会提示检查SQL SERVER代理服务的运行状态,执行复制操作的前提条件是SQL SERVER代理服务必须已经启动。
  (4)单击[完成]。完成订阅操作。
  
  完成上面的步骤其实复制也就是成功了。但是如何来知道复制是否成功了呢?这里可以通过这种方法来快速看是否成功。展开出版服务器下面的复制——发布内容——右键发布内容——属性——击活——状态然后点立即运行代理程序接着点代理程序属性击活调度把调度设置为每一天发生,每一分钟,在0:00:00和23:59:59之间。接下来就是判断复制是否成功了打开C:Program FilesMicrosoft SQL ServerMSSQLREPLDATAuncXIAOWANGZI_database_database下面看是不是有一些以时间做为文件名的文件夹差不多一分中就产生一个。要是你还不信的话就打开你的数据库看在订阅的服务器的指定订阅数据库下看是不是看到了你刚才所发布的表—

  一个手工同步的方案
  
  –定时同步服务器上的数据
  
  –例子:
  
  –测试环境,SQL Server2000,远程服务器名:xz,用户名为:sa,无密码,测试数据库:test
  
  –服务器上的表(查询分析器连接到服务器上创建)
  
  create table [user](id int primary key,number varchar(4),name varchar(10))
  go
  
  –以下在局域网(本机操作)
  
  –本机的表,state说明:null 表示新增记录,1 表示修改过的记录,0 表示无变化的记录
  
  if exists (select * from dbo.sysobjects where id = object_id(N‘[user]‘) and OBJECTPROPERTY(id, N‘IsUserTable‘) = 1)
  drop table [user]
  GO
  create table [user](id int identity(1,1),number varchar(4),name varchar(10),state bit)
  go
  
  –创建触发器,维护state字段的值
  
  create trigger t_state on [user]
  after update
  as
  update [user] set state=1
  from [user] a join inserted b on a.id=b.id
  where a.state is not null
  go
  
  –为了方便同步处理,创建链接服务器到要同步的服务器
  
  –这里的远程服务器名为:xz,用户名为:sa,无密码
  
  if exists(select 1 from master..sysservers where srvname=‘srv_lnk‘)
  exec sp_dropserver ‘srv_lnk‘,‘droplogins‘
  go
  exec sp_addlinkedserver ‘srv_lnk‘,‘‘,‘SQLOLEDB‘,‘xz‘
  exec sp_addlinkedsrvlogin ‘srv_lnk‘,‘false‘,null,‘sa‘
  go
  
  –创建同步处理的存储过程
  
  if exists (select * from dbo.sysobjects where id = object_id(N‘[dbo].[p_synchro]‘) and OBJECTPROPERTY(id, N‘IsProcedure‘) = 1)
  drop procedure [dbo].[p_synchro]
  GO
  create proc p_synchro
  as
  –set XACT_ABORT on
  
  –启动远程服务器的MSDTC服务
  
  –exec master..xp_cmdshell ‘isql /S"xz" /U"sa" /P"" /q"exec master..xp_cmdshell ‘‘net start msdtc‘‘,no_output"‘,no_output
  
  –启动本机的MSDTC服务
  
  –exec master..xp_cmdshell ‘net start msdtc‘,no_output
  
  –进行分布事务处理,如果表用标识列做主键,用下面的方法
  
  –BEGIN DISTRIBUTED TRANSACTION

  –同步删除的数据
  
  delete from srv_lnk.test.dbo.[user]
  where id not in(select id from [user])
  
  –同步新增的数据
  
  insert into srv_lnk.test.dbo.[user]
  select id,number,name from [user] where state is null
  
  –同步修改的数据
  
  update srv_lnk.test.dbo.[user] set
  number=b.number,name=b.name
  from srv_lnk.test.dbo.[user] a
  join [user] b on a.id=b.id
  where b.state=1
  
  –同步后更新本机的标志
  
  update [user] set state=0 where isnull(state,1)=1
  –COMMIT TRAN
  go
  
  –创建作业,定时执行数据同步的存储过程
  
  if exists(SELECT 1 from msdb..sysjobs where name=‘数据处理‘)
  EXECUTE msdb.dbo.sp_delete_job @job_name=‘数据处理‘
  exec msdb..sp_add_job @job_name=‘数据处理‘
  
  –创建作业步骤
  
  declare @sql varchar(800),@dbname varchar(250)
  select @sql=‘exec p_synchro‘ –数据处理的命令
  ,@dbname=db_name() –执行数据处理的数据库名
  exec msdb..sp_add_jobstep @job_name=‘数据处理‘,
  @step_name = ‘数据同步‘,
  @subsystem = ‘TSQL‘,
  @database_name=@dbname,
  @command = @sql,
  @retry_attempts = 5, –重试次数
  @retry_interval = 5 –重试间隔
  
  –创建调度
  
  EXEC msdb..sp_add_jobschedule @job_name = ‘数据处理‘,
  @name = ‘时间安排‘,
  @freq_type = 4, –每天
  @freq_interval = 1, –每天执行一次
  @active_start_time = 00000 –0点执行
  go

Vista和Office2007才发布,就遭遇破解了。呵呵~

摘自cnbeta:
Windows Vista的破解(名为"Vista BillGates")实际上并不算是真正的破解,它最早应该起源于我们的站友wbpluto,通过替换系统文件的方法让授权方式改变,使测试版本的授权能够用在正式版本上,它可以通过网络激活,但无法通过系统自身验证,不过它的确解除了使用限制.

Vista Key: YFKBB-PQJJV-G996G-VWGXY-2V3X8

Office2007 Key: DBXYD-TF477-46YM4-W74MH-6YDQ8

Vista (English Edition):
ed2k://|file|Microsoft.Windows.Vista.Final-BillGates.EN.[sharethefiles.com].iso|2678614016|88332DA3A5230D8B8B778C99B75939AE|/

Office2007 中文企业版:
ed2k://|file|office2007pro.chs.img|694059008|CFAE350F8A9028110D12D61D9AEC1315|h=NMYWTLZO2LUNCJIJVGCTA4AEVBUED2PC|/

附件是Office2007 English Enterprise版的BT种子

附件:microsoft_office_2007_enterprise_english_2114566.708.zip(13916 Byte)

GPS爱好者的好消息!灵图天行者5已被成功破解!

LT5的eMule下载链接:
ed2k://|file|%E7%81%B5%E5%9B%BE%E5%A4%A9%E8%A1%8C%E8%80%855.0.28R.rar|456115496|39B57A2C1ADA7253A0670AE01B70CAB0|h=S46RMJJWRB2URERH3JVJLFWUW4EGOTMU|/

小胖熊上的帖子:

硬件全面XX,不会有任何死机情况的发生,已经路试,一点问题也没有,直接硬件级别底层XX!
附件中一个是模拟机一个是正版ID一个是LT5最新的BT下载文件
哈哈
强烈感谢wh_cxh对我们的突出贡献,只给下载100次,顶的才下哦

1、下载:ftp://op_down:[email protected]:12121/ 的“灵图天行者5.0.28R PDA版”。下载模拟器:DevEmu.rar。见 http://www.sosaw.com/dispbbs.asp?boardID=43&ID=68368&page=1 的12楼。
2、安装:先装在电脑上,不要选同步安装,这样快些。可以选择使用PDA品牌,如Dopod、Hp……。
3、用读卡器把文件考到PDA的SD卡根目录下:文件夹“2577”、“ConfigFile”、“DB”、“StartUp“和“天行者安装. exe”。DB文件夹下是地图文件,测试可以只拷贝你所在省市的地图。插上卡后,LT会自动启动安装,并在桌面建立一个快捷图标。此时,不要启动LT5!
4、激活:启动模拟器DevEmu.exe,若正常则显示:模拟成功。然后启动LT5,会显示输入XXX,然后输入:GVY3H-C2T93-QR3X8 -7349M-9K84D,确定后显示安装码:MBGVB-KB2PY-HBBTB-K3J4T,再输入激活码:3B64-6TFT-DB26- BDRP。进入程序,搞定!!!
5、根据需要,调整Startup目录下SMG_SysConfig.txt设置文件中的路径。

附件:devemu.zip(11047 Byte)

  介绍四部根据Tom Clancy写的小说拍成的电影。必看啊!

  汤姆·克兰西(1947–)、美国军事作家,当今世界最畅销的反恐惊悚小说大师。他的小说布局广大,气势磅礴,对于军事武器、恐怖行动、国家情报体系、全球战略关系,描述逼真详实,在全球拥有广大读者群;代表作《猎杀“红十月”号》、《爱国者游戏》、《燃眉追击》和《惊天核网》先后由好莱坞搬上荧幕而轰动世界影坛。此外,他也积极涉足网络游戏开发,以《彩虹六号》、《幽灵行动》和《分裂细胞》等系列制作声名远播。

1. 《猎杀红色十月》http://lib.verycd.com/2004/12/29/0000032848.html

剧情简介:
  本片根据畅销名著改编,描述苏联核子潜艇“红色十月号"航道经常偏轨,引发美国中情局的优虑,认为它要攻击美国,但情报员杰克森却认为它欲归降美国,到底真相如何?本片为两大巨星史恩康纳莱、亚力鲍德温主演的强力动作片。

  1984年11月,苏联正处于戈尔巴乔夫上台前夕,也是美、苏两个超级大国明争暗斗的冷战高潮时期。
  苏联研制了一艘新型核潜艇“红十月号”,并派老练的雷米斯负责该艇的首次试航演习。此时,美国中央情报局也获取了有关“红十月”号的情报。
  途中,艇长雷米斯杀死了发现他隐私的专横政委并命令潜艇改变航向。他向全体官兵声称此举是要利用该艇先进的无声推进系统去通过美国海军的监视网并纵情游览美国的海岸线。美军潜艇“达拉斯号”无法追踪“红十月”,这使美国十分惊恐,以为这是一场偷袭。在秘密会议上,中情局情报员黎博士大胆地认为雷米斯率舰改变航向是有意变节而投奔美国。于是,中情局给黎三天时间,要他在此间争取与雷米斯联系上,否则就将歼灭“红十月”号。
  “红十月”核潜艇上,雷米斯召开军佐会议,表明打算变节。这时,苏方也认为“红十月”已投降美国而派出了大批舰艇开始搜寻着“红十月”,而美军的舰艇也时时探测发现了该艇。宁为玉碎的苏方向“红十月”发射了鱼雷弹,而此刻,“红十月”内又出现了潜伏奸细的破坏。
  黎冒着危险来到美方潜艇“达拉斯”号里,在获知雷米斯此行的目的是向美国发射飞弹的所谓情报后,坚持认为这是苏方想借用美军之手来消灭“红十月”的阴谋。在用信号灯进行了短暂的联系后,“红十月”号突然南逃。不久,因换气系统出了故障而浮出水面的“红十月”被美军驱逐舰追上。美军发射并自我引爆了鱼雷并假称击沉了“红十月”试图来欺骗苏方。其后,美方潜艇派小艇载着黎等人进入“红十月”号与雷米斯谈判,雷米斯要求美国的庇护。
  苏方再次向“红十月”发射鱼雷,雷米斯命令潜艇迎着鱼雷驶去而使鱼雷因距离过近而难以引爆。这时,奸细又在进行破坏,在又一枚鱼雷来临之前,黎终于发现并击毙了潜伏的奸细。老道的雷米斯引诱苏方鱼雷绕道击沉了自己的潜艇。最终,“红色十月”号驶入了美国的港湾……

2. 《爱国者游戏》 http://lib.verycd.com/2005/06/10/0000053601.html

简介:
  本片是改编自美国政治惊悚小说畅销作家汤姆克兰西(Tom Clancy)的同名畅销小说,亦是卖座强片「 猎杀红色十月」的续集电影;讲述的是前中央情报局分析师杰克瑞恩(哈里逊福特)带着妻女前往英国渡假,却意外卷入恐怖份子的攻击行动中,见义勇为的杰克解救了皇室成员,并射杀恐怖份子主脑之弟,因而一举成为英国皇室的英雄–以及恐怖份子最新的头号攻击目标;当无辜的妻女遭人追杀,稚女(苏拉柏区)不幸重伤住院,杰克决定不惜一切要恐怖份子付出代价;回到老东家怀抱的杰克投入这场只能赢不能输的间谍游戏中,利用他善于分析的头脑,以及中情局的卫星尖端科技,一举直捣恐怖份子的大本营!
  美国政治惊悚小说畅销作家汤姆克兰西以杰克瑞恩这个角色写了「猎杀红色十月」、「爱国者游戏」、「燃眉追击」、「恐惧的总和」四本小说,在亚历鲍德温辞演后,哈里逊福特以他成熟的魅力赋予角色另一种味道。
  这部片以爱尔兰的恐怖份子为题,反映出冷战结束后,好莱坞正在找寻新的「假想敌」,此次则由爱尔兰的恐怖份子「得标」,这也可以看出大美国主义的心态作祟。而剧情、配乐所营造出来的紧张悬疑的气氛,都让这部片具有商业与娱乐价值。

3. 《燃眉追击》 http://lib.verycd.com/2006/01/22/0000086159.html

简介:
  改编自汤姆.克兰西的畅销小说,是《爱国者游戏》的续集。哈里森.福特依旧饰演美国中情局乾员杰克.雷恩,这一次他卷入了哥伦比亚的贩毒战争之中,因为美国总统的友人遭毒贩谋杀,雷恩奉命追查真相。但另一方面总统又派了秘密的突击小组对付毒贩集团,使雷恩在状况不明、敌友不分的情况下陷入重重危机之中。导演菲利普.诺伊斯的叙事手法简练,将后冷战时代复杂的国际局势和政治权谋的诡异多变交代得很清楚,同时也兼顾了动作场面紧张刺激的娱乐性,堪称是成功的政治惊险片,但观众欣赏本片时非得聚精会神不可,要不然难以了解其中的微言大义。

4. 《所有恐惧的集合》 http://lib.verycd.com/2004/02/16/0000005229.html

简介:
  一伙以欧洲为基地的新纳粹恐怖分子从前苏联搞到了一枚威力强大的核弹,并秘密计划把它偷运到美国,趁着某个盛大集会之机,将其在超级碗体育场内引爆,从而制造一起骇人听闻的恐怖袭击事件。当然,更恐怖的阴谋还在后面,恐怖分子们还准备将这次袭击嫁祸给俄罗斯,妄图以此点燃又一次世界大战的导火索。
  年轻乾练的CIA情报分析专家杰克·雷恩及时洞察到这个惊天阴谋,但是在充满官僚气息的政府里,没人愿意相信这个不到30岁年轻分析员,危急之中,雷恩得到了情报局里睿智老道的分析顾问比尔·卡伯特(摩根·弗里曼)的帮助,一老一少通力合作,他们必须要抢在这帮丧心病狂的恐怖分子动手之前,拦截核掸,阻止这个毁灭性悲剧的发生……

 

  对于色友来说,摄影就是他们的生命。古人梅妻鹤子,而今的色友们也不让古人专美于前,他们给自己的镜头都取上了迷人或者诙谐的昵称,各家的镜头的昵称各不相同,但都独具特色,咱们来谈谈吧。

镜头分类:

  狗头----——大家都知道
  牛头----——不用我说了
  G头----——M家的牛头,N家的太监头(功能有所省略)
  L头----——C家的牛头
  *头(星头)—-P家的牛头

1.人性化称谓(基本上都跟颜色有关)

  小白--------Canon EF 70-200/2.8 L USM
  爱死小白------Canon EF 70-200/2.8 L (IS) USM
  小小白-------Canon EF 70-200/4 L USM
  大白--------Canon EF 100-400/4.5-5.6 L(IS)USM
  老黑--------Canon EF 80-200/2.8L

  小胖--------Nikkor AF-S VR 200/2 G[IF] ED

  小黑--------Sigma 70-200/2.8 EX HSM
  大黑--------Sigma 100-300/4 APO EX IF HSM
  大大黑-------Sigma 300-800/5.6 EX IF HSM

  大G--------Minolta AF 80-200/2.8 APO G
  小G--------Minolta AF 70-200/2.8 APO G(D) SSM

  小金--------Pentax SMC FA* 80-200/2.8
  小小金-------Pentax SMC FA* 28-70/2.8
  大金--------Pentax SMC FA* 250-600/5.6

2.现代武器型

  小钢炮----Nikkor AF 80-200/2.8 ED
  大钢炮----Nikkor AF-S 80-200/2.8
  小竹炮----Nikkor AF-S VR 70-200/2.8G IF-ED

3.冷兵器型(七种武器!!!)

  长生剑----Leica R Telyt 180mm/3.4 APO
  孔雀翎----Olumpus zuiko 90mm/2.0 macro
  碧玉刀----Nikkor AF 28mm/1.4 D(百变妖)
  多情环----Minolta 135mm/2.8 STF
  离别钩----Pentax SMC A* 200/4 Macro ED
  霸王枪----Canon EF 400mm/2.8 L U IS
  拳头-----Carl Zeiss C/Y 85mm/1.2

4.家用器具型(恶心不恶心就不提了,但是镜头都是好玩意)

  小痰盂----Canon EF 50/F1.8(那50/1.2不该叫马桶?)
  塑料痰盂---Canon EF 50/F1.8 II
  绿豆-----Canon EF 70-300mm IS DO(家用食品,先归类在此)

5.不太像外号型(一看就知道是镜头)

  金广角----Nikkor 17-35/2.8 ED
  银广角----Nikkor 18-35/3.5-4.5 ED
  钻石广角---Nikkor 20-35/2.8 D

6.外语型(老外们起的外号)

  Magic Drainpipe---Canon EF80-200L
  Bigma--------Sigma 50-500
  Sigmonster------Sigma 300-800
  Nifty Fifty----–50/1.4
  Thrifty Fifty---–50/1.8

7.珠光宝气型(有钱才好玩)

  八枚玉-----Leica 35/2
  七枚玉-----Leica 35/1.4

8.高贵型(外观精致华贵,价格高不可攀)

  三公主-----Pentax 三只限量版定焦镜头:
          Pentax SMC FA 31/1.8 Limited
          Pentax SMC FA 43/1.9 Limited
          Pentax SMC FA 77/1.8 Limited

    大部分的个人网站在一开始或许只是跟几十人上百人共享的一个虚拟主机空间,然后随着内容的增加和访问量的增长,虚拟主机的带宽、空间已经不能满足需求,站长就得开始考虑为网站购置一台独立的服务器,使用100M共享甚至是10M独享带宽;而当网站继续发展,访问的用户也已经遍布大江南北,站长又得考虑电信网通的互通问题,在南方和北方各放置一台服务器作为镜像站点,或是采用双线接入;当这个网站访问量更大时,一味的增加带宽和设置镜像站点无疑会使网站运营成本剧增,加上单个服务器本身也有性能和线程的瓶颈,在并发访问量较大并且集中在一台服务器的时候,“Server too busy”就出现了,而这时站长应该采用什么方式使得网站在高访问量的时候仍然拥有较好的访问效果呢?

    这就牵涉到负载均衡的话题。

    我们之前讨论过CDN,其实CDN除了加速之外,也具有分流的效果,因此在负载均衡领域也有不少应用,其实基本上缓存(Cache)+镜像技术都有分流作用,但是如何分流还是需要一个负载均衡设备进行引导,所以,我们今天专门讨论负载均衡技术。

关于负载均衡服务

  负载均衡服务能够平衡服务器群中的所有的服务器和应用之间的通信负载,根据实时响应时间进行判断,将任务交由负载最轻的服务器来处理,以实现真正的智能通信管理和最佳的服务器群性能。负载均衡技术控制第四层到第七层的应用/内容,从而对不同类型的客户和应用实现了优先级划分和差别服务,使用第七层智能会话恢复技术,同时可以检测出HTTP 400,500和600系列的错误。它透明地将交易重新定向到另一台服务器,从而使系统能够完成该交易。服务器故障切换和多重冗余特性可以让通信绕过故障点,从而使网站始终保持运行和可访问性。

实现负载均衡的方法

    关于实现负载均衡的方法,网上也有不少相关讨论,以下做一些引用:

    基于特定服务器软件的负载均衡

很多网络协议都支持“重定向”功能,例如在HTTP协议中支持Location指令,接收到这个指令的浏览器将自动重定向到Location指明的另一个URL上。由于发送Location指令比起执行服务请求,对Web服务器的负载要小的多,因此可以根据这个功能来设计一种负载均衡的服务器。

       任何时候Web服务器认为自己负载较大的时候,它就不再直接发送回浏览器请求的网页,而是送回一个Location指令,让浏览器去服务器集群中的其他服务器上获得所需要的网页。

在这种方式下,服务器本身必须支持这种功能,然而具体实现起来却有很多困难,例如一台服务器如何能保证它重定向过的服务器是比较空闲的,并且不会再次发送Location指令,Location指令和浏览器都没有这方面的支持能力,这样很容易在浏览器上形成一种死循环。

      因此这种方式实际应用当中并不多见,使用这种方式实现的服务器集群软件也较少。有些特定情况下可以使用CGI(包括使用FastCGI或mod_perl扩展来改善性能)来模拟这种方式去分担负载,而Web服务器仍然保持简洁、高效的特性,此时避免Location循环的任务将由用户的CGI程序来承担。

    基于DNS的负载均衡

    由于基于服务器软件的负载均衡需要改动软件,因此常常是得不偿失,负载均衡最好是在服务器软件之外来完成,这样才能利用现有服务器软件的种种优势。最早的负载均衡技术是通过DNS服务中的随机名字解析来实现的,在DNS服务器中,可以为多个不同的地址配置同一个名字,而最终查询这个名字的客户机将在解析这个名字时得到其中的一个地址。因此,对于同一个名字,不同的客户机会得到不同的地址,他们也就访问不同地址上的Web服务器,从而达到负载均衡的目的。

    例如如果希望使用三个Web服务器来回应对www.ghq.net的HTTP请求,就可以设置该域的DNS服务器中关于该域的数据包括有与下面例子类似的结果:

www1 IN A 192.168.1.1

www2 IN A 192.168.1.2

www3 IN A 192.168.1.3

www IN CNAME www1

www IN CNAME www2

www IN CNAME www3

    此后外部的客户机就可能随机的得到对应www的不同地址,那么随后的HTTP请求也就发送给不同地址了。

    DNS负载均衡的优点是简单、易行,并且服务器可以位于互联网的任意位置上,当前使用在包括Yahoo在内的Web站点上。然而它也存在不少缺点,一个缺点是为了保证DNS数据及时更新,一般都要将 DNS的刷新时间设置的较小,但太小就会造成太大的额外网络流量,并且更改了DNS数据之后也不能立即生效;第二点是DNS负载均衡无法得知服务器之间的差异,它不能做到为性能较好的服务器多分配请求,也不能了解到服务器的当前状态,甚至会出现客户请求集中在某一台服务器上的偶然情况。

    反向代理负载均衡

    使用代理服务器可以将请求转发给内部的Web服务器,使用这种加速模式显然可以提升静态网页的访问速度。因此也可以考虑使用这种技术,让代理服务器将请求均匀转发给多台内部Web服务器之一上,从而达到负载均衡的目的。这种代理方式与普通的代理方式有所不同,标准代理方式是客户使用代理访问多个外部Web服务器,而这种代理方式是多个客户使用它访问内部Web服务器,因此也被称为反向代理模式。

    实现这个反向代理能力并不能算是一个特别复杂的任务,但是在负载均衡中要求特别高的效率,这样实现起来就不是十分简单的了。每针对一次代理,代理服务器就必须打开两个连接,一个为对外的连接,一个为对内的连接,因此对于连接请求数量非常大的时候,代理服务器的负载也就非常之大了,在最后反向代理服务器会成为服务的瓶颈。

    例如,使用Apache的mod_rproxy模块来实现负载均衡功能时,提供的并发连接数量受Apache本身的并发连接数量的限制。一般来讲,可以使用它来对连接数量不是特别大,但每次连接都需要消耗大量处理资源的站点进行负载均衡,例如搜寻。

    使用反向代理的好处是,可以将负载均衡和代理服务器的高速缓存技术结合在一起,提供有益的性能,具备额外的安全性,外部客户不能直接访问真实的服务器。并且实现起来可以实现较好的负载均衡策略,将负载可以非常均衡的分给内部服务器,不会出现负载集中到某个服务器的偶然现象。

    基于NAT的负载均衡技术

    网络地址转换为在内部地址和外部地址之间进行转换,以便具备内部地址的计算机能访问外部网络,而当外部网络中的计算机访问地址转换网关拥有的某一外部地址时,地址转换网关能将其转发到一个映射的内部地址上。因此如果地址转换网关能将每个连接均匀转换为不同的内部服务器地址,此后外部网络中的计算机就各自与自己转换得到的地址上服务器进行通信,从而达到负载分担的目的。

    地址转换可以通过软件方式来实现,也可以通过硬件方式来实现。使用硬件方式进行操作一般称为交换,而当交换必须保存TCP连接信息的时候,这种针对OSI网络层的操作就被称为第四层交换。支持负载均衡的网络地址转换为第四层交换机的一种重要功能,由于它基于定制的硬件芯片,因此其性能非常优秀,很多交换机声称具备400MB-800MB的第四层交换能力。

    使用软件方式来实现基于网络地址转换的负载均衡则要实际的多,除了一些厂商提供的解决方法之外,更有效的方法是使用免费的自由软件来完成这项任务。其中包括Linux Virtual Server Project中的NAT实现方式,或者本文作者在FreeBSD下对natd的修订版本。一般来讲,使用这种软件方式来实现地址转换,中心负载均衡器存在带宽限制,在100MB的快速以太网条件下,能得到最快达80MB的带宽,然而在实际应用中,可能只有40MB-60MB的可用带宽。

大类 小类
本地负载均衡
(Server Load Balancing)
共享负载均衡
 (Shared Load Balancing Service)
独享负载均衡服务
 (Dedicated Load Balancing Service)
异地负载均衡服务
 (Website Load Balancing Service)
异地负载均衡服务
 (Website Load Balancing Service)

    互联网数据中心提供的专业负载均衡服务,可以针对用户的服务器做本地负载均衡(Server Load Balancing),负载均衡设备采用强劲有效的负载均衡算法,按照实际响应时间,在性能不同的服务器之间进行负载的智能分配,充分利用服务器群中的每一台服务器,保护现有投资,既保证性能一般的服务器不成为系统的瓶颈,也保证性能高的服务器资源得到充分的利用。大部分的电信IDC互联网数据中心都建立了共享的负载均衡设施(Shared Load Balancing),该机房的购买此项增值服务的所有托管客户的服务器都可以共享机房购置的负载均衡设施,针对一些高端用户,一些数据中心还推出了独享负载均衡服务 (Dedicated Load Balancing Service),该服务主要是为了避免共享用户争用负载均衡设备资源的可能,而且会为个别大型客户单独建立自己的负载均衡设施,以保证达到良好的效果。

  共享负载均衡服务 (Shared Load Balancing Service) 托管客户可以与其它客户共同分享IDC的共享负载均衡设施(Shared Load Balancing),以低廉的代价,获得服务器的负载均衡服务。

  独享负载均衡服务 (Dedicated Load Balancing Service) IDC也可以为托管客户提供独享的负载均衡设施,在确保数据安全的情况下,达到更好的负载均衡效果。

    但是,只对本地服务器(也就是指本机房服务器)进行负载均衡是不够的,大部分需要负载均衡服务的站点并发访问量都较大,这些站点多数都有异地镜像服务器,因此一些更加专业的 IDC 机房采用的负载均衡设备还可以穿透网络路由,进行异地镜像站点之间的负载均衡,这类负载均衡就称为异地负载均衡(Website Load Balancing)。

  异地负载均衡服务 (Website Load Balancing Service) IDC的负载均衡服务,可以穿透网络路由,进行异地镜像站点之间的负载均衡。

    负载均衡服务的更多服务对象

    负载均衡服务并非只针对托管服务器或者独立服务器,上面提到的几种也负载均衡服务可以对用户的防火墙(Firewall Load Balancing)及虚拟主机(Virtual Hosting Load Balancing)进行负载均衡,其效果和基本原理也是通用的。

IDC提供的负载均衡服务

  IDC提供的负载均衡服务有