当前位置:Linux教程 - Linux资讯 - 高性能、多线程的高速Web代理服务器--OOPS!

高性能、多线程的高速Web代理服务器--OOPS!

  “代理”是指作为替代者代表别人执行任务的人。正如您可能猜到的一样,代理服务器是代表其客户机执行特定任务的程序,如果有必要,这种任务通常可以由代理本身完成。在 Web 世界中,Web 代理服务器是充当信使的程序,它从诸如 Netscape、Mozilla、Internet EXPlorer 或 Konqueror 等的 Web 浏览器接收 HTTP 请求。然后,Web 代理从 Web 获取适当的数据,并将其传递给客户机。通过使用 Web 代理,Web 客户机可以不必建立与本地网之外任何机器的实际连接而访问因特网;Web 代理处理所有外部的 Web 通信。Web 代理有很多用途。最常用的一个是为处于防火墙之后的局域网提供因特网访问。代理可以绕过防火墙,代表局域网内部的 Web 客户机建立因特网里连接。因此,可以将局域网与因特网完全隔断,而代理则充当“桥梁”并允许 Web 浏览继续进行。另外,Web 代理还可以在同意提供服务之前自己验证局域网用户(通常用用户名和密码认证)。几乎可以将每一种现代浏览器配置成使用 Web 代理,而不是直接连接到因特网。通常,配置需要指定代理服务器的 IP 地址和端口。然后,Web 浏览器将其请求转发到这个特定的主机,而不是试图自己与远程站点联系。 除了提供基本的 HTTP 代理功能之外,很多 Web 代理还维护一个最近访问过的 Web 页面和图像的本地高速缓存。当请求的页面或图像已经在代理的高速缓存中时,代理将高速缓存的副本传递给客户机,而不再次从网站直接下载。这样做有两方面好处:首先,它通常会提高局域网装入 Web 页面的速度。其次,通过减少冗余页面和图像下载,可以减少 Web 浏览的带宽使用率。虽然大多数 Web 浏览器自己都有内置的高速缓存,但一般都很小 -- 通常不超过 10 MB。相比之下,高速缓存 Web 代理允许更大的基于磁盘的高速缓存 -- 通常有几百 MB,并且常常可达到几 GB。并且与简单的浏览器代理不同的是,高速缓存 Web 代理将为整个用户组提高访问 Web 的性能并减少网络带宽需求;这是相对弱小的浏览器高速缓存无法办到的。 好了,我们已经讨论了 Web 代理和高速缓存 Web 代理,但什么是透明 Web 代理呢?很简单,它是以特殊方式配置的 Web 代理,在这种方式中,Web 客户机(浏览器)甚至不知道它们的 HTTP 请求是通过代理进行的。在它们看来,它们正在直接与实际的远程站点通信。透明代理特别有用,因为一经正确配置,代理将“立即工作”,并且无需配置 Web 浏览器。不仅如此,如果正确配置了透明 Web 代理,想绕过它要困难得多。 ---------------------------------------------------- 目前,最流行的开放源码、高性能 Web 代理高速缓存是 Squid,可从http://www.squid-cache.org ] [url=www.squid-cache.org]http://www.squid-cache.org[/url] [/url] 获得。Squid 是一个不错的 Web 高速缓存,但我个人更喜欢不太出名的 oops。 oops 是质量极高、快速并且开放源码的高速缓存代理服务器,可从http://zipper.paco.net/~igor/oops.eng/ ] [url=zipper.paco.net/~igor/oops.eng/]http://zipper.paco.net/~igor/oops.eng/[/url] [/url] 获得。 我喜欢 oops 是因为它的源码是开放的,并且设计得很好。oops 是多线程的,这可以改进单处理器机器的性能,并且可以极大地提高多处理器系统的性能。另外,oops 可以在后台执行耗时的任务(例如进行检查高速缓存完整性的检查),以便不影响其 Web 代理功能,这是 Squid 无法做到的。 oops 还支持一些高级特性,包括带宽控制、连接限制、基于规则表达式的重定向以及其它一些吸引人的功能。我们来讨论一个Linux下基于oops和iptables的透明代理的案例。 如果您的 Linux 机器为局域网提供因特网访问(作为网关),则透明配置特别有用,因为那时,局域网上的所有 Web 浏览器将自动使用 oops 作为代理。所要做的全部工作就是把所有的局域网机器配置成将那台 Linux 机器作为缺省网关。如果您的局域网不是这样配置的,您仍可以使局域网客户机使用 oops,但是可能需要配置每一个 Web 浏览器,使其使用在 Linux 机器端口 3128 上运行的代理服务器。您可以使用这种方法,也可以使用我稍后将提到的另一种方法。 要安装 oops,请直接到 http://zipper.paco.net/~igor/oops.eng/,单击下载链接,然后下载最新的稳定版(当前是oops-1.5.22.tar.gz 文件)。下载之后,输入以下命令将 tar 文件从打包文件中解开:
