好得很程序员自学网
  • 首页
  • 后端语言
    • C#
    • PHP
    • Python
    • java
    • Golang
    • ASP.NET
  • 前端开发
    • Angular
    • react框架
    • LayUi开发
    • javascript
    • HTML与HTML5
    • CSS与CSS3
    • jQuery
    • Bootstrap
    • NodeJS
    • Vue与小程序技术
    • Photoshop
  • 数据库技术
    • MSSQL
    • MYSQL
    • Redis
    • MongoDB
    • Oracle
    • PostgreSQL
    • Sqlite
    • 数据库基础
    • 数据库排错
  • CMS系统
    • HDHCMS
    • WordPress
    • Dedecms
    • PhpCms
    • 帝国CMS
    • ThinkPHP
    • Discuz
    • ZBlog
    • ECSHOP
  • 高手进阶
    • Android技术
    • 正则表达式
    • 数据结构与算法
  • 系统运维
    • Windows
    • apache
    • 服务器排错
    • 网站安全
    • nginx
    • linux系统
    • MacOS
  • 学习教程
    • 前端脚本教程
    • HTML与CSS 教程
    • 脚本语言教程
    • 数据库教程
    • 应用系统教程
  • 新技术
  • 编程导航
    • 区块链
    • IT资讯
    • 设计灵感
    • 建站资源
    • 开发团队
    • 程序社区
    • 图标图库
    • 图形动效
    • IDE环境
    • 在线工具
    • 调试测试
    • Node开发
    • 游戏框架
    • CSS库
    • Jquery插件
    • Js插件
    • Web框架
    • 移动端框架
    • 模块管理
    • 开发社区
    • 在线课堂
    • 框架类库
    • 项目托管
    • 云服务

当前位置:首页>后端语言>PHP
<tfoot draggable='sEl'></tfoot>

php延时任务 php延时函数

很多站长朋友们都不太清楚php延时任务,今天小编就来给大家整理php延时任务,希望对各位有所帮助,具体内容如下:

本文目录一览: 1、 php使用redis的有序集合zset实现延迟队列 2、 PHP的哪个MVC框架最值得推荐 3、 求php项目开发文档 4、 php怎么处理高并发 5、 术士的宏 6、 为什么win10 edge浏览器无法访问该网页 php使用redis的有序集合zset实现延迟队列

延迟队列就是个带延迟功能的消息队列,相对于普通队列,它可以在指定时间消费掉消息。

我们通过redis的有序集合zset来实现简单的延迟队列,将消息数据序列化,作为zset的value,把消息处理时间作为score,每次通过zRangeByScore获取一条消息进行处理。

然后,我们写一个php脚本,用来处理队列中的任务。

PHP的哪个MVC框架最值得推荐

1、Laravel,laravel这个框架很有意思,定时任务,数据迁移,大概你能在web中想到的功能这个框架都可以提供,它的路由借鉴了Ruby on Rails 和Python的flask框架,但是还提供了web方面其它的一些功能,你可以把它想象成PHP中像Java一样强大的Web中的瑞士军刀,前提是你不考虑性能,因为它的实现使用了大量的闭包和反射,大概在PHP里严格引入设计模式的也只有这个了。

生产效率:5星

学习难度:5星(5星为最难,学习成本最高,下同)

性能:2星

社区活跃:4星(社区活跃可以很方便的找到别人已经开发的功能,专指中文文档,组件丰富性)

2、ThinkPHP5,大概3年前研究过TP3源码,使用起来简单,因为自动加载的问题,性能是个坑,现在发展到5,个人认为已经是一个相当优秀的框架了,路由定义简单,配置简单,文档丰富,社区也相当活跃

生产效率:5星

学习难度:1星

性能:4星

社区活跃:4星

3、Yii2,Yii2的路由分发跟TP5稍微有点不一样,也使用了反射的功能,自动加载现在都使用的composer,大体上都差不多,都有延时加载,Yii2的路由相对智能一些,不用去手动维护,类似于TP3所以使用起来也是很方便,性能比TP5应该略差点,没测试过,从源码来看

生产效率:5星

学习难度:2星

性能:3.5星

社区活跃:4星(很多强大的组件,你只要下载就行了,会省很多事)

4、CakePHP,这个框架内部的封装性看上去没上面那几个优美,但是它自己实现了use关键字功能,所以兼容性来看应该是比上面那几个好点的,但这在新项目上应该不是问题,新项目上PHP7,啥都别想,准没错。它的路由定义类似于TP5但是稍微多点功能,不过其实是个鸡肋。中文文档就不说了,很不好找。不过也算是个相对简单的框架严格遵循MVC

生产效率:3星

学习难度:3星

性能:4星

社区活跃:2星

5、Workman,这个框架相当强大,如果你要实现一些复杂的协议或者用php做一些websocket推送或者TCP/UDP服务器的话,这个框架可能可以满足你的需求,也有一些异步的组件,比较高级的框架,初中级程序员可能用不上

生产效率:3星

学习难度:4星

性能:3星

社区活跃:2星

6、swool,这是个相当有意思的框架,性能很强大,旁友,你听说过异步编程的nodejs,python的tornado框架吗,这个在php里做的就是一个这样的事情,国内的一位老兄开发的C扩展,用php来异步编程,看了下文档,稍微做了个性能测试,相当优秀,就是不知道在项目中重度使用会不会踩到什么坑,而且这也是一个相当高级的框架。大部分人可能直接转node了吧,毕竟node生态环境已经相当好了,总之,如果你想用php试试异步编程来提高性能,非这个框架莫属。性能独一档,编程难度也相对高一些,你需要有些进程的理论基础

生产效率:3星

学习难度:4星

性能:6星

社区活跃:2星

7、Yaf,鸟哥写的c扩展框架,然而你要自己实现很多轮子,生态环境是个大问题。

生产效率:4星

学习难度:4星

性能:5.5星

社区活跃:2星

其它框架还没怎么了解,国内的话,根据具体业务,选上面几个,没错。

求php项目开发文档

PHP项目开发全程实录

1.2 系统分析

1.2.1 需求分析

对于信息网站来说,用户的访问量是至关重要的。如果网站的访问量很低,那么就很少有企业会要求为他提供有偿服务,也就没有利润可言了。因此信息网站必须为用户提供大量的、免费的、有价值的信息才能够吸引用户。为此,网站不仅要为企业提供各种有偿服务,还需要额外为用户提供大量的无偿服务。通过与企业的实际接触和沟通,确定网站应包括招聘信息、求职信息、培训信息、公寓信息、家教信息、车辆信息、物品求购、物品出售、求兑出兑,寻求合作、企业广告等服务。

通过实际调查,要求供求信息网具有以下功能:

?0?6 界面设计美观大方、方便、快捷、操作灵活,树立企业形象。

?0?6 实现强大的供求信息查询,支持模糊查询。

?0?6 用户不需要注册,便可免费发布供求信息。

?0?6 免费发布的供求信息必须经后台审核后才能正式发布,避免不良信息。

?0?6 支持海量数据录入。

?0?6 由于供求信息数据量大,后台应该可以随时清理数据。

1.2.2 可行性分析

根据《GB8567-88计算机软件产品开发文件编制指南》中可行性分析的要求,制定可行性研究报告如下:

