看到这个标题的时候,我和此文作者是一样的心态,apache也能做这个?我一向以为是nginx之类的才行?
仔细一想,如果可行,那应该是用了apache 的 proxy吧?以前用proxy做过asp的代理,如果负载均衡,估计用这个也应该可以吧?
究竟是不是这样呢?看看原文内容就知道了
原文地址为:http://tech.idv2.com/2009/07/22/loadbalancer-with-apache/
内容如下:
第一次看到这个标题时我也很惊讶,Apache居然还能做负载均衡?真是太强大了。 经过一番调查后发现的确可以,而且功能一点都不差。 这都归功于 mod_proxy 这个模块。 不愧是强大的Apache啊。
废话少说,下面就来解释一下负载均衡的设置方法。
一般来说,负载均衡就是将客户端的请求分流给后端的各个真实服务器, 达到负载均衡的目的。还有一种方式是用两台服务器,一台作为主服务器(Master), 另一台作为热备份(Hot Standby),请求全部分给主服务器,在主服务器当机时, 立即切换到备份服务器,以提高系统的整体可靠性。
负载均衡的设置
Apache可以应对上面这两种需求。先来讨论一下如何做负载均衡。 首先需要启用Apache的几个模块:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_http_module modules/mod_proxy_http.so
mod_proxy提供代理服务器功能,mod_proxy_balancer提供负载均衡功能, mod_proxy_http让代理服务器能支持HTTP协议。如果把mod_proxy_http换成 其他协议模块(如mod_proxy_ftp),或许能支持其他协议的负载均衡, 有兴趣的朋友可以自己尝试一下。
然后要添加以下配置:
ProxyRequests Off
<Proxy balancer://mycluster>
BalancerMember http://node-a.myserver.com:8080
BalancerMember http://node-b.myserver.com:8080
</Proxy>
ProxyPass / balancer://mycluster
# 警告:以下这段配置仅用于调试,绝不要添加到生产环境中!!!
<Location /balancer-manager>
SetHandler balancer-manager
Order Deny,Allow
Deny from all
Allow from localhost
</Location>
从上面的 ProxyRequests Off 这条可以看出,实际上负载均衡器就是一个反向代理, 只不过它的代理转发地址不是某台具体的服务器,而是一个 balancer:// 协议:
ProxyPass / balancer://mycluster
协议地址可以随便定义。然后,在<Proxy>段中设置该balancer协议的内容即可。 BalancerMember指令可以添加负载均衡组中的真实服务器地址。
下面那段<Location /balancer-manager>是用来监视负载均衡的工作情况的, 调试时可以加上(生产环境中禁止使用!),然后访问 http://localhost/balancer-manager/ 即可看到 负载均衡的工作状况。
OK,改完之后重启服务器,访问你的Apache所在服务器的地址,即可看到负载均衡的效果了。 打开 balancer-manager 的界面,可以看到请求是平均分配的。
如果不想平均分配怎么办?给 BalancerMember 加上 loadfactor 参数即可,取值范围为1-100。 比如你有三台服务器,负载分配比例为 7:2:1,只需这样设置:
ProxyRequests Off
<Proxy balancer://mycluster>
BalancerMember http://node-a.myserver.com:8080 loadfactor=7
BalancerMember http://node-b.myserver.com:8080 loadfactor=2
BalancerMember http://node-c.myserver.com:8080 loadfactor=1
</Proxy>
ProxyPass / balancer://mycluster
默认情况下,负载均衡会尽量让各个服务器接受的请求次数满足预设的比例。 如果要改变算法,可以使用 lbmethod 属性。如:
ProxyRequests Off
<Proxy balancer://mycluster>
BalancerMember http://node-a.myserver.com:8080 loadfactor=7
BalancerMember http://node-b.myserver.com:8080 loadfactor=2
BalancerMember http://node-c.myserver.com:8080 loadfactor=1
</Proxy>
ProxyPass / balancer://mycluster
ProxySet lbmethod=bytraffic
lbmethod可能的取值有:
lbmethod=byrequests |
按照请求次数均衡(默认) |
lbmethod=bytraffic |
按照流量均衡 |
lbmethod=bybusyness |
按照繁忙程度均衡(总是分配给活跃请求数最少的服务器) |
各种算法的原理请参见Apache的文档。
热备份(Hot Standby)
热备份的实现很简单,只需添加 status=+H 属性,就可以把某台服务器指定为备份服务器:
ProxyRequests Off
<Proxy balancer://mycluster>
BalancerMember http://node-a.myserver.com:8080
BalancerMember http://node-b.myserver.com:8080 status=+H
</Proxy>
ProxyPass / balancer://mycluster
从 balancer-manager 界面中可以看到,请求总是流向 node-a ,一旦node-a挂掉, Apache会检测到错误并把请求分流给 node-b。Apache会每隔几分钟检测一下 node-a 的状况, 如果node-a恢复,就继续使用node-a。
500年一遇的日全食就这么被一场大雨给阻隔了。
下次要看再等三百年吧,准备考虑开始修真,可以多活几年。哈哈
随便说说关于日全食的笑话:
1、天宫用了盗版windows,被微软300年黑屏一次
2、天宫操作系统被黑客入侵,全黑了
3、为什么这次黑屏有五分钟?因为天狗吃太阳时,太烫,不象以前吃月亮,冷的,一口就可以干掉
4、老天和人玩:天黑请闭眼
5、日全食事件,显然是别有用心的太阳,煽动不明真相的月亮,利用地球自传和公转的机会,实施的一起有组织有预谋的破坏中国稳定的颠覆活动。我XX已经派出乌云部队进行拦截,同时对月亮进行宣传教育,在我XX强大的ZZ攻势和宣传教育下,月亮深刻明白了自身的错误,弃暗投明,并劝说太阳为宇宙建设发光发热。目前太阳月亮地球情绪稳定。乌云部队也已经返回基地。
6、嫦娥驾着月亮想与太阳神私会,却惹得地球人怨声载道,嫦娥不喜,结果不欢而散 (评论:美女傍老外,自然那么多人不开心了)
7、太阳:“亮,我们又见面了,很多话想跟你说,却不知道从何说起。”(月亮一下子扑入太阳怀中)月亮:“日,什么都不用说了!”地球及其他星体:[安静并感叹]我们五百年才看一次A片啊!
8、太阳:“亮,五百年了,我们终于又在一起了。 ”月亮:“日,什么都不用说了 ” (关灯,一头扑入怀中)。。。。。。。。(一会儿)月亮:“怎么才五分钟? ”太阳:“地球上看的人太多了,我紧张
其他的后来人补上。。
一直在考虑是不是要换到wordpress, sablog用了这么长时间,也算是有感情了的。只是,他一直不更新,而且前台模板用的那种定界符做模板处理,我很不习惯。
以前coolcode.cn也是用的wordpress,后来转到了sablog上面。如今,我却想转到wordpress上面。。。不知道是进步还是退步。
也曾想过重写前台,请了两个朋友帮我做页面,结果现在是程序写了一半,页面做了一半,离完成看来是遥遥无期了。。
所以,记录下这个文章,方便以后真的要转换的时候,也能做个参考。。
» 阅读全文
网上找来的代码,经典的东西哦。做网游的人可能会用到。。
XML/HTML代码
- <html><head><title>use A* to find path...</title></head>
- <body style="margin:0px">
- <script>
- /*
- written by hjjboy
- email:tianmashuangyi@163.com
- qq:156809986
- */
- var closelist=new Array(),openlist=new Array();//closelist保存最终结果。openlist保存临时生成的点;
- var gw=10,gh=10,gwh=14;//参数 gh是水平附加参数 gwh是四角的附加参数。
- var p_start=new Array(2),p_end=new Array(2);//p_start为起点,p_end为终点
- var s_path,n_path="";//s_path为当前点 n_path为障碍物数组样式的字符串.
- var num,bg,flag=0;
- var w=30,h=20;
- function GetRound(pos){//返回原点周围的8个点
- var a=new Array();
- a[0]=(pos[0]+1)+","+(pos[1]-1);
- a[1]=(pos[0]+1)+","+pos[1];
- a[2]=(pos[0]+1)+","+(pos[1]+1);
- a[3]=pos[0]+","+(pos[1]+1);
- a[4]=(pos[0]-1)+","+(pos[1]+1);
- a[5]=(pos[0]-1)+","+pos[1];
- a[6]=(pos[0]-1)+","+(pos[1]-1);
- a[7]=pos[0]+","+(pos[1]-1);
- return a;
- }
- function GetF(arr){ //参数为原点周围的8个点
- var t,G,H,F;//F,综合的距离值,H,距离值 G,水平\角落附加计算
- for(var i=0;i<arr.length;i++){
- t=arr[i].split(",");
- t[0]=parseInt(t[0]);
- t[1]=parseInt(t[1]);
- if(IsOutScreen([t[0],t[1]])||IsPass(arr[i])||InClose([t[0],t[1]])||IsStart([t[0],t[1]])||!IsInTurn([t[0],t[1]]))
- continue;//如果上面条件有一满足,则跳过本次循环,进行下一次。
- if((t[0]-s_path[3][0])*(t[1]-s_path[3][1])!=0)//判断该点是否处于起点的垂直或横向位置上
- G=s_path[1]+gwh;//如果不在G=14;
- else
- G=s_path[1]+gw;//如果在G=10;
- if(InOpen([t[0],t[1]])){//如果当前点已存在openlist数组中
- if(G<openlist[num][1]){
- maptt.rows[openlist[num][4][1]].cells[openlist[num][4][0]].style.backgroundColor="blue";//调试
- openlist[num][0]=(G+openlist[num][2]);
- openlist[num][1]=G;
- openlist[num][4]=s_path[3];
- }
- else{G=openlist[num][1];}
- }
- else{
- H=(Math.abs(p_end[0]-t[0])+Math.abs(p_end[1]-t[1]))*gw;
- F=G+H;
- arr[i]=new Array();
- arr[i][0]=F;
- arr[i][1]=G;
- arr[i][2]=H;
- arr[i][3]=[t[0],t[1]];
- arr[i][4]=s_path[3];
- openlist[openlist.length]=arr[i];//将F等信息保存到openlist
- }
- if(maptt.rows[t[1]].cells[t[0]].style.backgroundColor!="#cccccc"&&maptt.rows[t[1]].cells[t[0]].style.backgroundColor!="#0000ff"&&maptt.rows[t[1]].cells[t[0]].style.backgroundColor!="#ff0000"&&maptt.rows[t[1]].cells[t[0]].style.backgroundColor!="#00ff00")
- {
- maptt.rows[t[1]].cells[t[0]].style.backgroundColor="#FF00FF";
- if(F!=undefined)
- maptt.rows[t[1]].cells[t[0]].innerHTML="<font color='black'>"+F+"</font>";
- }
- }
- }
- function IsStart(arr){ //判断该点是不是起点
- if(arr[0]==p_start[0]&&arr[1]==p_start[1])
- return true;
- return false;
- }
- function IsInTurn(arr){ //判断是否是拐角
- if(arr[0]>s_path[3][0]){
- if(arr[1]>s_path[3][1]){
- if(IsPass((arr[0]-1)+","+arr[1])||IsPass(arr[0]+","+(arr[1]-1)))
- return false;
- }
- else if(arr[1]<s_path[3][1]){
- if(IsPass((arr[0]-1)+","+arr[1])||IsPass(arr[0]+","+(arr[1]+1)))
- return false;
- }
- }
- else if(arr[0]<s_path[3][0]){
- if(arr[1]>s_path[3][1]){
- if(IsPass((arr[0]+1)+","+arr[1])||IsPass(arr[0]+","+(arr[1]-1)))
- return false;
- }
- else if(arr[1]<s_path[3][1]){
- if(IsPass((arr[0]+1)+","+arr[1])||IsPass(arr[0]+","+(arr[1]+1)))
- return false;
- }
- }
- return true;
- }
- function IsOutScreen(arr){ //是否超出场景范围
- if(arr[0]<0||arr[1]<0||arr[0]>(w-1)||arr[1]>(h-1))
- return true;
- return false;
- }
- function InOpen(arr){//获得传入在openlist数组的位置,如不存在返回false,存在为true,位置索引保存全局变量num中。
- var bool=false;
- for(var i=0;i<openlist.length;i++){
- if(arr[0]==openlist[i][3][0]&&arr[1]==openlist[i][3][1]){
- bool=true;num=i;break;}
- }
- return bool;
- }
- function InClose(arr){
- var bool=false;
- for(var i=0;i<closelist.length;i++){
- if((arr[0]==closelist[i][3][0])&&(arr[1]==closelist[i][3][1])){
- bool=true;break;}
- }
- return bool;
- }
- function IsPass(pos){ //pos这个点是否和障碍点重合
- if((";"+n_path+";").indexOf(";"+pos+";")!=-1)
- return true;
- return false;
- }
- function Sort(arr){//整理数组,找出最小的F,放在最后的位置。
- var temp;
- for(var i=0;i<arr.length;i++){
- if(arr.length==1)break;
- if(arr[i][0]<=arr[i+1][0]){
- temp=arr[i];
- arr[i]=arr[i+1];
- arr[i+1]=temp;
- }
- if((i+1)==(arr.length-1))
- break;
- }
- }
- function main(){//主函数
- // alert('');
- GetF(//把原点周围8点传入GetF进行处理。算A*核心函数了 :),进行求F,更新openlist数组
- GetRound(s_path[3]) //求原点周围8点
- );
- // debugdiv.innerHTML+="A:"+openlist.join('|')+"<br />";//调试
- Sort(openlist);//整理数组,找出最小的F,放在最后的位置。
- //debugdiv.innerHTML+="B:"+openlist.join('|')+"<br />";//调试
- s_path=openlist[openlist.length-1];//设置当前原点为F最小的点
- closelist[closelist.length]=s_path;//讲当前原点增加进closelist数组中
- openlist[openlist.length-1]=null;//从openlist中清除F最小的点
- //debugdiv.innerHTML+="C:"+openlist.join('|')+"<br />";//调试
- if(openlist.length==0){alert("Can't Find the way");return;}//如果openlist数组中没有数据了,则找不到路径
- openlistopenlist.length=openlist.length-1;//上次删除把数据删了,位置还保留了,这里删除
- if((s_path[3][0]==p_end[0])&&(s_path[3][1]==p_end[1])){//如果到到终点了,描绘路径
- getPath();
- }
- else{//否则循环执行,标准原点
- maptt.rows[s_path[3][1]].cells[s_path[3][0]].style.backgroundColor="green";setTimeout("main()",100);
- }
- }
- function getPath(){//描绘路径
- var str="";
- var t=closelist[closelist.length-1][4];
- while(1){
- str+=t.join(",")+";";
- maptt.rows[t[1]].cells[t[0]].style.backgroundColor="#ffff00";
- for(var i=0;i<closelist.length;i++){
- if(closelist[i][3][0]==t[0]&&closelist[i][3][1]==t[1])
- t=closelist[i][4];
- }
- if(t[0]==p_start[0]&&t[1]==p_start[1])
- break;
- }
- alert(str);
- }
- function setPos(){//初始原点为起点
- var h=(Math.abs(p_end[0]-p_start[0])+Math.abs(p_end[1]-p_start[1]))*gw;
- s_path=[h,0,h,p_start,p_start];
- }
- function set(id,arr){//设置点的类型
- switch(id){
- case 1:
- p_start=arr;
- maptt.rows[arr[1]].cells[arr[0]].style.backgroundColor="#ff0000";break;
- case 2:
- p_end=arr;maptt.rows[arr[1]].cells[arr[0]].style.backgroundColor="#0000ff";break;
- case 3:
- n_path+=arr.join(",")+";";maptt.rows[arr[1]].cells[arr[0]].style.backgroundColor="#cccccc";break;
- default:
- break;
- }
- }
- function setflag(id){flag=id;}
- </script>
- <table id="maptt" cellspacing="1" cellpadding="0" border="0" bgcolor="#000000">
- <script>
- for(var i=0;i<h;i++){
- document.write("<tr>");
- for(var j=0;j<w;j++){
- document.write('<td onclick="set(flag,['+j+','+i+']);" bgcolor="#ffffff" width="20" height="20"></td>');
- }
- document.write("</tr>");
- }
- </script>
- </table>
- <a href="javascript:setflag(1);">StarPoint</a><br>
- <a href='javascript:setflag(2);'>EndPoint</a><br>
- <a href='javascript:setflag(3);'>Wall</a><br>
- <input type="button" onclick="setPos();main();this.disabled=true;" value="find">
- <div id="debugdiv"></div>
-
- </body>
- </html>
原文连接:http://www.gamedev.net/reference/articles/article2003.asp
中文翻译:http://data.gameres.com/message.asp?TopicID=25439
我是从http://www.cnblogs.com/jimtomjim/archive/2009/07/20/1527112.html拷贝来的
说实话,我没有用过这种方法,也不知道是否非常有用。但总体来说,它的效率肯定不如直接target="_blank"好吧?
如果不用JS,那以后的版本里怎么办才好呢?难道不开新窗了?怎么办?未来该如何操作?
原文如下:
itpob:http://www.cnblogs.com/itpob/archive/2009/07/19/1526700.html
- 现在一般网站打开新窗口采用的是target="_blank",这在过渡型DOCTYPE(xh tml1-transitional. dtd)下是允许的,但也不符合W3C的strict(xhtml1-strict.dtd)标准。
-
- 如果你去验证,会发现有下面的错误提示:
-
- "there is no attribute target for this element(in this HTML version)"
-
- 这是因为W3C认为如果不经过用户同意,没有明确提示就打开一个新窗口是不礼貌的。所以我们只好用下面的rel属性来解决这个问题。rel是 HTML4.0新增加的一个属性,这个属性用来说明链接和包含此链接页面的关系,以及链接打开的目标。rel有许多的属性值,比如next、 previous,、chapter、section等等。
-
- 我们用rel属性的external和一个js脚本来解决问题,代码如下:
-
- <a href=”http://www.kepu8.com“ rel="external"> 打开一个新窗口</a>
-
- * 大量古细菌在海底被发现
- * 英开发致命超级病菌-绿脓杆菌早期检测技术
- * 无需 DNA 细菌也变身
- * 小袋鼠育儿袋内吃奶照片
- * 大白鲨类似连环杀手-捕食方式揭秘
- * 蚂蚁长寿差异之谜:蚁后更长寿的秘诀在于多睡觉
- * 张启发院士:培育绿色超级稻可缓解农业生态问题
- * 广西反季节龙眼新品种挂果枝率达98%以上
- * 日本专家从柚子皮中提取出能抑制过敏的物质
- * 水稻精确定量栽培技术实现新突破
-
-
- 我们把js文件存储为external.js,然后通过<script type="text/javascript" src="external.js"></script>调用
-
- 下面是js文件
-
- function externallinks() {
- if (!document.getElementsByTagName) return;
- var anchors = document.getElementsByTagName("a");
- for (var i=0; i<anchors.length; i++) {
- var anchor = anchors[i];
- if (anchor.getAttribute("href") &&
- anchor.getAttribute("rel") == "external")
- anchor.target = "_blank";
- }
- }
- window.onload = externallinks;