[1] [2] [3] [4] 下一页 

# tar xzvf oops-1.5.22.tar.gz 无论何时运行网络服务,最好尽可能将该服务配置成以非“root”身份运行。当网络服务以非 root 用户运行并发现一处安全性漏洞时,可能会因为非 root 帐户的特权较低而防止安全性漏洞成为主要威胁。 当然,oops 是一个设计出色、考虑到安全性问题的程序;然而,oops 的创建者还是决定添加此特性作为额外的安全性措施。它的工作原理是:oops 以 root 权限启动,但它机会立即“降低”到非特权帐户。 在我的系统上,有一个 oops 所使用的特殊 "squid"(非登录)用户和组。Oops 在这个 UID 下运行,从而提供一个额外的安全层。另外,我还用特殊许可权设置了 oops /var/log 和 /var/run 目录,以便只有 root 和 "squid" 组成员可以读取其中的文件。我们将大致看一下如何这样做,但目前,您需要确定 oops 将使用哪个 UID。 oops 应该使用非登录帐户的 UID;几个不错的选择是 "daemon"、"squid" 或 "oops"。如果有必要,用同一名称创建一个组(确保 UDI 的缺省组就是该组),然后,您就可以开始了。从现在起,每当我提到 "squid" 用户或组时,您都应该用自己选择使用的组名来替换它。我将用红色突出显示 squid,以便给您以提示。 好了;现在该编译了。首先,进入 oops 源目录: # cd oops-1.5.22 然后,输入带以下选项的配置脚本: # ./configure --prefix=/usr --libdir=/usr/lib/oops --enable-oops-user=squid --sysconfdir=/etc/oops --sbindir=/usr/sbin --localstatedir=/var/run/oops 配置完成之后,输入: # make 源代码将开始编译。 现在,可以安装 oops 了。因为 make 文件是对 Solaris 而不是 Linux 系统准备的,所以这部分有一点棘手。继续进行并输入: # make install "make install" 进程将正确设置大多数事物,但现在,还需要进行一些其它调整。下面是您需要作的: # rm -rf /usr/oops # rm -rf /usr/lib/oops/modules 这将除去 "make install" 所创建的两个无关目录。 现在,我们需要正确配置 /etc/oops、/var/log/oops、/var/lib/oops 和 /var/run/oops 目录。只有 root、squid 和 squid 组成员能够读取 /etc/oops、/var/log/oops 和 /var/lib/oops 的内容;并且只有 root 和 squid 用户能够写入这些目录: # chmod o-rwx g=wxs /etc/oops # chown -R squid.squid /etc/oops # install -d -o squid -g squid -m0750 /var/log/oops # chmod g+s /var/log/oops # install -d -o squid -g squid -m0750 /var/lib/oops/storage # install -d -o squid -g squid -m0750 /var/lib/oops/db # install -d -o squid -g squid -m0755 /var/run/oops # chmod g+s /var/run/oops 现在,所有文件和目录都已就位,但在可以启动 oops 之前还有一步要完成:需要为您的站点定制 oops.cfg 配置文件。oops.cfg 可能会令新用户困惑,因此,我创建了一个最小的 oops.cfg 文件,您应该将它复制到 /etc/oops 中。但首先,将原始 oops.cfg 备份成 oops.cfg.eg。原始文件包含很多有关 oops 更高级特性的有用注释,因此应该将其保留,供以后参考。 现在,我将引导您浏览 oops.cfg 文件,并解释该文件的各部分如何工作,以及为使 oops 在您的环境中工作需要作哪些更改。我们首先看一下 oops.cfg 的前三行: nameserver 192.168.1.1 http_port 3128 userid squid 在第一行,我们指定了 oops 将用来执行 DNS 查询的名称服务器。如果需要的话,也可以添加多个名称服务器行;oops 将循环查询每个名称服务器。在您的 oops.cfg 中指定名称服务器很重要,因为这样做将允许 oops 执行它自己的多线程直接 DNS 查询。如果省略nameserver 参数,则 oops 将不得不使用 gethostbyname_r() 函数来执行 DNS 查询。这不是理想的解决方案,因为 gethostbyname_r() 一次只会处理一个 DNS 查询,这就在象 oops 这样高度多线程化的程序中形成一个瓶颈。在 oops.cfg 中指定名称服务器的唯一缺点是:oops 在名称解析过程中不会参考您的 /etc/hosts 文件,而是执行一个简单的 DNS 查询。大多数情况下,这种解决方案都会很好地工作。在第二行,我们设置了 oops 将要侦听的端口:3128 是 Web 代理的标准端口。并且,我们在第三行指定了 oops 将要使用的用户标识。请根据需要修改这行。 接下来,我们到达日志行: logfile /var/log/oops/oops.log { 3 1m }
上一页 [1] [2] [3] [4] 下一页 