1.引言

(1)编写目的

为了给企业的决策层提供是否进行项目实施的参考依据,现以文件的形式分析项目的风险、项目需要的投资与效益。

(2)背景

×××信息科技有限公司是一家以整合渠道资源为主的高科技公司。企业为了不断满足客户的需求,为达到企业在同行业领域中的领先地位,现需要委托其他公司开发一个综合信息网,项目名称为九九度供求信息网。

2.可行性研究的前提

(1)要求

九九度供求信息网要求能够提供信息搜索、信息定位描红、发布免费信息、发布付费信息、发布企业广告、对各类发布的信息进行审核、删除、检索等功能。

(2)目标

九九度供求信息网的主要目标是提供强大的搜索功能,准确的信息描红定位功能,付费信息的管理、免费信息的审核和删除功能。

(3)条件、假定和限制

项目需要在两个月内交付用户使用。系统分析师需要3天内到位,用户需要4天时间确认需求分析文档。去除员工两个月的正常休息日16天,那么程序开发人员需要在1个月零几天的时间内进行系统设计、程序编码、系统测试、程序调试和网站部署工作。

(4)评价尺度

根据用户的要求,系统应以搜索引擎为主,对于发布的供求信息应能及时准确地保存、审核、查询、描红定位。由于用户存在多个营业点,系统应具有局域网操作的能力,在多个营业点同时运行系统时,系统中各项操作的延时不能超过10秒钟。此外,在系统出现故障时,应能及时进行恢复。

3.投资及效益分析

(1)支出

根据系统的规模及两个月的项目开发周期,公司决定投入5个人。因此,公司将直接支付8万元的工资及各种福利待遇。在项目安装及调试阶段,用户培训、员工出差等费用支出需要2万元。在项目维护阶段预计需要投入2万元的资金,累计项目投入需要12万元资金。

(2)收益

用户提供项目资金30万元。对于项目运行后进行的改动,采取协商的原则根据改动规模额外提供资金。因此从投资与收益的效益比上,公司可以获得18万元的利润。

项目完成后,将给公司提供资源储备,包括技术、经验的积累,以后再开发类似的项目时,可以极大地缩短项目开发周期。

4.结论

根据上面的分析,技术上不会存在问题,因此项目延期的可能性很小。在效益上,公司投入5个人、两个月的时间获利18万元,比较可观。在公司今后的发展上可以储备网站开发的经验和资源,因此认为该项目可以开发。

1.2.3 编写项目计划书

根据《GB8567-88计算机软件产品开发文件编制指南》中的项目开发计划要求,结合单位实际情况,设计项目计划书如下:

1.引言

(1)编写目的

为了保证项目开发人员按时保质地完成预订目标,更好地了解项目实际情况,按照合理的顺序开展工作,现以书面的形式将项目开发生命周期中的项目任务范围、项目团队组织结构、团队成员的工作责任、团队内外沟通协作方式、开发进度、检查项目工作等内容描述出来,作为项目相关人员之间的共识和约定以及项目生命周期内的所有项目活动的行动基础。

(2)背景

九九度供求信息网是本公司与×××信息科技有限公司签定的待开发项目,网站性质为信息服务类型,可为信息发布者有偿或无偿提供招聘、求职、培训、求购、公寓、车辆、房屋和出售等信息。项目周期为两个月,项目背景规划如表1.1所示。

表1.1 项目背景规划

项 目 名 称

签定项目单位

项目负责人

项目承担部门

九九度供求信息网

甲方:×××信息科技有限公司

甲方:赵经理

设计部门

开发部门

测试部门

乙方:×××网络科技有限公司

乙方:张经理

2.概述

(1)项目目标

项目目标应当符合SMART原则,把项目要完成的工作用清晰的语言描述出来。九九度供求信息网的项目目标如下:

九九度供求信息网主要用来为用户提供信息服务,对于生活和工作中的各类信息都应尽可能地全部包括在内,例如公寓、求职、招聘、培训、招商、房屋、车辆、出售、求购等信息。项目发布后,要实现能够为用户生活、工作带来极大的方便并提高企业知名度、为企业产品宣传节约大量成本的目标。整个项目需要在两个月的期限结束后,交给客户进行验收。

(2)产品目标与范围

一方面九九度供求信息网能够为企业节省大量人力资源,企业不再需要大量的业务人员去跑市场,间接为企业节约了成本。另一方面,九九度供求信息网能够收集海量供求信息,将会有大量用户访问网站,有助于提高企业知名度。

(3)应交付成果

项目开发完成后,交付的内容如下:

?0?6 以光盘的形式交付九九度供求信息网的源程序、网站数据库文件、系统使用说明书。

?0?6 客户方应用自己的服务器,因此需要乙方架设Apache服务器、安装PHP开发环境、协助甲方购买域名,将开发的九九度供求信息网发布到互联网上运行。

?0?6 网站发布到互联网上以后,进行后期的6个月无偿维护与服务,超过6个月后进行网站有偿维护与服务。

(4)项目验收方式与依据

项目验收分为内部验收和外部验收两种方式。在项目开发完成后,首先进行内部验收,由系统测试员根据用户需求和项目目标进行验收。项目在通过内部验收后交给用户进行验收,验收的主要依据为需求规格说明书。

3.项目团队组织

(1)组织结构

为了完成九九度供求信息网的项目开发,公司组建了一个临时的项目团队,由项目经理、系统分析师、PHP开发工程师、网页设计师和系统测试员构成

php怎么处理高并发

以下内容转载自徐汉彬大牛的博客?亿级Web系统搭建——单机到分布式集群?

当一个Web系统从日访问量10万逐步增长到1000万,甚至超过1亿的过程中,Web系统承受的压力会越来越大,在这个过程中,我们会遇到很多的问题。为了解决这些性能压力带来问题,我们需要在Web系统架构层面搭建多个层次的缓存机制。在不同的压力阶段,我们会遇到不同的问题,通过搭建不同的服务和架构来解决。

Web负载均衡?

Web负载均衡(Load Balancing),简单地说就是给我们的服务器集群分配“工作任务”,而采用恰当的分配方式,对于保护处于后端的Web服务器来说,非常重要。

负载均衡的策略有很多,我们从简单的讲起哈。

1.?HTTP重定向

当用户发来请求的时候,Web服务器通过修改HTTP响应头中的Location标记来返回一个新的url,然后浏览器再继续请求这个新url,实际上就是页面重定向。通过重定向,来达到“负载均衡”的目标。例如,我们在下载PHP源码包的时候,点击下载链接时,为了解决不同国家和地域下载速度的问题,它会返回一个离我们近的下载地址。重定向的HTTP返回码是302

这个重定向非常容易实现,并且可以自定义各种策略。但是,它在大规模访问量下,性能不佳。而且,给用户的体验也不好,实际请求发生重定向,增加了网络延时。

2. 反向代理负载均衡

反向代理服务的核心工作主要是转发HTTP请求,扮演了浏览器端和后台Web服务器中转的角色。因为它工作在HTTP层(应用层),也就是网络七层结构中的第七层,因此也被称为“七层负载均衡”。可以做反向代理的软件很多,比较常见的一种是Nginx。

Nginx是一种非常灵活的反向代理软件,可以自由定制化转发策略,分配服务器流量的权重等。反向代理中,常见的一个问题,就是Web服务器存储的session数据,因为一般负载均衡的策略都是随机分配请求的。同一个登录用户的请求,无法保证一定分配到相同的Web机器上,会导致无法找到session的问题。

解决方案主要有两种:

1.?配置反向代理的转发规则,让同一个用户的请求一定落到同一台机器上(通过分析cookie),复杂的转发规则将会消耗更多的CPU,也增加了代理服务器的负担。

2.?将session这类的信息,专门用某个独立服务来存储,例如redis/memchache,这个方案是比较推荐的。

反向代理服务,也是可以开启缓存的,如果开启了,会增加反向代理的负担,需要谨慎使用。这种负载均衡策略实现和部署非常简单,而且性能表现也比较好。但是,它有“单点故障”的问题,如果挂了,会带来很多的麻烦。而且,到了后期Web服务器继续增加,它本身可能成为系统的瓶颈。

3. IP负载均衡

IP负载均衡服务是工作在网络层(修改IP)和传输层(修改端口,第四层),比起工作在应用层(第七层)性能要高出非常多。原理是,他是对IP层的数据包的IP地址和端口信息进行修改,达到负载均衡的目的。这种方式,也被称为“四层负载均衡”。常见的负载均衡方式,是LVS(Linux Virtual Server,Linux虚拟服务),通过IPVS(IP Virtual Server,IP虚拟服务)来实现。

在负载均衡服务器收到客户端的IP包的时候,会修改IP包的目标IP地址或端口,然后原封不动地投递到内部网络中,数据包会流入到实际Web服务器。实际服务器处理完成后,又会将数据包投递回给负载均衡服务器,它再修改目标IP地址为用户IP地址,最终回到客户端。

上述的方式叫LVS-NAT,除此之外,还有LVS-RD(直接路由),LVS-TUN(IP隧道),三者之间都属于LVS的方式,但是有一定的区别,篇幅问题,不赘叙。

IP负载均衡的性能要高出Nginx的反向代理很多,它只处理到传输层为止的数据包,并不做进一步的组包,然后直接转发给实际服务器。不过,它的配置和搭建比较复杂。

4. DNS负载均衡

DNS(Domain Name System)负责域名解析的服务,域名url实际上是服务器的别名,实际映射是一个IP地址,解析过程,就是DNS完成域名到IP的映射。而一个域名是可以配置成对应多个IP的。因此,DNS也就可以作为负载均衡服务。

这种负载均衡策略,配置简单,性能极佳。但是,不能自由定义规则,而且,变更被映射的IP或者机器故障时很麻烦,还存在DNS生效延迟的问题。?

5. DNS/GSLB负载均衡

我们常用的CDN(Content Delivery Network,内容分发网络)实现方式,其实就是在同一个域名映射为多IP的基础上更进一步,通过GSLB(Global Server Load Balance,全局负载均衡)按照指定规则映射域名的IP。一般情况下都是按照地理位置,将离用户近的IP返回给用户,减少网络传输中的路由节点之间的跳跃消耗。

“向上寻找”,实际过程是LDNS(Local DNS)先向根域名服务(Root Name Server)获取到顶级根的Name Server(例如测试数据的),然后得到指定域名的授权DNS,然后再获得实际服务器IP。

CDN在Web系统中,一般情况下是用来解决大小较大的静态资源(html/Js/Css/图片等)的加载问题,让这些比较依赖网络下载的内容,尽可能离用户更近,提升用户体验。

例如,我访问了一张imgcache.gtimg.cn上的图片(腾讯的自建CDN,不使用qq测试数据域名的原因是防止http请求的时候,带上了多余的cookie信息),我获得的IP是183.60.217.90。

这种方式,和前面的DNS负载均衡一样,不仅性能极佳,而且支持配置多种策略。但是,搭建和维护成本非常高。互联网一线公司,会自建CDN服务,中小型公司一般使用第三方提供的CDN。

Web系统的缓存机制的建立和优化

刚刚我们讲完了Web系统的外部网络环境,现在我们开始关注我们Web系统自身的性能问题。我们的Web站点随着访问量的上升,会遇到很多的挑战,解决这些问题不仅仅是扩容机器这么简单,建立和使用合适的缓存机制才是根本。

最开始,我们的Web系统架构可能是这样的,每个环节,都可能只有1台机器。

我们从最根本的数据存储开始看哈。

一、 MySQL数据库内部缓存使用

MySQL的缓存机制,就从先从MySQL内部开始,下面的内容将以最常见的InnoDB存储引擎为主。

1. 建立恰当的索引

最简单的是建立索引,索引在表数据比较大的时候,起到快速检索数据的作用,但是成本也是有的。首先,占用了一定的磁盘空间,其中组合索引最突出,使用需要谨慎,它产生的索引甚至会比源数据更大。其次,建立索引之后的数据insert/update/delete等操作,因为需要更新原来的索引,耗时会增加。当然,实际上我们的系统从总体来说,是以select查询操作居多,因此,索引的使用仍然对系统性能有大幅提升的作用。

2. 数据库连接线程池缓存

如果,每一个数据库操作请求都需要创建和销毁连接的话,对数据库来说,无疑也是一种巨大的开销。为了减少这类型的开销,可以在MySQL中配置thread_cache_size来表示保留多少线程用于复用。线程不够的时候,再创建,空闲过多的时候,则销毁。

其实,还有更为激进一点的做法,使用pconnect(数据库长连接),线程一旦创建在很长时间内都保持着。但是,在访问量比较大,机器比较多的情况下,这种用法很可能会导致“数据库连接数耗尽”,因为建立连接并不回收,最终达到数据库的max_connections(最大连接数)。因此,长连接的用法通常需要在CGI和MySQL之间实现一个“连接池”服务,控制CGI机器“盲目”创建连接数。

建立数据库连接池服务,有很多实现的方式,PHP的话,我推荐使用swoole(PHP的一个网络通讯拓展)来实现。

3. Innodb缓存设置(innodb_buffer_pool_size)

innodb_buffer_pool_size这是个用来保存索引和数据的内存缓存区,如果机器是MySQL独占的机器,一般推荐为机器物理内存的80%。在取表数据的场景中,它可以减少磁盘IO。一般来说,这个值设置越大,cache命中率会越高。

4. 分库/分表/分区。

MySQL数据库表一般承受数据量在百万级别,再往上增长,各项性能将会出现大幅度下降,因此,当我们预见数据量会超过这个量级的时候,建议进行分库/分表/分区等操作。最好的做法,是服务在搭建之初就设计为分库分表的存储模式,从根本上杜绝中后期的风险。不过,会牺牲一些便利性,例如列表式的查询,同时,也增加了维护的复杂度。不过,到了数据量千万级别或者以上的时候,我们会发现,它们都是值得的。?

二、 MySQL数据库多台服务搭建

1台MySQL机器,实际上是高风险的单点,因为如果它挂了,我们Web服务就不可用了。而且,随着Web系统访问量继续增加,终于有一天,我们发现1台MySQL服务器无法支撑下去,我们开始需要使用更多的MySQL机器。当引入多台MySQL机器的时候,很多新的问题又将产生。