Accesslog /var/log/oops/oops.access { 3 1m } statistics /var/log/oops/oops.stats pidfile /var/run/oops/oops.pid 这几行无需更改,但有必要理解其工作原理。第一行配置 oops,使其将常规日志存储在 /var/log/oops/oops.log,并且当该文件超过一兆 ("1m") 时自动翻转 (rotate) 日志。oops 使用 3 个日志进行翻转的机制。下一行指定访问日志的位置,该日志将记录所有 HTTP 请求;这个文件被配置成以与 oops.log 同样的方式自动翻转。接下来,我们指定 oops.stats 的位置。与其它日志文件不同,oops.stats 不会被 oops 定期覆盖(而是象普通日志那样在日志尾部附加内容),因此无需自动翻转。oops.stats 包含一些有用的统计信息,例如运行时间、自 oops 其启动以来的 HTTP 请求数量等。最后,我们指定 pidfile 的位置,该文件将包含 oops 主进程的数字进程标识。为保持与 FHS 2.1 (http://www.pathname.com/fhs/) 一致,将该文件放在 /var/run/oops 中。 接下来,我们设置几个高速缓存调整参数: mem_max 128m lo_mark 80m 前两个参数是 mem_mark 和 lo_mark,它们调整 oops 的内存高速缓存行为。mem-mark 设置内存高速缓存大小的硬性最大限制;如果 oops 的内存高速缓存大小超过 128 MB,则 oops 将开始丢弃对象。显然,用户应该努力避免这种行为的发生,而这正是 lo_mark 的用处所在。当 oops 的内存高速缓存达到 lo_mark 时(本例为 80MB),oops 将开始把内存中的对象移至磁盘高速缓存。 接下来,我们设置两个磁盘高速缓存调整参数:\ disk-low-free 3 disk-ok-free 5 disk-low-free 告诉 oops:当使用了 97% 的磁盘高速缓存时,开始清理它,disk-ok-free 告诉 oops:继续清理磁盘高速缓存,直到至少有总缓存的 5% 可用于新对象为止。我们还没有实际配置 oops 磁盘高速缓存的大小和位置,但将在此文件的稍后部分配置。 接下来,我们设置一些杂项设置: force_http11 force_completion 85 maxresident 1m insert_x_forwarded_for no insert_via no always_check_freshness "force_http11" 告诉 oops:即使 Web 客户机使用 HTTP/1.0,在连接到因特网站点时也使用 HTTP/1.1。"force_completion" 告诉 oops:如果已经至少接收了文件的 85%,那么,即使用户异常中止下载,也要继续下载该对象。该设置的含义是:因为以后可能会请求这个对象,所以允许 oops 花费一点额外的带宽将该对象添加到其高速缓存中,"maxresident" 设置 oops 将要高速缓存的对象大小的硬性上界。在本例中,oops 不会高速缓存超过 1 MB 的文件。该参数的目的是防止较大的对象占据 oops 的高速缓存,从而迫使 oops 丢弃较小的对象,而用户请求较小对象的次数常常比较大文件的次数多得多。然后,我们关闭了 "insert_x_forwarded_for" 和 "insert_via" HTTP 头。通常,oops 在每个 HTTP 请求中插入两个纯信息性的头。既然不需要它们,我就将它们关闭 -- 这就节省了一点带宽,还使 oops 不那么罗嗦。最后,"always_check_freshness" 选项指示 oops:每次请求高速缓存的页面时,在将该页面发回客户机之前都应该快速检查,以确定该页面是否为最新页面。如果没有该选项,oops 将对页面是否为最新作某种假设,而这种假设可能不正确,从而导致人们获得某些站点的旧副本。"always_check_freshness" 为我们提供我们所需的类似于 Squid 的行为。 接下来,我们使用 acl、stop_cache 和 stop_cache_acl 参数来避免高速缓存不应该缓存的事物: acl MYSITE urlregex (www\.gentoo\.orgcvs\.gentoo\.org) stop_cache_acl MYSITE stop_cache ? stop_cache cgi-bin 首先,我们使用 acl 参数创建一个名为 "MYSITE" 的新 ACL(访问控制表)。将 oops ACL 看成一种可以在文件的以后部分引用的模式,它允许我们指定:当 ACL 恰巧匹配时,应该执行哪些操作和不应该执行哪些操作。虽然 oops 非常广泛地使用 ACL,但这是我们样本配置文件中唯一出现的一个 ACL。这个 ACL 将匹配任何包含 "www.gentoo.org" 和 "cvs.gentoo.org" 的 URL。在接下来的一行中,我么使用 stop_cache_acl 参数让 oops 知道:不应该高速缓存任何带有与 MYSITE ACL 匹配的 URL 的请求。这将有效防止高速缓存从 [url=www.gentoo.org]www.gentoo.org[/url] 和 cvs.gentoo.org 下载的对象。那么,我为什么要这样做呢?啊,因为 oops 恰巧运行在我的名为 "cvs.gentoo.org" 和 "www.gentoo.org" 的服务器/网关上。这台机器是使用 Apache 的 [url=www.gentoo.org]http://www.gentoo.org[/url] 网站的主机。 既然 oops 和 Apache 位于同一台机器,那么,oops 再高速缓存我的站点中的数据就显得有些愚蠢。这样做不会提高 Web 请求的处理速度,也不会减少网络带宽需求。相反,它只会浪费宝贵的内存和磁盘存储空间。您应该考虑使用 acl 和 stop_cache_acl 参数过滤掉与 oops 在同一台主机上的站点或者通过 oops 经局域网就可到达的站点。在这些情况下浪费宝贵的 oops 资源毫无意义。
上一页 [1] [2] [3] [4] 下一页 

接下来,我们使用两个 stop_cache 参数告诉 oops:永远不要高速缓存任何在 URL 中带有 "?" 或 "cgi'bin" 的请求;这是避免高速缓存 CGI 数据的快速而简便的方法。 配置文件的下一部分非常重要,它定义了我们的网络中允许使用 oops 的主机组。让我们看一下: group gentoo { networks 192.168.1/24 127.0.0/24; redir_mods transparent; badports [0:79],110,138,139,513,[6000:6010] ; miss allow; http { allow dstdomain * ; } } ……………… ……………… #module transparent { //-----注释掉前面的#号 # myport can have next form: # myport [{hostnameip_addr}:]port ... # myport 3128 //-----注释掉前面的#号 # broken_browsers MSIE # } //-----注释掉前面的#号 这个特定的组名为 "gentoo"(可随意将该名称改成别的名称),它包括在 "networks" 参数中指定的所有主机 -- 具有以 192.168.1 开头的 IP 地址的所有主机(我的本地局域网)和以 127.0.0 开头的所有主机(本地主机)。如果某台机器的 IP 地址属于 "networks" 参数中列出的网络的一部分,则将它看成 "gentoo" 组的一部分。当然,您要确保:"networks" 参数包括应该被允许使用 oops 的网络。接下来,redir_mods 行启用透明高速缓存功能(版本1.5.22的oops.cfg默认transparent模块被禁止,所以您要自己打开),并且 badports 参数告诉 oops 拒绝连接到特定远程端口的请求(在本例中,这些端口用于其它网络服务,几乎不可能提供任何 Web 内容)。badports 后面跟有 "miss" 参数,该参数很重要,因为它告诉 oops:如果这个特定组中的机器所请求的对象恰巧不在其内存或磁盘高速缓存中,则应该下载该对象。如果没有此参数,oops 将只能为这个组提已经高速缓存过的对象,而这几乎肯定不是您想要的。最后,http 参数允许这个组请求任何 ("*") 远程主机的数据。 好,这是我们要看的配置文件的最后一部分;该文件的其余部分无需任何手工配置,因此我们略过不谈。 group world { networks 0/0; badports [0:79],110,138,139,513,[6000:6010]; http { deny dstdomain * ; } } storage { path /var/lib/oops/storage/oops_storage ; size 400m ; } 如您所见,我们创建了另一个名为 "world" 的组,它与所有网络地址 (0/0) 匹配。这意味者,如果某台机器不是 "gentoo" 组的一部分,则可以将它看成 "world" 组的一部分,并将缺省拒绝 HTTP 访问 ("deny dstdomain *")。 最后,我们定义磁盘高速缓存的位置和大小 (400 MB);您可能想根据需要和可用的存储空间来减少或增加磁盘高速缓存的大小。另外还要注意,将把 /var/lib/oops/storage/oops_storage 创建成稀疏文件。这意味着,最初该文件几乎不占据任何磁盘空间,但可以根据需要达到这里指定的最大容量。好,完成该文件之后,请保存并关闭 oops.cfg 文件,我们也就最终配置好了 oops! 既然已经配置了 oops,现在就可以指示 oops 创建其磁盘高速缓存了。您只需这样做一次。请输入: # oops -z -c /etc/oops/oops.cfg 现在,应该可以使用磁盘高速缓存了。此时,您可以输入以下命令来启动 oops: # oopsctl start 现在,oops 应该正在运行,并且,您应该可以将局域网上的 Web 浏览器配置成:使用您 Linux 机器的端口 3128 作为 Web 代理。请尝试一会儿 oops,您应该注意到,当再次查看同一站点时,速度会有很大提升。 既然 oops 作为普通的代理工作,那么,您可能想让 oops 以透明模式工作。要这样做,需要满足几个要求: 1、您的 Linux 机器必须是您的局域网的网关 2、您的 Linux 机器必须使用启用了 netfilter 的 2.4+ 内核 3、必须安装了 iptables 如果满足了这些要求,就可以通过输入以下命令启用透明模式: # iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j REDIRECT --to-port 3128 该命令将把所有目标端口为 80 的、通过您的 Linux 网关的连接自动转向 Linux 网关的 3128 端口,oops 将在那里拦截和处理它们。现在,无需任何额外配置,您的局域网中的所有浏览器都应该可以自动开始使用这个代理。请注意,如果将浏览器配置成使用该 oops 代理,它仍可以工作。 如果您的 Linux 机器不是局域网网关,也并非完全不能实现透明模式。仍然可以配置网络,以便您的 Linux 机器可以充当透明代理。幸运的是,有一种极佳的方法来这样做,这在 Linux Advanced Routing HOWTO 中的 Cookbook 一节有详细描述。 --------作者:Daniel Robbins

(出处:http://www.sheup.com)


上一页 [1] [2] [3] [4] 

如您所见,我们创建了另一个名为 "world" 的组,它与所有网络地址 (0/0) 匹配。这意味者,如果某台机器不是 "gentoo" 组的一部分,则可以将它看成 "world" 组的一部分,并将缺省拒绝 HTTP 访问 ("deny dstdomain *")。 最后,我们定义磁盘高速缓存的位置和大小 (400 MB);您可能想根据需要和可用的存储空间来减少或增加磁盘高速缓存的大小。另外还要注意,将把 /var/lib/oops/storage/oops_storage 创建成稀疏文件。这意味着,最初该文件几乎不占据任何磁盘空间,但可以根据需要达到这里指定的最大容量。好,完成该文件之后,请保存并关闭 oops.cfg 文件,我们也就最终配置好了 oops! 既然已经配置了 oops,现在就可以指示 oops 创建其磁盘高速缓存了。您只需这样做一次。请输入: # oops -z -c /etc/oops/oops.cfg 现在,应该可以使用磁盘高速缓存了。此时,您可以输入以下命令来启动 oops: # oopsctl start 现在,oops 应该正在运行,并且,您应该可以将局域网上的 Web 浏览器配置成:使用您 Linux 机器的端口 3128 作为 Web 代理。请尝试一会儿 oops,您应该注意到,当再次查看同一站点时,速度会有很大提升。 既然 oops 作为普通的代理工作,那么,您可能想让 oops 以透明模式工作。要这样做,需要满足几个要求: 1、您的 Linux 机器必须是您的局域网的网关 2、您的 Linux 机器必须使用启用了 netfilter 的 2.4+ 内核 3、必须安装了 iptables 如果满足了这些要求,就可以通过输入以下命令启用透明模式: # iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j REDIRECT --to-port 3128 该命令将把所有目标端口为 80 的、通过您的 Linux 网关的连接自动转向 Linux 网关的 3128 端口,oops 将在那里拦截和处理它们。现在,无需任何额外配置,您的局域网中的所有浏览器都应该可以自动开始使用这个代理。请注意,如果将浏览器配置成使用该 oops 代理,它仍可以工作。 如果您的 Linux 机器不是局域网网关,也并非完全不能实现透明模式。仍然可以配置网络,以便您的 Linux 机器可以充当透明代理。幸运的是,有一种极佳的方法来这样做,这在 Linux Advanced Routing HOWTO 中的 Cookbook 一节有详细描述。 --------作者:Daniel Robbins

(出处:http://www.sheup.com)


上一页 [1] [2] [3] [4] [5] 

好,这是我们要看的配置文件的最后一部分;该文件的其余部分无需任何手工配置,因此我们略过不谈。 group world { networks 0/0; badports [0:79],110,138,139,513,[6000:6010]; http { deny dstdomain * ; } } storage { path /var/lib/oops/storage/oops_storage ; size 400m ; } 如您所见,我们创建了另一个名为 "world" 的组,它与所有网络地址 (0/0) 匹配。这意味者,如果某台机器不是 "gentoo" 组的一部分,则可以将它看成 "world" 组的一部分,并将缺省拒绝 HTTP 访问 ("deny dstdomain *")。 最后,我们定义磁盘高速缓存的位置和大小 (400 MB);您可能想根据需要和可用的存储空间来减少或增加磁盘高速缓存的大小。另外还要注意,将把 /var/lib/oops/storage/oops_storage 创建成稀疏文件。这意味着,最初该文件几乎不占据任何磁盘空间,但可以根据需要达到这里指定的最大容量。好,完成该文件之后,请保存并关闭 oops.cfg 文件,我们也就最终配置好了 oops! 既然已经配置了 oops,现在就可以指示 oops 创建其磁盘高速缓存了。您只需这样做一次。请输入: # oops -z -c /etc/oops/oops.cfg 现在,应该可以使用磁盘高速缓存了。此时,您可以输入以下命令来启动 oops: # oopsctl start 现在,oops 应该正在运行,并且,您应该可以将局域网上的 Web 浏览器配置成:使用您 Linux 机器的端口 3128 作为 Web 代理。请尝试一会儿 oops,您应该注意到,当再次查看同一站点时,速度会有很大提升。 既然 oops 作为普通的代理工作,那么,您可能想让 oops 以透明模式工作。要这样做,需要满足几个要求: 1、您的 Linux 机器必须是您的局域网的网关 2、您的 Linux 机器必须使用启用了 netfilter 的 2.4+ 内核 3、必须安装了 iptables 如果满足了这些要求,就可以通过输入以下命令启用透明模式: # iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j REDIRECT --to-port 3128 该命令将把所有目标端口为 80 的、通过您的 Linux 网关的连接自动转向 Linux 网关的 3128 端口,oops 将在那里拦截和处理它们。现在,无需任何额外配置,您的局域网中的所有浏览器都应该可以自动开始使用这个代理。请注意,如果将浏览器配置成使用该 oops 代理,它仍可以工作。 如果您的 Linux 机器不是局域网网关,也并非完全不能实现透明模式。仍然可以配置网络,以便您的 Linux 机器可以充当透明代理。幸运的是,有一种极佳的方法来这样做,这在 Linux Advanced Routing HOWTO 中的 Cookbook 一节有详细描述。 --------作者:Daniel Robbins

(出处:http://www.sheup.com/)


上一页 [1] [2] [3] [4] [5] [6]