1. 建立MySQL主从,从库作为备份

这种做法纯粹为了解决“单点故障”的问题,在主库出故障的时候,切换到从库。不过,这种做法实际上有点浪费资源,因为从库实际上被闲着了。

2. MySQL读写分离,主库写,从库读。

两台数据库做读写分离,主库负责写入类的操作,从库负责读的操作。并且,如果主库发生故障,仍然不影响读的操作,同时也可以将全部读写都临时切换到从库中(需要注意流量,可能会因为流量过大,把从库也拖垮)。

3. 主主互备。

两台MySQL之间互为彼此的从库,同时又是主库。这种方案,既做到了访问量的压力分流,同时也解决了“单点故障”问题。任何一台故障,都还有另外一套可供使用的服务。

不过,这种方案,只能用在两台机器的场景。如果业务拓展还是很快的话,可以选择将业务分离,建立多个主主互备。

三、 MySQL数据库机器之间的数据同步

每当我们解决一个问题,新的问题必然诞生在旧的解决方案上。当我们有多台MySQL,在业务高峰期,很可能出现两个库之间的数据有延迟的场景。并且,网络和机器负载等,也会影响数据同步的延迟。我们曾经遇到过,在日访问量接近1亿的特殊场景下,出现,从库数据需要很多天才能同步追上主库的数据。这种场景下,从库基本失去效用了。

于是,解决同步问题,就是我们下一步需要关注的点。

1. MySQL自带多线程同步

MySQL5.6开始支持主库和从库数据同步,走多线程。但是,限制也是比较明显的,只能以库为单位。MySQL数据同步是通过binlog日志,主库写入到binlog日志的操作,是具有顺序的,尤其当SQL操作中含有对于表结构的修改等操作,对于后续的SQL语句操作是有影响的。因此,从库同步数据,必须走单进程。

2. 自己实现解析binlog,多线程写入。

以数据库的表为单位,解析binlog多张表同时做数据同步。这样做的话,的确能够加快数据同步的效率,但是,如果表和表之间存在结构关系或者数据依赖的话,则同样存在写入顺序的问题。这种方式,可用于一些比较稳定并且相对独立的数据表。

国内一线互联网公司,大部分都是通过这种方式,来加快数据同步效率。还有更为激进的做法,是直接解析binlog,忽略以表为单位,直接写入。但是这种做法,实现复杂,使用范围就更受到限制,只能用于一些场景特殊的数据库中(没有表结构变更,表和表之间没有数据依赖等特殊表)。?

四、 在Web服务器和数据库之间建立缓存

实际上,解决大访问量的问题,不能仅仅着眼于数据库层面。根据“二八定律”,80%的请求只关注在20%的热点数据上。因此,我们应该建立Web服务器和数据库之间的缓存机制。这种机制,可以用磁盘作为缓存,也可以用内存缓存的方式。通过它们,将大部分的热点数据查询,阻挡在数据库之前。

1. 页面静态化

用户访问网站的某个页面,页面上的大部分内容在很长一段时间内,可能都是没有变化的。例如一篇新闻报道,一旦发布几乎是不会修改内容的。这样的话,通过CGI生成的静态html页面缓存到Web服务器的磁盘本地。除了第一次,是通过动态CGI查询数据库获取之外,之后都直接将本地磁盘文件返回给用户。

在Web系统规模比较小的时候,这种做法看似完美。但是,一旦Web系统规模变大,例如当我有100台的Web服务器的时候。那样这些磁盘文件,将会有100份,这个是资源浪费,也不好维护。这个时候有人会想,可以集中一台服务器存起来,呵呵,不如看看下面一种缓存方式吧,它就是这样做的。

2. 单台内存缓存

通过页面静态化的例子中,我们可以知道将“缓存”搭建在Web机器本机是不好维护的,会带来更多问题(实际上,通过PHP的apc拓展,可通过Key/value操作Web服务器的本机内存)。因此,我们选择搭建的内存缓存服务,也必须是一个独立的服务。

内存缓存的选择,主要有redis/memcache。从性能上说,两者差别不大,从功能丰富程度上说,Redis更胜一筹。

3. 内存缓存集群

当我们搭建单台内存缓存完毕,我们又会面临单点故障的问题,因此,我们必须将它变成一个集群。简单的做法,是给他增加一个slave作为备份机器。但是,如果请求量真的很多,我们发现cache命中率不高,需要更多的机器内存呢?因此,我们更建议将它配置成一个集群。例如,类似redis cluster。

Redis cluster集群内的Redis互为多组主从,同时每个节点都可以接受请求,在拓展集群的时候比较方便。客户端可以向任意一个节点发送请求,如果是它的“负责”的内容,则直接返回内容。否则,查找实际负责Redis节点,然后将地址告知客户端,客户端重新请求。

对于使用缓存服务的客户端来说,这一切是透明的。

内存缓存服务在切换的时候,是有一定风险的。从A集群切换到B集群的过程中,必须保证B集群提前做好“预热”(B集群的内存中的热点数据,应该尽量与A集群相同,否则,切换的一瞬间大量请求内容,在B集群的内存缓存中查找不到,流量直接冲击后端的数据库服务,很可能导致数据库宕机)。

4. 减少数据库“写”

上面的机制,都实现减少数据库的“读”的操作,但是,写的操作也是一个大的压力。写的操作,虽然无法减少,但是可以通过合并请求,来起到减轻压力的效果。这个时候,我们就需要在内存缓存集群和数据库集群之间,建立一个修改同步机制。

先将修改请求生效在cache中,让外界查询显示正常,然后将这些sql修改放入到一个队列中存储起来,队列满或者每隔一段时间,合并为一个请求到数据库中更新数据库。

除了上述通过改变系统架构的方式提升写的性能外,MySQL本身也可以通过配置参数innodb_flush_log_at_trx_commit来调整写入磁盘的策略。如果机器成本允许,从硬件层面解决问题,可以选择老一点的RAID(Redundant Arrays of independent Disks,磁盘列阵)或者比较新的SSD(Solid State Drives,固态硬盘)。

5. NoSQL存储

不管数据库的读还是写,当流量再进一步上涨,终会达到“人力有穷时”的场景。继续加机器的成本比较高,并且不一定可以真正解决问题的时候。这个时候,部分核心数据,就可以考虑使用NoSQL的数据库。NoSQL存储,大部分都是采用key-value的方式,这里比较推荐使用上面介绍过Redis,Redis本身是一个内存cache,同时也可以当做一个存储来使用,让它直接将数据落地到磁盘。

这样的话,我们就将数据库中某些被频繁读写的数据,分离出来,放在我们新搭建的Redis存储集群中,又进一步减轻原来MySQL数据库的压力,同时因为Redis本身是个内存级别的Cache,读写的性能都会大幅度提升。

国内一线互联网公司,架构上采用的解决方案很多是类似于上述方案,不过,使用的cache服务却不一定是Redis,他们会有更丰富的其他选择,甚至根据自身业务特点开发出自己的NoSQL服务。

6. 空节点查询问题

当我们搭建完前面所说的全部服务,认为Web系统已经很强的时候。我们还是那句话,新的问题还是会来的。空节点查询,是指那些数据库中根本不存在的数据请求。例如,我请求查询一个不存在人员信息,系统会从各级缓存逐级查找,最后查到到数据库本身,然后才得出查找不到的结论,返回给前端。因为各级cache对它无效,这个请求是非常消耗系统资源的,而如果大量的空节点查询,是可以冲击到系统服务的。

在我曾经的工作经历中,曾深受其害。因此,为了维护Web系统的稳定性,设计适当的空节点过滤机制,非常有必要。

我们当时采用的方式,就是设计一张简单的记录映射表。将存在的记录存储起来,放入到一台内存cache中,这样的话,如果还有空节点查询,则在缓存这一层就被阻挡了。

异地部署(地理分布式)

完成了上述架构建设之后,我们的系统是否就已经足够强大了呢?答案当然是否定的哈,优化是无极限的。Web系统虽然表面上看,似乎比较强大了,但是给予用户的体验却不一定是最好的。因为东北的同学,访问深圳的一个网站服务,他还是会感到一些网络距离上的慢。这个时候,我们就需要做异地部署,让Web系统离用户更近。

一、 核心集中与节点分散

有玩过大型网游的同学都会知道,网游是有很多个区的,一般都是按照地域来分,例如广东专区,北京专区。如果一个在广东的玩家,去北京专区玩,那么他会感觉明显比在广东专区卡。实际上,这些大区的名称就已经说明了,它的服务器所在地,所以,广东的玩家去连接地处北京的服务器,网络当然会比较慢。

当一个系统和服务足够大的时候,就必须开始考虑异地部署的问题了。让你的服务,尽可能离用户更近。我们前面已经提到了Web的静态资源,可以存放在CDN上,然后通过DNS/GSLB的方式,让静态资源的分散“全国各地”。但是,CDN只解决的静态资源的问题,没有解决后端庞大的系统服务还只集中在某个固定城市的问题。

这个时候,异地部署就开始了。异地部署一般遵循:核心集中,节点分散。

·?核心集中:实际部署过程中,总有一部分的数据和服务存在不可部署多套,或者部署多套成本巨大。而对于这些服务和数据,就仍然维持一套,而部署地点选择一个地域比较中心的地方,通过网络内部专线来和各个节点通讯。

·?节点分散:将一些服务部署为多套,分布在各个城市节点,让用户请求尽可能选择近的节点访问服务。

例如,我们选择在上海部署为核心节点,北京,深圳,武汉,上海为分散节点(上海自己本身也是一个分散节点)。我们的服务架构如图:

需要补充一下的是,上图中上海节点和核心节点是同处于一个机房的,其他分散节点各自独立机房。?

国内有很多大型网游,都是大致遵循上述架构。它们会把数据量不大的用户核心账号等放在核心节点,而大部分的网游数据,例如装备、任务等数据和服务放在地区节点里。当然,核心节点和地域节点之间,也有缓存机制。?

二、 节点容灾和过载保护

节点容灾是指,某个节点如果发生故障时,我们需要建立一个机制去保证服务仍然可用。毫无疑问,这里比较常见的容灾方式,是切换到附近城市节点。假如系统的天津节点发生故障,那么我们就将网络流量切换到附近的北京节点上。考虑到负载均衡,可能需要同时将流量切换到附近的几个地域节点。另一方面,核心节点自身也是需要自己做好容灾和备份的,核心节点一旦故障,就会影响全国服务。

过载保护,指的是一个节点已经达到最大容量,无法继续接接受更多请求了,系统必须有一个保护的机制。一个服务已经满负载,还继续接受新的请求,结果很可能就是宕机,影响整个节点的服务,为了至少保障大部分用户的正常使用,过载保护是必要的。

解决过载保护,一般2个方向:

·?拒绝服务,检测到满负载之后,就不再接受新的连接请求。例如网游登入中的排队。

·?分流到其他节点。这种的话,系统实现更为复杂,又涉及到负载均衡的问题。

小结

Web系统会随着访问规模的增长,渐渐地从1台服务器可以满足需求,一直成长为“庞然大物”的大集群。而这个Web系统变大的过程,实际上就是我们解决问题的过程。在不同的阶段,解决不同的问题,而新的问题又诞生在旧的解决方案之上。

系统的优化是没有极限的,软件和系统架构也一直在快速发展,新的方案解决了老的问题,同时也带来新的挑战。

术士的宏

由于通篇全是术士的宏所以就发到术士区来了有错误的地方还望指正

SuperMacro的下载页面

此网页不属于NGA网站,NGA不保证其安全性

继续访问 取消 不再提示我[ ]

某些宏需要它的支持比如“RunMacro”。

MegaMacro:

此网页不属于NGA网站,NGA不保证其安全性

继续访问 取消 不再提示我[ ]

SmartPet:

此网页不属于NGA网站,NGA不保证其安全性

继续访问 取消 不再提示我[ ]

首发在

此网页不属于NGA网站,NGA不保证其安全性

继续访问 取消 不再提示我[ ]

这篇文章是在那看到的,这个博客也不是我的。

这是原文,作者应该是一个叫Graguk 的谢谢他了

此网页不属于NGA网站,NGA不保证其安全性

继续访问 取消 不再提示我[ ]

===============以下是正文=================

Announcing our first of many MEGAMACROS! Using the addon SuperMacro (

此网页不属于NGA网站,NGA不保证其安全性

继续访问 取消 不再提示我[ ]), we can now split our macros into multiple /script commands (each /script is still limited to 255 character) and run them all.

宣布我们许多MEGAMACROS中的第一个宏!利用了SuperMacro这个插件,现在我们可以把我们的宏分成若干个/script命令(每个/script依然限制在255个字符那)并且能运行它。

SuperMacro的下载页面

此网页不属于NGA网站,NGA不保证其安全性

继续访问 取消 不再提示我[ ]

Thanks Daemorius for the original Megamacro request (and some help) and for helping me iron out the bugs with some testing and his own macro skills.

感谢Daemorius对于这个原始的Megamacro (request怎么翻?)(及其一些小帮助)Revenant(灵魂?)并且帮助我寻找测试bugs方面他自己的能力(大致意思就是感谢对于我在寻找bugs、测试方面的帮助)

This is a smart megamacro - it will cast Siphon Life, Corruption, and Curse of Agony in that order if those debuffs are not found on your target. In addition, if your target is dispelling class (priest or paladin), it will only cast the curse. Also, if your target is a curse curing class, it will only cast the magic debuffs.

这是一个痛苦宏 - 使用了生命虹吸、腐化、痛苦诅咒在使用这些命令后假如你的目标还是没有发现那些debuffs。另外假如你的目标是能够趋散的职业(牧师或者骑士)就要使用语言诅咒。并且,如果你的目标是诅咒的治疗职业,就只用语言诅咒。

Unfortunately, there's no way to know if the debuff it found was yours, so if 2 warlocks are dot'ing the same target, the macro assumes the debuffs are yours and doesn't try to stack them.

遗憾的是,他们是没有方式去知道是谁放的假如这个debuff被发现是你放的,这样假设有2个术士正在对同一个目标使用dot,这个宏会假设这些debuffs是你施放的并且不再试图去叠加他(说白了就是这个宏不重复对同一个目标使用同一个debuff)

Make seperate macros for each /script command, and name them z1, z2, z3, and z4 respectively. You then drag the last macro onto your UI and activate that one.

制作其它的宏都要使用/script命令,并且分别对他们命名就如z1,z2,z3,z4。你可以在你的插件里托动the last macro(最后?最近?的宏)并且去激活它们。

上篇最后一句话应该是”最后你可以对你的宏进行命名并去激活它(就是使用)“

/script

hasAgony=false;

hasCorruption=false;

hasSiphon=false;

--建立全局变量“hasAgony”、“hasCorruption”、“hasSiphon”并对它们分别赋值为false

/script

local i,l;

for i=1,16,1 do

GameTooltip:SetUnitDebuff("target",i); --[[游戏工具小帖示:建立目标debuff索引。对目标的所有debuff查找找到需要的后对于相应的debuff赋值]]

l=GameTooltipTextLeft1:GetText(); --对 局部变量赋值(这里好像涉及到字体的设置)

if l=="Curse of Agony" then --假如 变量“l”等于“Curse of Agony”(痛苦诅咒)那么

hasAgony=true; --对 变量“hasAgony”赋值为“true” 并结束循环

else --否则

if l=="Corruption" then --假如 局部变量“l”等于“Corruption”(腐化)那么

hasCorruption=true; --对 变量“hasCorruption” 赋值为 “ture” 并结束条件判断

else --否则

if l=="Siphon Life" then --再来个判断假如 变量“l”等于“Siphon Life”(生命虹吸)那么

hasSiphon=true; --对 变量“hasSiphon” 赋值为 “true” 并结束循环

end; --结束当前if

end; --结束上一个if

end; --结束再上一个if

end; --结束for循环

--[[注意“==”不是赋值而是一个判断

建立了2个局部变量“i”、“l”,建立一个循环语句初值是1,终止是16,步长是1

for i=1,16,1 do 这个我是故意把8改成16的1.6.1以后BLZ增加了buff的位置我们要紧跟时代的潮流所以把8改成了16]]

/script

if UnitClass("target") == ("Paladin" or "Priest") then --假如目标职业是 骑士或者牧师 那么

hasCorruption=true; --变量“hasCorruption”值为“true”

hasSiphon=true; --变量“hasSiphon”值为“true”

else --否则

if UnitClass("target") == ("Mage" or "Druid") then --假如目标职业是 法师或者德鲁伊 那么

hasAgony = true; --变量“hasAgony”值为“true”

end; --结束当前if

end;

/script

if hasSiphon==false then --假如 变量“hasSiphon”等于“false” 那么

CastSpellByName("Siphon Life(Rank 4)"); --使用技能 "Siphon Life(Rank 4)" (4级 生命虹吸)

else --否则

if hasCorruption==false then --再判断 变量“hasCorruption”值为“false” 那么

CastSpellByName("Corruption(rank 6)"); --使用技能 "Corruption(rank 6)"(6级 生命虹吸)

else --否则

if hasAgony==false then --再判断 变量“hasAgony”值为“false” 那么

CastSpellByName("Curse of Agony(rank 6)"); --使用技能 "Curse of Agony(rank 6)" (6级 痛苦诅咒)

else --否则

TargetNearestEnemy(); --选择最最近的一个敌人

end; --结束但前if

end; --结束上一个if判断

end; --结束再上一个if判断

/script

RunMacro("z1");

RunMacro("z2");

RunMacro("z3");

RunMacro("z4")

--[[RunMacro就是运行宏的意思这需要那个叫SuperMacro的插件来支持它(就如同“in”一个延时命令需要cosmos的支持一样)

“z1”之类的应该是它对4个/script的命名]]

8th June 2005:

2005年6月8日

TargetLastEnemy()

(another minor update - TargetLastEnemy() can be used to recover your target if you command

your pet to reseduce when you have no target.

一个小小的更新 - “TargetLastEnemy()”能够被用来恢复你选择的目标假如你命令你的宝宝去reseduce(

我不知道这是什么意思=.=!但我猜测是自动选择)当你没有目标时。(乱啊~我的理解是有个更新是关于“

TargetLastEnemy()”它能够用来选择你最后一个敌人……那位达人帮忙翻下)

This is an update to the original Seduce macro. If you have a succubus out, it will

PetAttack (so we can assist again later), start casting Seduction, and cast Curse of Shadow

(rank 2). If you have the Felhunter out, it will Devour Magic on your target. There may be

times when you want to devour your enemy, there may be times you want to devour yourself.. I

figured I'd leave it up to the user to hit F1 to target himself if required (I also ran out

of space :P).

--[[这是在原先媚惑的宏上更新的。

假如你在野外招了个媚魔,就会有宠物攻击(所以在后面我们协助攻击),开始使用媚惑并且施放2级暗影诅咒。

假如你在野外招了胆汁猎人……(应该是指狗狗),它将吞噬你目标的魔法(应该就是指打断魔法)。

在你想要打败你的敌人时或许那就时个机会,翻不下去了……还是看看他编的宏]]

/script

b=UnitCreatureFamily("pet"); --对 变量“b” 赋值为 “自己的宠物”

c=CastPetAction; --对 变量“c” 赋值为 “宠物技能”

d=UnitName("target").." is being SEDUCED <3 <3"; --对 变量“d” 赋值为 “目标..正在被媚惑”

if b=="Succubus" then --假如 变量“b” 等于 媚魔(就是说召唤的宠物是媚魔)那么

PetAttack(); --宠物攻击目标

c(6); --使用第6个技能,我猜应该是媚惑,我的10级术士虚空任务刚接……

SendChatMessage(d,"PARTY"); --在队伍频道输出 变量“d” 什么效果不用我说了吧

CastSpellByName("Curse of Shadow(rank 2)"); --使用技能 2级 暗影诅咒

else --否则

if b=="Felhunter" then --判断假如 变量“b” 等于 地狱犬 那么

c(4); --[[宠物使用第4个技能,谁能告诉我第4个是什么技能如果知道第4个技能那么那几句英文应该猜的出来了]]

end;

end;

--[[一段根据召唤的宠物使用不同的技能并且在队伍频道告诉其他人。比起那段英文容易多了]]

This is an update to the re-seduce macro.

If you have the Succubus out, it will assist her, then start casting Seduction again, then TargetLastEnemy.

If you have the Felhunter out, it will spell lock your target.

这是根据二次媚惑修改的宏。

假如你在野外召唤了媚魔,在她再次使用媚惑时就要协助她攻击刚才那个目标。

假如你在野外召唤了地狱犬就会锁定你的目标。

/script

b=UnitCreatureFamily("pet"); --对 变量“b” 赋值为 “自己的宠物”

c=CastPetAction; --对 变量“c” 赋值为 “宠物技能”

if b=="Succubus" then --假如 变量“b” 等于 媚魔那么

ClearTarget(); --取消目标选择

c(6); --使用宠物技能第6个,谁能告诉我是什么技能?有什么用?

TargetLastEnemy(); --选择上一个敌人

else --否则

if b=="Felhunter" then --判断 变量“b” 等于 “地狱犬” 那么

c(6); --使用宠物第6个技能,还是那个问题谁能告诉我

end;

end;

--由于对宠物技能的不了解我也不知道这个宏有什么意义。

23rd May 2005:

2005年5月23日

Sends in the pet, casts curse of agony. If health is getting low, hit again to curse of recklessness to stop it running. (by Stix)

(这里的sends怎么翻?是送?牺牲?)宠物,使用痛苦诅咒。假如目标生命值很低,再次使用鲁莽诅咒阻止对方逃跑。

/script

PetAttack();

/script

if (UnitHealth("target")<90) then

CastSpellByName("Curse of Recklessness(Rank 1)")

else

CastSpellByName("Curse of Agony(Rank 4)")

end;

--[[太简单了我不解释了自己看"Curse of Recklessness(Rank 1)" 1级 鲁莽诅咒,"Curse of Agony(Rank 4)" 4级 痛苦诅咒]]

16th May 2005:

2005年5月16日

PVP macro: Scan current target for Siphon Life, cast it if it's not present, if it is, try

to target another enemy.

pvp 宏:分析目标目前是否适合使用生命虹吸,如果目标没有生命虹吸就对它使用,假如目标已经有了就选择另外一个敌人。

/script

z=0;

for i=1,16 do

UnitDebuff("target", i);

GameTooltip:SetUnitDebuff("target",i);

if GameTooltipTextLeft1:GetText()=="Siphon Life" then

z=1;

end;

end;

if z==1 then

TargetNearestEnemy();

else

CastSpellByName("Siphon Life(Rank 4)");

end;

--同样简单具体自己分析,我说下它的功能根据目标的debuff来判断施放使用4级 生命虹吸。

Curse of Shadow, then Enslave Demon.

暗影诅咒,并且奴役恶魔。

/script

x=CastSpellByName;

z=0;

for i=1,8 do

UnitDebuff("target", i);

GameTooltip:SetUnitDebuff("target",i);

if GameTooltipTextLeft1:GetText()=="Curse of Shadow" then

z=1;

end;

end;

if z==1 then

x("Enslave Demon(Rank 3)");

else

x("Curse of Shadow(Rank 2)");

end;

--实现的方法同上一个自己分析吧"Enslave Demon(Rank 3)" 3级 奴役恶魔,"Curse of Shadow(Rank 2)" 2级 暗影诅咒

13th May 2005:

2005年5月13日

Searing Pain macro that check to see if Nightfall/Shadow Trance has proceed and if so cast Shadow Bolt.

灼热之痛的宏检查是否有黑夜降临/暗影状态就继续并且使用暗影箭

/script

z=0;

for i=1,16 do

UnitBuff("player", i);

GameTooltip:SetUnitBuff("player",i);

if GameTooltipTextLeft1:GetText()=="Shadow Trance" then

z=1

;end;

end;

if z==1 then

CastSpellByName("Shadow Bolt(Rank 9)");暗影箭

else

CastSpellByName("Searing Pain(Rank 6)");灼热之痛

end;

--同上同上~!"Searing Pain(Rank 6)" 6级 灼热之痛,"Shadow Bolt(Rank 9)" 9级 暗影箭

9th May 2005:

2005年5月9日

Today's macros are new and untested. Please post feedback. :)

今天的宏是新的没有没有被测试过,请各位告诉我效果如何。:)

--[[This is an update to Yvero's conflagrate else Immolate macro.

Please note this is experimental and I need to know if using GameTooltip in this way has any adverse effect on tooltips in game.

这是根据Yvero的火灾和献祭宏来修改的。

请注意这是实验过的并且我需要了解如果在游戏提示里利用GameTooltip有什么不好的影响。]]

/script

z=0;

for i=1,16 do

UnitDebuff("target", i);

GameTooltip:SetUnitDebuff("target",i);

if GameTooltipTextLeft1:GetText()=="Immolate" then

z=1;

end;

end;

if z==1 then

CastSpellByName("Conflagrate(Rank 4)");天赋技能4级火灾

else

CastSpellByName("Immolate(Rank 7)");7级献祭

end;

--没新意思~~:"Conflagrate(Rank 4)" 天赋技能 4级 火灾,"Immolate(Rank 7)" 7级 献祭

Amplify Curse, else Curse of Exhaustion:

增强诅咒,否则使用疲劳诅咒:

/script

local e, f, g = GetSpellCooldown(16, SpellBookFrame.bookType);

if (f<= 0) then

CastSpellByName("Amplify Curse");

else

CastSpellByName("Curse of Exhaustion");

end

--[[这有了一个新的函数“GetSpellCooldown”是一个显示技能冷却时间的函数

基本格式:local start,duration,enable= GetSpellCooldown(id, SpellBookFrame.bookType)

对于它的意义运用消化中,也就不误人子弟了 "Amplify Curse" 增强诅咒,"Curse of Exhaustion" 疲劳诅咒]]

2nd May 2005:

2005年5月2日

Fel Domination/Summon Voidwalker/Sacrifice Voidwalker macro (updated)

邪恶控制、召唤、控制虚空,牺牲虚空的宏(更新过)

/script

local a=CastSpellByName;

local e,f,g=GetSpellCooldown(16, SpellBookFrame.bookType);

if UnitCreatureFamily("pet") == "Voidwalker" then

CastPetAction(5);

else

if f<=0 then

a("Fel Domination");

else

a("Summon Voidwalker");

end;

end;

--[[对于“GetSpellCooldown”函数依然没有完全理解,谁能告诉我那3个变量有什么用?

我知道duration是魔法持续时间,start是魔法开始时间,enable呢?是不是使用指定的技能?

id这有是什么意思?是指定技能的编号吗?怎么确定的?

“Summon Voidwalker” 召唤虚空,"Fel Domination" 邪恶控制

NOTE: You MUST change the 16 in GetSpellCooldown to the index of Fel Domination.

Every time you learn a new spell, you need to check if the index has incremented.

In order to find the ID, execute the following macro:

注意:你必须更新 "Fel Domination" 邪恶控制 在GetSpellCooldown里的索引编号。

每次你学完一个新的技能,你需要去检查一下索引编号是否又增加了。

为了找到这个编号,需要执行以下的宏~(原来这个技能编号这么来的要看的要看的)]]

/script

for id = 1, 180, 1 do

local spellName, subSpellName = GetSpellName(id, SpellBookFrame.bookType);

if spellName and string.find(spellName, "Fel Domination", 1, true) then

ChatFrame1:AddMessage("ID is "..id, 1.0, 1.0, 0.5);

end;

end;

--[[又是一个新的函数“GetSpellName”返回技能的名称和排名(就是那个索引编号)

基本格式:local spellName, subSpellName = GetSpellName(id, SpellBookFrame.bookType);

NOTE2: Some people have reported problems with the Summon Voidwalker part of this macro.

If you have this problem, please do the following to make it work:

注意2:有人告诉我一些问题是是关于召唤虚空的那段宏。

假如你也有这些问题请照着下面的去做:

Execute the following macro to determine the spell ID of Summon Voidwalker

(note you'll have to re-run this any time you learn a new spell as the ID may change).

执行判断 召唤虚空 技能编号的宏。

(注意你每次学了一个新的技能后这个编号都可能会改变)]]

/script

for id = 1, 180, 1 do

local spellName, subSpellName = GetSpellName(id, SpellBookFrame.bookType);

if spellName and string.find(spellName, "Summon Voidwalker", 1, true) then

ChatFrame1:AddMessage("ID is "..id, 1.0, 1.0, 0.5);

end;

end;

--[[Now you have the ID for Summon Voidwalker, replace the index 100 in the CastSpell function

in the following macro with the ID in *your* spellbook

(as above, you still need to change 16 to whatever the ID of Fel Domination is in your spellbook):

现在你有了召唤虚空的技能编号,更换索引编号在施法函数里在以下的宏里这个id就是在你的技能书里

【好像翻的不对~】(同上面一样,你还是需要更换你在技能书里的技能编号):]]

/script

local a=CastSpellByName;

local e,f,g=GetSpellCooldown(16, SpellBookFrame.bookType);

if UnitCreatureFamily("pet") == "Voidwalker" then

CastPetAction(5);

else

if f<=0 then

a("Fel Domination");

else

CastSpell(100, SpellBookFrame.bookType);

end;

end;

--[[由于对于几个新的函数了解不深所以这个我不解释了免得误人子弟,残害他人那幼小的心灵终于剩下这最后一段了]]

1st May 2005:

(Graguk post)

2005年5月1日

(Graguk 公告)那天是我在ngacn注册的那天

This macro scans your Spellbook and reports the ID of the spell you are interested in on your Main Chat frame.

Replace Fel Domination with the spell whose index you are interested in.

这段宏是分析你所感兴趣的技能并在你的主聊天窗口里报告它的id。(后面那句翻不来)

/script

for id = 1, 180, 1 do

local spellName, subSpellName = GetSpellName(id, SpellBookFrame.bookType);

if spellName and string.find(spellName, "Fel Domination", 1, true) then

ChatFrame1:AddMessage("ID is "..id, 1.0, 1.0, 0.5);

end;

end;

PVP marco: Each press of this macro will scan your target for Corruption,

if it's not present, it will Cast Corruption(Rank 1), if it is present, it will TargetNearestEnemy (same as hitting TAB).

This macro is based on one of Yvero's macros. (updated with correct string)

PVP 宏:如果对方不是平民,每次运行宏都会检查你目标是否有腐化,并使用1级的腐化,如果是平民,就选择最近一个敌人(相当于按下Tab)。这个宏的基础是Yvero的宏中的一个。(修正了string<不知道怎么翻>)

The benefit is three-fold..

它有3个好处……(翻的比较差,原谅我吧~!)

1. Dispellers using CTRaidAssist will see the debuff and dispell it - they don't know it's rank 1.

Dispellers【亚没查一下(就是估计的意思)<趋散诅咒的人>】利用CTRaidAssist可以看到这个debuff并去趋散它,但是他们不知道这是一个1级的诅咒。

(浪费对方的魔法?趋散是瞬发的吧?那是锻炼对方的操作?)

2. Little DoTs like this drive rogues up the wall because they can't stealth.

一些dots可以把盗贼逼出来,因此他们不再变得诡秘。

3. Nightfall proc chance :)

使用的过程中有机会出黑夜降临:)

/script z=0

for i=1,8 do

t=UnitDebuff("target", i)

if (t and string.find(t,"Spell_Shadow_AbominationExplosion")) then

z=1

end;

end;

if z==1 then

TargetNearestEnemy()

else

CastSpellByName("Corruption(Rank 1)")

end;

Shadow bolt/Pet Attack/Dark Pact macro:

暗影箭/宠物攻击/黑暗契约 宏:

If you have an enemy target, when you hit this macro it will start casting shadow bolt and send in the pet.

If you have no target and you hit this macro, it will Dark Pact your pet.

假如你有一个目标(敌人),在你运行这个宏以后它将施放暗影箭并且宠物上前攻击。

假如你没有目标并且你也运行了这个宏就是用黑暗契约。

/script

if UnitName("target")~=nil and UnitIsEnemy("target", "player") then

CastSpellByName("Shadow Bolt(rank 9)");

PetAttack();

else

CastSpellByName("Dark Pact(rank 3)");

end;

为什么win10 edge浏览器无法访问该网页

因为默认访问规则的限制,Windows Apps 在默认状态下无法访问本地回环端口。

1.在Win10任务栏中的Cortana搜索框中输入Powershell 。

2.在顶部的搜索结果“Windows Powershell”上点击右键,选择“以管理员身份运行”。

3.然后在打开的“管理员:Windows Powershell”窗口中输入以下命令(先复制后面的内容,右键直接粘贴):Get-AppXPackage -AllUsers | Foreach {Add-AppxPackage -DisableDevelopmentMode -Register “$($_.InstallLocation)\AppXManifest.xml”}回车,等待命令运行完毕,运行的时间与系统已安装的应用数量有关。

4.命令运行完毕之后,即完成了Win10所有Modern应用的重置。

关于php延时任务的介绍到此就结束了,不知道本篇文章是否对您有帮助呢?如果你还想了解更多此类信息,记得收藏关注本站,我们会不定期更新哦。

查看更多关于php延时任务 php延时函数的详细内容...

声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did195986
更新时间:2023-04-26   阅读:28次

上一篇: php遍历新建目录 php遍历结果集

下一篇:php重写父类方法 php 重写 重载

最新资料更新

  • 1.php实现小说目录的方法 php自动生成小说
  • 2.php半角全角 全角半角字符切换
  • 3.php前端页面源码 php前端页面源码是多少
  • 4.学php学什么专业 学php可以干什么工作
  • 5.中南php哪家好 中南cp
  • 6.php梗怎么来的 php是什么意思饭圈
  • 7.php生成缓存图片 php缓存机制有哪些
  • 8.php代码的缺点 php的缺点是什么
  • 9.php编程实验总结 php简单实训项目
  • 10.php中catch的简单介绍
  • 11.php图片打不开 php打不开文件
  • 12.包含php7.0.10的词条
  • 13.php每天更新数据 php数据库更新语句
  • 14.登录htmlphp 登录html
  • 15.php余数1 php math
  • 16.phpml源码安装 下载了个php源码包,怎么使用
  • 17.php输出jq代码 php输出hello
  • 18.php文章发布系统 php发布网站
  • 19.php数学函数 php中函数的定义
  • 20.如何阅读php源码 php在线源码获取

CopyRight:2016-2025好得很程序员自学网 备案ICP:湘ICP备09009000号-16 http://haodehen.cn
本站资讯不构成任何建议,仅限于个人分享,参考须谨慎!
本网站对有关资料所引致的错误、不确或遗漏,概不负任何法律责任。
本网站刊载的所有内容(包括但不仅限文字、图片、LOGO、音频、视频、软件、程序等)版权归原作者所有。任何单位或个人认为本网站中的内容可能涉嫌侵犯其知识产权或存在不实内容时,请及时通知本站,予以删除。

网站内容来源于网络分享,如有侵权发邮箱到:kenbest@126.com,收到邮件我们会即时下线处理。
网站框架支持:HDHCMS   51LA统计 百度统计
Copyright © 2018-2025 「好得很程序员自学网」
[ SiteMap ]