1.Ursa云硬盘对IaaS云计算平台有至关重要的作用,几乎已成为必备组件,如亚马逊的EBS(ElasticBlockStore)、阿里云的盘古、OpenStack中的Cinder等。云硬盘可为云计算平台带来许多优良特性,如更高的数据可靠性和可用性、灵活的数据快照功能、更好的虚拟机动态迁移支持、更短的主机故障恢复时间等等。随着万兆以太网逐渐普及,云硬盘的各项优势得到加强和凸显,其必要性变得十分强烈。云硬盘的底层通常是分布式块存储系统,目前开源领域有一些此类项目,如CephRBD、Sheepdog。另外MooseFS和GlusterFS虽然叫做文件系统,但由于其特性与块存储系统接近,也能用于支持云硬盘。我们在测评中发现,这些开源项目均存在一些问题,使得它们都难以直接应用在大规模的生产系统当中。例如CephRBD的效率较低(CPU使用过高);Sheepdog在压力测试中出现了数据丢失的现象;MooseFS的POSIX语义支持、基于FUSE的架构、不完全开源的2.0版本等问题给它自身带来了许多的局限性;GlusterFS与Ceph同属红帽收购的开源存储系统,主要用于scale-out文件存储场景,在云计算领域使用不多。此外,这些存储系统都难以充发挥用万兆网卡和SSD的性能潜力,难以在未来承担重任。由于以上原因,美团云研发了全新的分布式块存储系统Ursa,通过简单稳固的系统架构、高效的代码实现以及对各种非典型场景的仔细考虑,实现了高可靠、高可用、高性能、低开销、可扩展、易运维、易维护等等目标。Ursa的名字源于DotA中的熊战士,他具有极高的攻击速度、攻击力和生命值,分别隐喻存储系统中的IOPS、吞吐率和稳定性。分布式块存储相关项目与技术2.1Ceph(主要参考:https://www.ustack.com/blog/ceph_infra/)Ceph项目起源于其创始人SageWeil在加州大学SantaCruz分校攻读博士期间的研究课题。项目的起始时间为2004年。在2006年的OSDI学术会议上,Sage发表了关于Ceph的论文,并提供了项目的下载链接,由此开始广为人知。2010年Ceph客户端部分代码正式进入Linuxkernel2.6.34。Ceph同时提供对象、块和文件这三个层次的分布式存储服务,其中只有块层存储与我们相关。由于块存储在IaaS云计算系统中占有重要地位,Ceph在近些年的关注度得到显著提高。许多云计算系统实例基于Ceph提供块存储服务,如UnitedStack、MirantisOpenStack等。Ceph性能测试测试版本:0.81操作系统:CentOS6.x测试工具:fio服务器配置:CPU:IntelXeonE5-2650v2@2.6GHzRAM:96GBNIC:10GbEHDD:6NLSAS,7200RPMRAIDController:DellH710p(LSI2208with1GBNVRAM)服务器数量:4,其中一个为兼职客户端注意:由于客户端位于一个存储服务器上,所以有1/4的吞吐率不经过网卡。测试结果如下:读IOPS:16407(此时客户端CPU占用率超过500%,5台服务器CPU总使用率接近500%)写IOPS:941顺序读吞吐率:218859KB/s顺序写吞吐率:67242KB/s顺序读延迟:1.6ms(664IOPS)顺序写延迟:4.4ms(225IOPS)网络ping值:0.1324ms本地硬盘顺序读写延迟:0.03332ms(29126IOPS)从测试来看,Ceph的读吞吐率正常,然而写吞吐率不足读的1/3,性能偏低;读写延迟比显著大于网络延迟与磁盘I/O延迟之和;CPU占用率过高。2.2Sheepdog(主要参考:http://peterylh.blog.163.com/blog/static/12033201221594937257/)Sheepdog是由日本NTT实验室的MoritaKazutaka专为虚拟化平台创立的分布式块存储开源项目,于2009年开源[1]。从2011年9月开始,一些淘宝的工程师加入了Sheepdog项目,以及相关开源项目比如Corosync、Accord的开发。Sheepdog主要由两部分组成:集群管理和存储服务,其中集群管理目前使用Corosync或者Zookper来完成,存储服务是全新实现的。Sheepdog采用无中心节点的全对称架构,基于一致性哈希实现从ObjectID到存储节点的定位:每个节点划分成多个虚拟节点,虚拟节点和ObjectID一样,采用64位整数唯一标识,每个虚拟节点负责一段包含节点ID在内的ObjectID区间。DataObject副本存在ObjectID对应的虚拟节点,及在后续的几个节点上。Sheepdog无单点故障问题,存储容量和性能均可线性扩展,新增节点通过简单配置即可加入集群,并且Sheepdog自动实现负载均衡,节点故障时可自动发现并进行副本修复,还直接支持QEMU/KVM。Sheepdog的服务进程既承担数据服务的职责,同时也是客户端(QEMU)访问数据的gateway。QEMU的Sheepdogdriver将对volume的请求转换成为对object的请求,然后通过UNIXdomainsocket或者TCPsocket连接一个Sheepdog服务进程,并将访问请求发给该进程来完成后续步骤。Sheepdog的服务进程还可以开启数据缓存功能,以减少网络I/O。Sheepdog的I/O路径是“clientgatewayobjectmanager(s)”,读操作可以在任意副本完成,更新操作并行的发往所有副本,当所有副本都更新成功之后,gateway才告诉客户端更新操作成功。Sheepdog的数据可靠性问题我们对Sheepdog开展了可靠性、可用性测试。在测试中有共3台服务器,每台配有6个机械硬盘,配置好Sheepdog之后,每台服务器启动10个VM,每个VM内无限循环运行fio分别执行小块随机读、写和大块顺序读、写的测试。在执行压力测试一周后,对集群中的全部数据进行一致性检测(collieclustercheck),发现有些数据块副本与另外2个不一致(“fixedreplica...”),有些数据块的3个各不相同(“nomajorityof...”): 复制代码代码如下:[root@node3-10gtest~]#collieclustercheckfixvditest1-399.9%[=================================================================>]50GB/50GBfixedreplica3e563000000fca99.9%[=================================================================>]50GB/50GBfixedreplica3e563000000fec100.0%[================================================================>]50GB/50GBfixedreplica3e5630000026f5100.0%[================================================================>]50GB/50GBfixedreplica3e563000002da6100.0%[================================================================>]50GB/50GBfixedreplica3e563000001e8c100.0%[================================================================>]50GB/50GBfixedreplica3e563000001530...fixvditest2-950.9%[=================================>]25GB/50GBnomajorityofd781e30000012351.0%[===================================>]26GB/50GBnomajorityofd781e30000015951.2%[===================================>]26GB/50GBnomajorityofd781e30000018a53.2%[====================================>]27GB/50GB…2.3MooseFS(主要参考:http://peterylh.blog.163.com/blog/static/12033201251791139592/)MooseFS是容错的分布式文件系统,通过FUSE支持标准POSIX文件系统接口。MooseFS的架构类似于GFS,由四个部分组成:管理服务器Master:类似于GFS的Master,主要有两个功能:(1)存储文件和目录元数据,文件元数据包括文件大小、属性、对应的Chunk等;(2)管理集群成员关系和Chunk元数据信息,包括Chunk存储、版本、Lease等。元数据备份服务器MetaloggerServer:根据元数据文件和log实时备份Master元数据。存储服务器ChunkServer:负责存储Chunk,提供Chunk读写能力。Chunk文件默认为64MB大小。客户端Client:以FUSE方式挂到本地文件系统,实现标准文件系统接口。MooseFS本地不会缓存Chunk信息,每次读写操作都会访问Master,Master的压力较大。此外MooseFS写操作流程较长且开销较高。MooseFS支持快照,但是以整个Chunk为单位进行CoW(Copy-on-Write),可能造成响应时间恶化,补救办法是以牺牲系统规模为代价,降低Chunk大小。MooseFS基于FUSE提供POSIX语义支持,已有应用可以不经修改直接迁移到MooseFS之上,这给应用带来极大的便利。然而FUSE也带来了一些负面作用,比如POSIX语义对于块存储来说并不需要,FUSE会带来额外开销等等。2.4GFS/HDFS(主要参考:http://www.nosqlnotes.net/archives/119)HDFS基本可以认为是GFS的一个简化开源实现,二者因此有很多相似之处。首先,GFS和HDFS都采用单一主控机+多台工作机的模式,由一台主控机(Master)存储系统全部元数据,并实现数据的分布、复制、备份决策,主控机还实现了元数据的checkpoint和操作日志记录及回放功能。工作机存储数据,并根据主控机的指令进行数据存储、数据迁移和数据计算等。其次,GFS和HDFS都通过数据分块和复制(多副本,一般是3)来提供更高的可靠性和更高的性能。当其中一个副本不可用时,系统都提供副本自动复制功能。同时,针对数据读多于写的特点,读服务被分配到多个副本所在机器,提供了系统的整体性能。最后,GFS和HDFS都提供了一个树结构的文件系统,实现了类似与Linux下的文件复制、改名、移动、创建、删除操作以及简单的权限管理等。然而,GFS和HDFS在关键点的设计上差异很大,HDFS为了规避GFS的复杂度进行了很多简化。例如HDFS不支持并发追加和集群快照,早期HDFS的NameNode(即Master)没原生HA功能。总之,HDFS基本可以认为是GFS的简化版,由于时间及应用场景等各方面的原因对GFS的功能做了一定的简化,大大降低了复杂度。2.5HLFS(主要参考:http://peterylh.blog.163.com/blog/static/120332012226104116710/)HLFS(HDFSLog-structuredFileSystem)是一个开源分布式块存储系统,其最大特色是结合了LFS和HDFS。HDFS提供了可靠、随时可扩展的文件服务,而HLFS通过Log-structured技术弥补了HDFS不能随机更新的缺憾。在HLFS中,虚拟磁盘对应一个文件,文件长度能够超过TB级别,客户端支持Linux和Xen,其中Linux基于NBD实现,Xen基于blktap2实现,客户端通过类POSIX接口libHLFS与服务端通讯。HLFS主要特性包括多副本、动态扩容、故障透明处理和快照。HLFS性能较低。首先,非原地更新必然导致数据块在物理上非连续存放,因此读I/O比较随机,顺序读性能下降。其次,虽然从单个文件角度看来,写I/O是顺序的,但是在HDFS的ChunkServer服务了多个HLFS文件,因此从它的角度来看,I/O仍然是随机的。第三,写延迟问题,HDFS面向大文件设计,小文件写延时不够优化。第四,垃圾回收的影响,垃圾回收需要读取和写入大量数据,对正常写操作造成较大影响。此外,按照目前实现,相同段上的垃圾回收和读写请求不能并发,垃圾回收算法对正常操作的干扰较大。2.6iSCSI、FCoE、AoE、NBDiSCSI、FCoE、AoE、NBD等都是用来支持通过网络访问块设备的协议,它们都采用C/S架构,无法直接支持分布式块存储系统。3.Ursa的设计与实现分布式块存储系统给虚拟机提供的是虚拟硬盘服务,因而有如下设计目标:大文件存储:虚拟硬盘实际通常GB级别以上,小于1GB是罕见情况需要支持随机读写访问,不需支持追加写,需要支持resize通常情况下,文件由一个进程独占读写访问;数据块可被共享只读访问高可靠,高可用:任意两个服务器同时出现故障不影响数据的可靠性和可用性能发挥出新型硬件的性能优势,如万兆网络、SSD由于应用需求未知,同时需要优化吞吐率和IOPS高效率:降低资源消耗,就降低了成本除了上述源于虚拟硬盘的直接需求意外,分布式块存储还需要支持下列功能:快照:可给一个文件在不同时刻建立多个独立的快照克隆:可将一个文件或快照在逻辑上复制成独立的多份精简配置(thin-provisioning):只有存储数据的部分才真正占用空间3.1系统架构分布式存储系统总体架构可以分为有master(元数据服务器)和无master两大类。有master架构在技术上较为简单清晰,但存在单点失效以及潜在的性能瓶颈问题;无master架构可以消除单点失效和性能瓶颈问题,然而在技术上却较为复杂,并且在数据布局方面具有较多局限性。块存储系统对master的压力不大,同时master的单点故障问题可采用一些现有成熟技术解决,因而美团EBS的总体架构使用有master的类型。这一架构与GFS、HDFS、MooseFS等系统的架构属于同一类型。如图1所示,美团EBS系统包括M、S和C三个部分,分别代表Master、ChunkServer和Client。Master中记录的元数据包括3种:(1)关于volume的信息,如类型、大小、创建时间、包含哪些数据chunk等等;(2)关于chunk的信息,如大小、创建时间、所在位置等;(3)关于ChunkServer的信息,如IP地址、端口、数据存储量、I/O负载、空间剩余量等。这3种信息当中,关于volume的信息是持久化保存的,其余两种均为暂存信息,通过ChunkServer上报。在元数据中,关于volume的信息非常重要,必须持久化保存;关于chunk的信息和ChunkServer的信息是时变的,并且是由ChunkServer上报的,因而没必要持久化保存。根据这样的分析,我们将关于volume的信息保存在MySQL当中,其他元数据保存在Redis当中,余下的集群管理功能由Manager完成。Master==Manager+MySQL+Redis,其中MySQL使用双机主从配置,Redis使用官方提供的标准cluster功能。3.2CAP取舍C、A、P分别代表Consistency、Availability和Partition-tolerance。分布式系统很难同时在这三个方面做到很高的保障,通常要在仔细分析应用需求的基础之上对CAP做出取舍。块存储系统主要用于提供云硬盘服务,每块云硬盘通常只会挂载到1台VM之上,不存在多机器并发读写的情况,因而其典型应用场景对一致性的需求较低。针对这一特性,我们可以在设计上舍C而取AP。对于多机并行访问云硬盘的使用模式,若数据是只读的则无需额外处理;若数据有写有读,甚至是多写多读,则需要在上层引入分布式锁,来确保数据一致性和完整性。这种使用模式在SAN领域并不少见,其典型应用场景是多机同时挂载一个网络硬盘,并通过集群文件系统(而不是常见的单机文件系统)来协调访问存储空间。集群文件系统内部会使用分布式锁来确保数据操作的正确性,所以我们舍C的设计决策不会影响多机并行访问的使用模式。3.3并发模型并发(不是并行!)模型的选择和设计无法作为实现细节隐藏在局部,它会影响到程序代码的各个部分,从底层到上层。基本的并发模型只有这样几种:事件驱动、多线程、多进程以及较为小众的多协程。事件驱动模型是一种更接近硬件工作模式的并发模型,具有更高的执行效率,是高性能网络服务的普遍选择。为能充分发挥万兆网络和SSD的性能潜力,我们必须利用多核心并行服务,因而需要选用多线程或者多进程模型。由于多进程模型更加简单,进程天然是故障传播的屏障,这两方面都十分有利于提高软件的健壮性;并且我们也很容易对业务进行横向拆分,做到互相没有依赖,也不需要交互,所以我们选择了多进程模型,与事件驱动一起构成混合模型。协程在现实中的应用并不多,很多语言/开发生态甚至不支持协程,然而协程在一些特定领域其实具有更好的适用性。比如,QEMU/KVM在磁盘I/O方面的并发执行完全是由协程负责的,即便某些blockdriver只提供了事件驱动的接口(如CephRBD),QEMU/KVM也会自动把它们转化封装成多协程模式。实践表明,在并发I/O领域,多协程模型可以同时在性能和易用性方面取得非常好的效果,所以我们做了跟QEMU/KVM类似的选择——在底层将事件驱动模型转换成了多协程模型,最终形成了“多进程+多协程+事件驱动”的混合并发模型。3.4存储结构如图所示,Ursa中的存储结构与GFS/HDFS相似,存储卷由64MB(可配置)大小的chunk组成。Ursa系统中的数据复制、故障检测与修复均在chunk层次进行。系统中,每3个(可配置)chunk组成一组,互为备份。每2个chunk组构成一个stripe组,实现条带化交错读写,提高单客户端顺序读写性能。Ursa在I/O栈上层添加Cache模块,可将最常用的数据缓存在客户端本地的SSD介质当中,当访问命中缓存时可大大提高性能。3.5写入策略最常见的写入策略有两种:(1)客户端直接写多个副本到各个ChunkServer,如图(a)所示,Sheepdog采用此种办法;(2)客户端写第一个副本,并将写请求依次传递下去,如图(b)所示。这两种方法各有利弊:前者通常具有较小的写入延迟,但吞吐率最高只能达到网络带宽的1/3;后者的吞吐率可以达到100%网络带宽,却具有较高的写入延迟。由于Ursa可能用于支持各种类型的应用,必须同时面向吞吐率和带宽进行优化,所以我们设计采用了一种分叉式的写入策略:如图(c)所示,客户端使用WRITE_REPLICATE请求求将数据写到第一个副本,称为primary,然后由primary负责将数据分别写到其他副本。这样Ursa可以在吞吐率和延迟两方面取得较好的均衡。为确保数据可靠性,写操作会等所有副本的写操作都完成之后才能返回。3.6无状态服务ChunkServer内部几乎不保存状态,通常情况下各个请求之间是完全独立执行的,并且重启ChunkServer不会影响后续请求的执行。这样的ChunkServer不但具有更高的鲁棒性,而且具有更高的扩展性。许多其他网络服务、协议的设计都遵循了无状态的原则。3.7模块如下图所示,Ursa中的I/O功能模块的组织采用decorator模式,即所有模块都实现了IStore抽象接口,其中负责直接与ChunkServer通信的模块属于decorator模式中的concretecomponent,其余模块均为concretedecorator。所有的decorator都保存数量不等的指向其他模块的指针(IStore指针)。在运行时,Ursa的I/O栈层次结构的对象图如下所示。3.8产品界面4.性能实测如下图所示,测试环境由万兆以太网、1台Client和3台ChunkServer组成,chunk文件存在tmpfs上,即所有写操作不落盘,写到内存为止。选择tmpfs主要是为了避免硬盘的I/O速度的局限性,以便测试Ursa在极限情况下的表现。测试环境的网络延迟如下:在上述环境中,用fio分别测试了读写操作的吞吐率、IOPS以及I/O延迟,测试参数与结果如下:从测试结果可以看出:(1).Ursa在吞吐率测试中可以轻易接近网卡理论带宽;(2).Ursa的IOPS性能可以达到SSD的水准;(3).Ursa的读延迟接近ping值,写操作需要写3个副本,延迟比读高68%。作为对比,我们在测试Ceph的过程中监测到服务端CPU占用情况如下:此时机器上5个存储服务进程ceph-osd共占用123.7%的CPU资源,提供了4101的读IOPS服务;而Ursa的服务进程只消耗了43%的CPU资源,提供了61340读IOPS服务,运行效率比Ceph高43倍。在客户端方面,Ceph消耗了500%+的CPU资源,得到了16407读IOPS;而Ursa只消耗了96%的CPU资源,得到了61340读IOPS,运行效率比Ceph高21倍。总结与展望Ursa从零开始动手开发到内部上线只经历了9个月的时间,虽然基本功能、性能都已达到预期,但仍有许多需要进一步开发的地方。一个重要的方向是对SSD的支持。虽然将HDD简单替换为SSD,不修改Ursa的任何代码、配置就可以运行,并取得性能上的显著改善,然而SSD在性能、成本、寿命等方面与HDD差异巨大,Ursa必须做出针对性的优化才能使SSD扬长避短。另一个重要方向是对大量VM同时启动的更好的支持。如果同时有上百台相同的VM从Ursa启动(即系统盘放在Ursa上),会在短时间内有大量读请求访问相同的数据集(启动文件),形成局部热点,此时相关的ChunkServer服务能力会出现不足,导致启动变慢。由于各个VM所需的启动数据基本相同,我们可以采用“一传十,十传百”的方式组织一个应用层组播树overlay网络来进行数据分发,这样可以从容应对热点数据访问问题。随着一步步的完善,相信Ursa将在云平台的运营当中起到越来越重要的作用。
许多淘宝的店家每天都需要查找大量的关键词排名,帮助自己更好的选择一些关键词,但是数量多了查询起来就很麻烦,今天就来为大家分享一下淘宝关键词排名怎么批量查询,帮助大家节省更多的时间。1.登录淘宝直通车,最先你的账户要有淘宝直通车管理权限2.能够大批量检索关键词,例如你另外检索“休闲男装”、“品牌女装”可是必须自动换行键入。3.能够根据删掉词汇表,筛选不用的关键词,例如你如今做的事休闲男装,关键词有女的,对你毫无疑问不起作用的,那麼在删掉词汇表键入,随后筛选就可以,能够好几个大批量筛选,自动换行切分。4.能够去重复关键词。5.筛选好的关键词能够导出数据,在报表中剖析改动。筛选方法:1.商城点击占有率商城点击占有率指的是在选定的终端设备(PC或无线网络)上,当客户检索关键词后出現的百度搜索中,点击天猫店商品的频次/点击全部(天猫店+淘宝网店)商品的频次。那麼假如你是一个淘宝网店,你是不是必须去挑选商城点击占有率低的词呢?很显著,是的,这就是市场需求。2.线上商品数线上商品数:获得当今淘宝网主搜商品包括总体目标关键词的线上商品数。根据参照这一数据信息大家能看得出商品在销售市场中的市场竞争尺寸。同样大家也应当挑选线上商品数少的词。3.检索人气值统计分析时间内,依据检索总数线性拟合出的指数值类指标值。搜索量越高,表明检索总数越多。检索人气值越多,证实他的市场的需求就越高。4.商品的深入了解。要想提升一个好的标题,最先要把自己的商品掌握深入,从知名品牌到特性再到作用这些,那样大家才可以找寻更合适,更配对自身的商品的关键词!
这里示范如何使用GoogleDFP来刊登广告,突破AdSense最多只能放三个广告的限制。许多的网站都会放置一些广告,透过广告收益来维持网站的运作,甚至用这样的模式把网站当作一个事业来经营,而Google的AdSense是目前最热门的网络广告商,一般网站上的广告大多数都是藉由AdSense来刊登的。AdSense的广告刊登政策中明确规定了各种广告刊登数量限制,一个网页中最多只能放置三个广告单元、三个连结单元和两个搜寻框,一般的网站最主要都会使用大面积的广告单元,正常来说三个广告是足够的,但是对于某些内容特别丰富的网站而言,一个页面非常的长,其实放置超过三个广告也不会对读者有太大的影响,但受限于AdSense的规定,最后也是无可奈何。后来Google花了31亿买下了DoubleClick,推出了DFP这个广告管理系统,使用者可以透过DFP刊登与管理自己的广告,或是播放AdSense或是其他联播网的广告,而在选择播放的广告时,DFP会让GoogleAdSense与其他广告联播网竞争以提高发布者的收益,也就是说DFP会挑选收益最好的广告优先播放,理论上这样会比一般直接放AdSense广告更好。因为AdSense的广告数量在计算时是跟DFP分开的,所以我们可以使用AdSense放三个广告单元,剩下的部分就用DFP,许多网站就是以这样的方式播放三个以上的大面积广告单元,当然您必须仔细衡量自己的网页内容与排版是否适合放置那么多的广告,过多的广告容易让整个版面杂乱无章,这一点是在放置广告之前要审慎考虑的。不过DFP只负责放送广告,不负责付款的动作,所有的款项都是由广告客户或广告联播网(如AdSense)直接付款。以下是使用DFP服务在网站上放置广告的流程。STEP1若要在自己的网站上刊登广告,首先在DFP的「广告空间」中,选择「新增广告单元」。STEP2输入广告相关信息,「程序码」的部分就自己用英文取一个容易辨识的代码即可,剩下的栏位大概大家都看得懂,我就不解释了。STEP3在AdSense广告空间设定的部分,记得要启用,或是勾选「利用AdSense尽量提高未售出及剩余广告空间的收益」,这样就可以让DFP播放AdSense的广告。STEP4新增完广告单元之后,再新增一个刊登位置,点选「新增刊登位置」。刊登位置的意义其实就跟AdSense的频道一样,让广告业主可以知道广告的刊登位置。STEP5填写刊登位置的基本资料,并选择这个位置所包含的广告单元。STEP6填写AdWords用的信息,这里要填写的资料跟AdSense的频道几乎一样,反正按照您的广告所放置的位置填写即可。填完则按下储存。STEP7开启刚刚上面新增的广告单元,点选右上方的「产生广告代码」。STEP8选择「Google发布商广告代码」。STEP9调整代码选项,如果不清楚这些是做什么用的,其实用预设值就可以了。STEP10将产生的HTML程序码贴在自己的网页中。 vargoogletag=googletag||{};googletag.cmd=googletag.cmd||[];(function(){vargads=document.createElement('script');gads.async=true;gads.type='text/javascript';varuseSSL='https:'==document.location.protocol;gads.src=(useSSL?'https:':'http:')+'//www.googletagservices.com/tag/js/gpt.js';varnode=document.getElementsByTagName('script')[0];node.parentNode.insertBefore(gads,node);})(); googletag.cmd.push(function(){googletag.defineSlot('/54009424/gtwang-post-bottom-1',[336,280],'div-gpt-ad-1432171343962-0').addService(googletag.pubads());googletag.pubads().enableSingleRequest();googletag.enableServices();}); 这所产生的HTML程序码有两段,第一段是放在与之间: var googletag = googletag || {}; googletag.cmd = googletag.cmd || []; (function() { var gads = document.createElement('script'); gads.async = true; gads.type = 'text/javascript'; var useSSL = 'https:' == document.location.protocol; gads.src = (useSSL ? 'https:' : 'http:') + '//www.googletagservices.com/tag/js/gpt.js'; var node = document.getElementsByTagName('script')[0]; node.parentNode.insertBefore(gads, node); })(); googletag.cmd.push(function() { googletag.defineSlot('/54009424/gtwang-post-bottom-1', [336, 280], 'div-gpt-ad-1432171343962-0').addService(googletag.pubads()); googletag.pubads().enableSingleRequest(); googletag.enableServices(); }); 而第二段则是放在要显示广告的位置:googletag.cmd.push(function(){googletag.display('div-gpt-ad-1432171343962-0');}); googletag.cmd.push(function() { googletag.display('div-gpt-ad-1432171343962-0'); }); 现在cnblogs还是使用这个方法的 var googletag = googletag || {}; googletag.cmd = googletag.cmd || []; googletag.cmd.push(function () { googletag.defineSlot('/1090369/A1', [468, 60], 'div-gpt-ad-1547816814884-0').addService(googletag.pubads()); googletag.defineSlot('/1090369/B1', [300, 250], 'div-gpt-ad-1546331539224-0').addService(googletag.pubads()); googletag.defineSlot('/1090369/B2', [300, 250], 'div-gpt-ad-1539007469525-0').addService(googletag.pubads()); googletag.defineSlot('/1090369/B3', [300, 250], 'div-gpt-ad-1546331252242-0').addService(googletag.pubads()); googletag.defineSlot('/1090369/B4', [300, 250], 'div-gpt-ad-1546331385104-0').addService(googletag.pubads()); googletag.pubads().enableSingleRequest(); googletag.enableServices(); }); /**/ 显示 googletag.cmd.push(function () { googletag.display('div-gpt-ad-1547816814884-0'); }); googletag.cmd.push(function () { googletag.display('div-gpt-ad-1546331539224-0'); }); cnblogs是页面最后加载的。将HTML程序码贴好之后就完成了,不过通常刚刚新增的广告单元放上网页时,并不会马上显示出来,我是大约等了好几分钟之后,才看到广告正常出现在网页上。使用经验总结不得不说,Google的DFP广告管理系统是个很牛逼的产品,对于需要进行站内广告管理的网站主来说,这是一件得心应手的武器。多种广告模式设置,再配合Adsense广告联盟,使得站内的广告位置得到最佳的利用,还有广告客户管理,提供广告数据给客户查看等。不管是管理多个网站,还是只有一个网站,网站主们都不应该错过这个工具。虽然DFP是一个非常强大的广告管理工具,但新手刚接触这个系统时,操作逻辑上会存在一些绕弯(也许是我理解能力有差异),所以说一说我之前在DFP广告管理系统标准版上的操作错误以及经验。1、可用广告资源不足新建的广告订单时,可能会提示“可用广告资源不足”的提示,但明明是可以确定有空置的广告位的。其实这个并非真正的可用广告资源不足,而是DFP的一个问题,不知是BUG还是特意为之的,新订单在刚添加的时候基本都会提示这个,这个时候就要勾选“超量预订此订单项”,保存就可以成功了。据说这个提示在订单刚添加好的前几天,如果检查广告资源的时候都会提示这个,大概过七天之前就会提示正常。2、广告单元与展示位置比如说同一个侧边栏有两个相同尺寸的广告位置,那么新建一个”Sidebar”的展示位置,然后在建两个”Sidebar-Top”、”Sidebar-Bottom”的广告单元,这两个广告单元属于这一个展示位置。似乎这样的描述是正常的逻辑行为,但这样做的结果就是,两个不同广告单元里的广告会互串,无法固定A广告显示在”Sidebar-Top”,而B广告显示在”Sidebar-Bottom”,展示位置才是唯一固定的地方。也就是说展示位置不能往大了写,如果要固定某个广告的显示位置的话,只能建”Sidebar-Top”跟”Sidebar-Bottom”两个展示位置。广告单元与展示位置是两个相对的属性,一个广告单元可以从属于几个展示位置,一个展示位置也可以包含几个广告单元。3、生成广告代码广告要在页面里显示,就需要在页面里植入广告代码,每个广告单元都是单独的代码。代码分为两段,一段在标签里,另一段则是在具体的广告位置所在。但与Adsense的广告代码里ID是固定不同的是,DFP的广告单元代码,每点一次“生成代码”,代码里的ID数值都会变化,所以两段广告代码一定要在同时植入到页面代码里。如果第一次生成的代码里只复制了部分,第二次生成再复制具体位置的代码,那么就会造成两次广告代码里的ID不一样。4、订单状态新添加的订单并非实时生效的,添加完新订单项后还需要审核才能生效,即使页面里已经显示出广告内容了,订单里的状态可能还需要一点时间才能正常显示“正在投放”。5、广告类型如果是按时间买断的广告位置,广告类型一定要选择“赞助”,才能在目标那里设置100%展示。6、报告报告不像AdSense的效果报告那样,每天自动生成,DFP里的报告需要手动生成才能显示。7、关于展示次数这一点,到现在我也还疑惑着。DFP的广告展示次数似乎并不是由具体的展示位置那里的代码来统计的,而是由添加到标签里的那段代码来统计的,这也就意味着如果在首页跟内容页各添加一个展示位置,这两个展示位置里各有一个类型为“赞助”的广告内容,那么这两个广告内容的展示次数将是完全一样的。显然,首页跟内容页的PV值是不太可能完成一样的。
前言一位计算机前辈曾说过:Controllingcomplexityistheessenceofcomputerprogramming.随着前端开发复杂度的日益提升,组件化开发应运而生,并随着FIS、React等优秀框架的出现遍地开花。这一过程同样发生在美团,面临业务规模的快速发展和工程师团队的不断扩张,美团历经引入组件化解决资源整合问题、逐步增强组件功能促进开发效率、重新打造新一代组件化方案适应全栈开发和共享共建等阶段,努力“controllingcomplexity”。本文将介绍美团组件化开发的实践过程。组件化1.0:资源重组在美团早期,前端资源是按照页面或者类似业务页面集合的形式进行组织的。例如order.js对应订单相关页面的交互,account.css对应账户相关页面的样式。这种方式在过去的较长一段时间内,持续支撑了整个项目的正常推进,功勋卓著。随着业务规模的增加和开发团队的扩张,这套机制逐渐显示出它的一些不足:1.资源冗余页面的逐渐增加,交互的逐渐复杂化,导致对应的css和js都有大幅度增长,进而出现为了依赖某个js中的一个函数,需要加载整个模块,或者为了使用某个css中的部分样式依赖整个css,冗余资源较多2.对应关系不直观没有显而易见的对应规则,导致的一个问题是修改某个业务模块的css或者js时,几乎只能依靠grep。靠人来维护页面模块html、css和js之间的依赖关系,容易犯错,常常出现内容已经删除但是css或js还存在的问题。3.难于单元测试以页面为最小粒度进行资源整合,不同功能的业务模块相互影响,复杂度太高,自动化测试难以推进。2013年开始,在调研了FIS、BEM等方案之后,结合美团开发框架的实际,美团初步实现了一套轻量级的组件化开发方案。主要的改进是:1.以页面功能组件为单位聚合前端资源2.自动加载符合约定的css、js资源3.将业务数据到渲染数据的转换过程独立出来举例来说,美团顶部的搜索框就被实现为一个组件。代码构成: 复制代码代码如下:www/component/smart-box/├──smart-box.js#交互├──smart-box.php#渲染数据生产、组件配置├──smart-box.scss#样式├──smart-box.tpl#内容└──test├──default.js#自动化测试└──default.php#调用组件变得十足简单:JavaScriptCode复制内容到剪贴板echo View::useComponent('smart-box', [ 'keyword' => $keyword ]); 对比之前,可以看到组件化的一些特点:1.按需加载只加载必要的前端资源2.对应关系非常清晰组件所需要的前端资源都在同一目录,职责明确且唯一,对应关系显著3.易于测试组件是具备独立展现和交互的最小单元,可利用Phantom等工具自动化测试此外,由于前端资源集中进行调度,组件化也为高阶性能优化提供了空间。例如实现组件级别的BigRender、通过数据分析进行资源的合并加载等等。组件化2.0:趋于成熟组件化1.0上线后,由于简单易用,很快得到工程师的认可,并开始在各项业务中应用起来。新的需求接踵而来,一直持续到2014年底,这个阶段美团称之为组件化2.0。下面介绍下主要的几个改进。Lifecycle组件在高内聚的同时,往往需要暴露一些接口供外界调用,从而能够适应复杂的页面需求,例如提交订单页面需要在支付密码组件启动完成后绑定提交时的检查。WebComponents、React等都选择了生命周期事件/方法,美团也是一样。组件的生命周期:一个组件的完整生命周期包括:1.init,初始化组件根节点和配置2.fetch,加载css和js资源3.render,内容渲染,默认的渲染内容方式是BigRender4.ready,进行数据绑定等操作5.update,数据更新6.destroy,解除所有事件监听,删除所有组件节点组件提供pause、resume方法以方便进行生命周期控制。各个阶段使用Promise串行进行,异步的管理更清晰。使用自定义语义事件,在修改默认行为、组件间通信上充分利用了YUI强大的自定义事件体系,有效降低了开发维护成本。举个例子,页面初始化时组件的启动过程实际也是借助生命周期实现的:JavaScriptCode复制内容到剪贴板var afterLoadList = []; Y.all('[data-component]').each(function (node) { var component = new Y.mt.Component(node); // 绑定 init 生命周期事件,在 init 默认行为完成后执行回调 component.after('init', function (e) { // 如果配置了延迟启动 if (e.config.afterLoad) { // 暂停组件生命周期 e.component.pause(); // 压入延迟启动数组 afterLoadList.push(e.component); } }); // 开始进入生命周期 component.start(); }); Y.on('load', function () { // 在页面 load 事件发生时恢复组件生命周期 afterLoadList.forEach(function (component) { component.resume(); }); }); 回过头来看,引入生命周期除了带来扩展性外,更重要的是理顺了组件的各个阶段,有助于更好的理解和运用。DataBinding数据绑定是美团期盼已久的功能,将View和ViewModel之间的交互自动化无疑会节省工程师的大量时间。在组件化减少关注点和降低复杂度后,实现数据绑定变得更加可能。美团最终实现的数据绑定方案主要参考了Angular,通过在html节点上添加特定的属性声明绑定逻辑,js扫描这些内容并进行相应的渲染和事件绑定。当数据发生变化时,对应的内容全部重新渲染。JavaScriptCode复制内容到剪贴板 Y.use(['mt-bind', 'mt-scope'], function () { Y.mt.bind.init(document.body); var scope = Y.one('.addressList').getScope(); // 将 scope.addrList 设置为一个数组,DOM 上将自动渲染其内容 scope.$set('addrList', [ { text: "first address" }, { text: "second address" } ]); }); 使用属性声明绑定逻辑的好处是可以同时支持后端渲染,这对于美团团购这样的偏展现型业务是非常必要的,用户可以很快看到页面内容。Flux实现数据绑定后,美团不得不面对另外一个问题:如何协同多个组件间的数据。因为某个组件的数据变化,很有可能引起其他组件的变化。例如当修改购买数量,总金额会变化,而总金额超过500后,还需要展示大额消费提醒。为了解决这个问题,美团引入了Flux,使用全局消息总线的思路进行跨组件交互。例如因为交互复杂而一直让美团非常头疼的项目购买页,在应用组件+Flux重构后,各模块之间的互动更加清晰:其他方面的改进还有很多,包括引入模板引擎LightnCandy约束模板逻辑、支持组件任意嵌套、支持异步加载并自动初始化等。随着组件化2.0的逐步完善,基本已经可以从容应对日常开发,在效率和质量方面都上了一个台阶。组件化3.0:重启征程时间的车轮滚滚前行,2014年底,美团遇到一些新的机遇和挑战:基于Node的全栈开发模式开始应用,前后端渲染有了更多的可能性YUI停止维护,需要一套新的资源管理方案新业务不断增加,需要找到一种组件共享的方式,避免重复造轮子结合之前的实践,以及在这一过程中逐渐积累的对业内方案的认知,美团提出了新的组件化方案:基于React开发页面组件,使用NPM进行分发,方便共建共享基于Browserify二次开发,建设资源打包工具Reduce,方便浏览器加载建设适应组件化开发模式的工程化开发方案Turbo,方便工程师将组件应用于业务开发中React在组件化2.0的过程中,美团发现很多功能和React重合,例如DataBinding、Lifecycle、前后端渲染,甚至直接借鉴的Flux。除此之外,React的函数式编程思想、增量更新、兼容性良好的事件体系也让美团非常向往。借着前端全栈开发的契机,美团开始考虑基于React进行组件化3.0的建设。NPM+ReduceNPM+Reduce构成了美团新的资源管理方案,其中:NPM负责组件的发布和安装。可以认为是“分”的过程,粒度越小,重用的可能性越大Reduce负责将页面资源进行打包。可以认为是“合”的过程,让浏览器更快地加载一个典型的组件包: 复制代码代码如下:smart-box/├──package.json#组件包元信息├──smart-box.jsx#ReactComponent├──smart-box.scss#样式└──test└──main.js#测试NPM默认只支持js文件的管理,美团对NPM中的package.json进行了扩展,增加了style字段,以使打包工具Reduce也能够对css和css中引用的image、font进行识别和处理:JavaScriptCode复制内容到剪贴板{ "style": "./smart-box.scss" } 只要在页面中require了smart-box,经过Reduce打包后,js、css甚至图片、字体,都会出现在浏览器中。JavaScriptCode复制内容到剪贴板var SmartBox = require('@mtfe/smart-box'); // 页面 var IndexPage = React.createClass({ render: function () { return ( ... ); } }); module.exports = IndexPage; 整体思路和组件化1.0如出一辙,却又那么不同。Turbo单单解决分发和打包的问题还不够,业务开发过程如果变得繁琐、难以Debug、性能低下的话,恐怕不会受到工程师欢迎。为了解决这些问题,美团在Node框架的基础上,提供了一系列中间件和开发工具,逐步构建对组件友好的前端工程化方案Turbo。主要有:1.支持前后端同构渲染,让用户更早看到内容2.简化Flux流程,数据流更加清晰易维护3.引入ImmutableJS,保证Store以外的数据不可变4.采用cursor机制,保证数据修改/获取同步5.支持HotModuleReplacement,改进开发流自动化6.通过这些改进,一线工程师可以方便的使用各种组件,专注在业务本身上。开发框架层面的支持也反过来促进了组件化的发展,大家更乐于使用一系列组件来构建页面功能。小结发现痛点、分析调研、应用改进的解决问题思路在组件化开发实践中不断运用。历经三个大版本的演进,组件化开发模式有效缓解了业务发展带来的复杂度提升的压力,并培养工程师具备小而美的工程思想,形成共建共享的良好氛围。毫无疑问,组件化这种“分而治之”的思想将会长久地影响和促进前端开发模式。美团现在已经准备好,迎接新的机遇和挑战,用技术的不断革新提升工程师的幸福感。
一、线上篇随着业务的发展,美团的商家和团购数正在飞速增长。这一背景下,搜索排序的重要性显得更加突出:排序的优化能帮助用户更便捷地找到满足其需求的商家和团购,改进用户体验,提升转化效果。和传统网页搜索问题相比,美团的搜索排序有自身的特点——90%的交易发生在移动端。一方面,这对排序的个性化提出了更高的要求,例如在“火锅”查询下,北京五道口的火锅店A,对在五道口的用户U1来说是好的结果,对在望京的用户U2来讲不一定是好的结果;另一方面,我们由此积累了用户在客户端上丰富准确的行为,经分析获得用户的地理位置、品类和价格等偏好,进而指导个性化排序。针对美团的O2O业务特点,我们实现了一套搜索排序技术方案,相比规则排序有百分之几十的提升。基于这一方案,我们又抽象了一套通用的O2O排序解决方案,只需1-2天就可以快速地部署到其他产品和子行业中,目前在热词、Suggestion、酒店、KTV等多个产品和子行业中应用。我们将按线上和线下两部分分别介绍这一通用O2O排序解决方案,本文是线上篇,主要介绍在线服务框架、特征加载、在线预估等模块,下篇将会着重介绍离线流程。排序系统为了快速有效的进行搜索算法的迭代,排序系统设计上支持灵活的A/B测试,满足准确效果追踪的需求。美团搜索排序系统如上图所示,主要包括离线数据处理、线上服务和在线数据处理三个模块。离线数据处理HDFS/Hive上存储了搜索展示、点击、下单和支付等日志。离线数据流程按天调度多个MapReduce任务分析日志,相关任务包括:离线特征挖掘产出Deal(团购单)/POI(商家)、用户和Query等维度的特征供排序模型使用。数据清洗标注&模型训练数据清洗去掉爬虫、作弊等引入的脏数据;清洗完的数据经过标注后用作模型训练。效果报表生成统计生成算法效果指标,指导排序改进。特征监控特征作为排序模型的输入是排序系统的基础。特征的错误异常变动会直接影响排序的效果。特征监控主要监控特征覆盖率和取值分布,帮我们及时发现相关问题。在线数据处理和离线流程相对应,在线流程通过Storm/SparkStreaming等工具对实时日志流进行分析处理,产出实时特征、实时报表和监控数据,更新在线排序模型。在线服务(RankService)RankService接到搜索请求后,会调用召回服务获取候选POI/Deal集合,根据A/B测试配置为用户分配排序策略/模型,应用策略/模型对候选集合进行排序。下图是RankService内部的排序流程。L1粗粒度排序(快速)使用较少的特征、简单的模型或规则对候选集进行粗粒度排序。L2细粒度排序(较慢)对L1排序结果的前N个进行细粒度排序。这一层会从特征库加载特征(通过FeatureLoader),应用模型(A/B测试配置分配)进行排序。L3业务规则干预在L2排序的基础上,应用业务规则/人工干预对排序进行适当调整。RankService会将展示日志记录到日志收集系统,供在线/离线处理。A/B测试A/B测试的流量切分是在RankServer端完成的。我们根据UUID(用户标识)将流量切分为多个桶(Bucket),每个桶对应一种排序策略,桶内流量将使用相应的策略进行排序。使用UUID进行流量切分,是为了保证用户体验的一致性。下面是A/B测试配置的一个简单示例。 复制代码代码如下:{"search":{"NumberOfBuckets":100,"DefaultStrategy":"Base","Segments":[{"BeginBucket":0,"EndBucket":24,"WhiteList":[123],"Strategy":"Algo-1"},{"BeginBucket":25,"EndBucket":49,"WhiteList":[],"Strategy":"Algo-2"}]}}对于不合法的UUID,每次请求会随机分配一个桶,以保证效果对比不受影响。白名单(WhiteList)机制能保证配置用户使用给定的策略,以辅助相关的测试。除了A/B测试之外,我们还应用了Interleaving[7]方法,用于比较两种排序算法。相较于A/B测试,Interleaving方法对排序算法更灵敏,能通过更少的样本来比较两种排序算法之间的优劣。Interleaving方法使用较小流量帮助我们快速淘汰较差算法,提高策略迭代效率。特征加载搜索排序服务涉及多种类型的特征,特征获取和计算是RankService响应速度的瓶颈。我们设计了FeatureLoader模块,根据特征依赖关系,并行地获取和计算特征,有效地减少了特征加载时间。实际业务中,并行特征加载平均响应时间比串行特征加载快约20毫秒。FeatureLoader的实现中我们使用了Akka[8]。如上图所示,特征获取和计算的被抽象和封装为了若干个Akkaactor,由Akka调度、并行执行。特征和模型美团从2013年9月开始在搜索排序上应用机器学习方法(LearningtoRank),并且取得很大的收益。这得益于准确的数据标注:用户的点击下单支付等行为能有效地反映其偏好。通过在特征挖掘和模型优化两方面的工作,我们不断地优化搜索排序。下面将介绍我们在特征使用、数据标注、排序算法、PositionBias处理和冷启动问题缓解等方面的工作。特征从美团业务出发,特征选取着眼于用户、Query、Deal/POI和搜索上下文四个维度。用户维度包括挖掘得到的品类偏好、消费水平和地理位置等。Query维度包括Query长度、历史点击率、转化率和类型(商家词/品类词/地标词)等。Deal/POI维度包括Deal/POI销量、价格、评价、折扣率、品类和历史转化率等。上下文维度包括时间、搜索入口等。此外,有的特征来自于几个维度之间的相互关系:用户对Deal/POI的点击和下单等行为、用户与POI的距离等是决定排序的重要因素;Query和Deal/POI的文本相关性和语义相关性是模型的关键特征。模型LearningtoRank应用中,我们主要采用了Pointwise方法。采用用户的点击、下单和支付等行为来进行正样本的标注。从统计上看,点击、下单和支付等行为分别对应了该样本对用户需求的不同的匹配程度,因此对应的样本会被当做正样本,且赋予不断增大的权重。线上运行着多种不同类型模型,主要包括:Gradientboostingdecision/regressiontree(GBDT/GBRT)GBDT是LTR中应用较多的非线性模型。我们开发了基于Spark的GBDT工具,树拟合梯度的时候运用了并行方法,缩短训练时间。GBDT的树被设计为三叉树,作为一种处理特征缺失的方法。选择不同的损失函数,boostingtree方法可以处理回归问题和分类问题。应用中,我们选用了效果更好的logisticlikelihoodloss,将问题建模为二分类问题。LogisticRegression(LR)参考Facebook的paper[3],我们利用GBDT进行部分LR特征的构建。用FTRL算法来在线训练LR模型。对模型的评估分为离线和线上两部分。离线部分我们通过AUC(AreaUndertheROCCurve)和MAP(MeanAveragePrecision)来评价模型,线上则通过A/B测试来检验模型的实际效果,两项手段支撑着算法不断的迭代优化。冷启动在我们的搜索排序系统中,冷启动问题表现为当新的商家、新的团购单录入或新的用户使用美团时,我们没有足够的数据用来推测用户对产品的喜好。商家冷启动是主要问题,我们通过两方面手段来进行缓解。一方面,在模型中引入了文本相关性、品类相似度、距离和品类属性等特征,确保在没有足够展示和反馈的前提下能较为准确地预测;另一方面,我们引入了Explore&Exploit机制,对新商家和团单给予适度的曝光机会,以收集反馈数据并改善预测。PositionBias在手机端,搜索结果的展现形式是列表页,结果的展示位置会对用户行为产生很大的影响。在特征挖掘和训练数据标注当中,我们考虑了展示位置因素引入的偏差。例如CTR(click-through-rate)的统计中,我们基于ExaminationModel,去除展示位置带来的影响。线上篇总结线上篇主要介绍了美团搜索排序系统线上部分的结构、算法和主要模块。在后续文章里,我们会着重介绍排序系统离线部分的工作。一个完善的线上线下系统是排序优化得以持续进行的基础。基于业务对数据和模型上的不断挖掘是排序持续改善的动力。我们仍在探索。二、线下篇针对美团90%的交易发生在移动端的业务特点,我们实现了一套适用于O2O业务的搜索排序技术方案,已在许多产品和子行业中得到应用。在之前的线上篇中,我们已经介绍了服务的框架、排序算法等。本文为线下篇,主要讲述数据清洗、特征矩阵、监控系统、模型训练和效果评估等模块。数据清洗数据清洗的主要工作是为离线模型训练准备标注数据,同时洗掉不合法数据。数据清洗的数据源主要有团购的曝光、点击和下单。整个数据清洗的流程如下:序列化曝光、点击和下单数据从Hive表中读取,采用schema的处理方式,可以直接根据日志字段名来抽取相应的字段,不受日志字段增加或者减少的影响。曝光日志存储了一次用户行为的详细信息,包括城市、地理位置、筛选条件及一些行为特征;点击日志主要记录了用户点击的POIID、点击时间;下单日志记录了用户下单的POIID、下单时间和下单的金额。数据清洗模块根据配置文件从数据源中抽取需要的字段,进行序列化(Serialization)之后存储在HDFS上。序列化的过程中,如果日志字段不合法或者单一用户曝光、点击或下单超出设定的阈值,相关日志都会被清洗掉,避免数据对模型训练造成影响。数据标注数据序列化之后在HDFS上保存三份文本文件,分别是曝光(Impression)、点击(Click)和下单(Order)。数据标注模块根据globalid(一次搜索的全局唯一标示,类似于sessionid)和相应的团购id为key,将曝光、点击和下单关联起来,最终生成一份标注好是否被点击、下单、支付的标注数据。同时这份标注数据携带了本次展现的详细特征信息。数据标注通过一次Map/Reduce来完成。Map阶段:Map的输入为曝光、点击和下单三种HDFS数据。用三个Mapper分别处理三种日志。数据分发的key为globalid。其中,如果点击和下单数据中的globalid字段为空(""),则丢弃该条日志(因为globalid为空无法和曝光日志join,会出现误标注)。Reduce阶段:Reduce接收的key为globalid,values为具有相同globalid的曝光、点击、下单数据List,遍历该List,如果日志类型为曝光日志,则标记该globalid对应的曝光日志存在(imp_exist=true)。日志类型为点击日志,则将曝光日志的clicked字段置为1。日志类型为下单日志,则将曝光日志的ordered字段置为1。日志类型为下单日志,如果pay_account字段>0,则将曝光日志的paid字段置为1。遍历List之后,如果imp_exist==true,则将标注好的数据写入HDFS,否则丢弃。数据标注的流程图如下:特征矩阵特征矩阵的作用是提供丰富的特征集合,以方便在线和离线特征调研使用。特征矩阵的生成特征矩阵的生成框架为:下面我们来详细说明一下流程。基础特征按来源可分为三部分:1、Hive表:有一些基础特征存储在Hive标注,如POI的名字、品类、团购数等。2、离线计算:一些特征需要积累一段时间才能统计,如POI的点击率、销量等,这部分通过积累历史数据,然后经过Map/Reduce处理得到。3、HDFS:特征矩阵可能融合第三方服务的特征,一般第三方服务将产生的特征按照约定的格式存储在HDFS上。数据源统一格式为:poiid/dealid/bizareaid'\t'name1:value1'\t'name2:value2...特征合并模块,将所有来源合并为一个大文件,通过featureconf配置的特征和特征顺序,将特征序列化,然后写入Hive表。特征监控模块每天监控特征的分布等是否异常。特征矩阵的特征每日更新。添加新的特征来源,只需要按照约定的格式生成数据源,配置路径,可自动添加。添加新特征,在featureconf文件末尾添加相应的特征名,特征名字和数据源中的特征name保持一致,最后修改相应的特征Hive表结构。特征矩阵的使用特征矩阵的使用框架为:我们来详细说明一下流程。其中特征矩阵既提供在线的特征仓库,又可提供离线的特征调研。线上服务需要大量的特征来对POI/DEAL质量打分,特征分散会造成服务取用特征很耗时,特征矩阵将特征整合,很好的解决了特征耗时的问题。一般调研一个新特征需要积累一段时间的数据,将特征放入特征矩阵,然后和已有的数据进行融合,可方便的构造包含新特征的训练数据。下面我们分别来看一下在线、离线和特征融合的流程。在线使用在线方面的使用主要是方便特征的获取,将线上需要的特征纳入特征矩阵统一管理,通过配置文件读取特征矩阵的特征,封装成ProtoBuffers写入Medis(美团自主构建的Redis集群,支持分布式和容错),通过Mediskey批量读取该key对应的特征,减少读取Medis的次数,从而缩减特征获取的时间,提高系统的性能。特征矩阵在线使用框架如下:流程说明:序列化模块通过特征配置文件从特征矩阵抽取需要的特征,调用protoBufferLib将特征封装成protoBuffer的格式,写入Medis。线上通过featureLoader服务从Medis读取数据,然后通过protoBufferLib反序列化数据,取到相应的特征值。离线使用离线方面的使用主要是方便调研新特征。如果从线上获取新特征,由于需要积累训练数据,特征调研的周期会变长;而如果将待调研的特征纳入特征矩阵中,可以很方便地通过离线的方法调研特征的有效性,极大的缩短了特征调研的周期,提高开发效率和模型迭代的速度。特征矩阵离线使用框架如下:其中,从特征矩阵取出待调研的新特征,格式化为joinKey'\t'FeatureName:FeatureValue,例如12345'\t'CTR:0.123,joinkey为poiid,新特征为CTR,特征值为0.123。格式化后的新特征文件和标注好的rerank日志作为输入,经过Map/Reduce处理生成新的标注日志,用于模型训练。特征融合特征融合作用于离线特征调研,上篇我们提到数据标准会输出拥有丰富特征的标注日志,特征融合的目的在于将待调研的新特征通过某一个joinkey合并到在线特征列表中,从而在模型训练中使用该特征。特征融合的框架:流程说明:特征融合模块可以指定任意一个或者多个joinkey,将离线特征加入在线特征列表。监控系统监控系统的目的是确保在线和离线任务的正常运行。监控系统按照作用范围的不同又分为线上监控和离线监控。线上监控线上监控主要是监测收集的在线特征日志是否正常,线上特征监控主要检测特征的覆盖度、阈值范围、分布异常三方面。三方面的监控主要分以下几个场景:覆盖度:监控特征的数据源是否存在或者有数据丢失。阈值范围:监控特征的阈值是否符合预期,防止因为生成特征的算法改变或者在线计算方法的不同等因素造成特征的最大值或者最小值发生比较明显的变化,导致特征不可用。分布异常:监控特征值的分布是否符合预期,主要防止因为获取不到特征,使得特征都使用了默认值,而又没有及时发现,导致线上模型预估出现偏差。分布异常主要用到了卡方距离[3]。特征覆盖度监控效果图:下图是用户到POI距离的覆盖度监控。从图中可以直观的看出,该特征的覆盖度约为75%,也即只有75%的用户能得到距离特征,另外25%可能没有开手机定位服务或者得不到POI的坐标。75%的覆盖度是一个比较稳定的指标,如果覆盖度变的很高或者很低都说明我们的系统出现了问题,而我们的监控系统能及时发现这种问题。离线监控离线监控主要检测两方面:1、离线任务是否按时完成及生成的数据是否正确。2、特征矩阵特征的有效性。当离线定时任务多达数十个的时候,很难每天去逐个检查每个任务是否如期完成,这时候离线任务监控的重要性就凸显出来。当前离线监控可以根据配置文件,监控需要关注的任务,以及这些任务生成的数据是否正常。如果不正常则发出报警给任务负责人,达到任务失败能够及时处理的目的。特征矩阵监控的目的与在线特征的监控目的一样,监控指标也相同,所不同的是因为监控数据的获取不同,监控实现也不尽相同,这里不再赘述。模型调研模型训练模型训练框架支持多种模型的训练,将训练数据格式化为模型需要的输入格式。修改模型训练的配置文件,就可以使用该框架训练模型了。模型训练框架:其中,顶层是训练数据和测试数据的输入层,该层是原始训练和测试数据。中间是模型训练的框架,框架支持多个配置项,包括配置模型算法、相应的参数、数据源的输入及模型的输出等。底层是多种模型的实现,算法之前相互独立,每种算法封装成独立的jar,提供给模型训练框架使用,目前支持的算法包括GBDT[4]、FTRL[5]。为了实现模型的快速迭代,模型训练支持在Spark上运行。效果评估模型的效果评估主要是对比新模型和老模型的效果,以评估结果来决定是否更新线上模型。我们的系统支持两种效果指标的评估,一种是AUC[1],另一种是MAP。MAP(MeanAveragePrecision)[2]是一种对搜索排序结果好坏评估的指标。Prec@K的定义:设定阈值K,计算排序结果topK的相关度。注:绿色表示搜索结果与搜索词相关,红色表示不相关。AP(AveragePrecision)的定义:AveragePrecision=averageofPrec@KAP作为排序好坏的直观理解灰色表示与搜索相关的结果,在团购中表示被点击的DEAL,从召回结果看Ranking#1要好于Ranking#2,反映在MAP指标上,Ranking#1的MAP值大于Ranking#2的MAP值。所以可以简单地使用AP值来衡量模型排序的好坏。MAP的计算对于多个query的搜索结果,MAP为这些搜索结果AP的均值。实验结果表明MAP作为排序指标,对模型好坏的评估起到很好的指导作用。在AUC的近似计算方法中,主要考虑有多少对正负样本组合中正样本的得分大于负样本的得分,与正样本在排序中的具体位置没有绝对的关系。当正负样本的分布变化,如某一小部分正样本得分变大,大部分正样本得分变小,那么最终计算的AUC值可能没有发生变化,但排序的结果却发生了很大变化(大部分用户感兴趣的单子排在了后边)。因此AUC指标没法直观评估人对排序好坏的感受。
今年进入新公司,开始接受公司网站。在对网站进行诊断过程中,发现排名出现了带www和不带www排名进行交替出现的情况。在询问了公司的其他同事之后,发现一个很明显的问题就是公司网站出现www和不带www同事解析的情况。并且没有做过301重定向问题。并且在之前进行链接策略中,重点以www进行外链策略,为什么还会出现这种情况发生。其实,这和网站在优化过程中,没有进行301重定向有关系。 SEOER都知道,网站在优化过程中,首页权重占据第一位,这是因为我们把主要关键词和友情链接以及反链集中到首页的情况。百度在定期更新中,都会出现排名的波动,这种波动还是以关键词排名为主。基于百度算法,把用户体验和权重值高的页面尽可能提前。这种现象主要表现在首页方面,内页由于权重和链接策略方面相比首页要小很多,就导致内页出现波动很小。除非百度一次大的更新,出现内页排名变动。 我们在回过头来,看看出现www和不带www交替排名现象。在搜索引擎眼中,带不带www,其实是网址不同,内容相同的页面。这在我们眼中很容易区分开来,就好比有两张身份证,身份证号码不一样。然而,搜索引擎还是基于链接来判断页面生成。当我们在优化过程中,由于对于网址操作不规范,在百度周期性规律调整中,百度一般还是把权重值高的页面调整到搜索结果的前面。这种网址不规范,就导致在搜索引擎眼中,存在网站两个网址不同的首页面。就很容易解释清楚为什么出现小编开头所说的情况。 如何才能尽可能避免不出现这种情况发生,这就是今天小编要说的问题,其实这种问题还是老调重弹的话题,制作网站301重定向,尽可能把首页权重指定到一个链接上面。例如我们可以通过301重定向把不带www网址定向到带www网址上面,这样就告诉搜索引擎,我们网站只有一个首页,搜索引擎就会把首页权重全部集中到一个网址上面。做到网址规范化,在排名方面和内容方面都对于网站有利。 如何制作网站301 1、基于虚拟主机(vps)和服务器,针对是windou服务器 做网站运营和站长来说,都会有属于自己的独立空间,这样在网站建设中,可以取得对网站所有权限。网站在被黑和改版过程中,都可以自己亲手操作。这种好处就是保证了站长对于主机拥有权。下面我们就说说如何在windou服务器上面制作网站301 1)以虚拟主机为例。远程链接到网站所在主机。步骤:点击网站左下角开始菜单。找到远程桌面链接,属于主机所对于的IP地址和端口号,进入远程链接页面。属于用户名和密码就可以进入到远程服务器。 2)以IIS为例。 *打开internet信息服务管理器, *找到网站,点击属性,找到重定向到URL(U), *选中“资源的永久重定向”(切记) *最后点击“应用” 2、如果是云主机,只需要相比虚拟主机来说,简单很多。 以美橙互联为例。首先站长要拥有账号和密码,如果账号密码都有的话,直接登录账号和密码,进入到主机面之后,点击我们的域名,知道域名重定向选项,就可以设置301。 3、其实我们在解析的时候,不解析不带www域名a记录也是可以的,这样的方式,就可以不用使用网站301重定向,也减去了重定向和网址不规范的问题。 最后就是经常网站优化QQ群中,看到有人提问问题就是我制作网站301重定向为什么到现在还没有生成。其实,网站301重定向生成需要时间,一般是一个月左右,百度会根据情况,来判断网站,已决定生成时间。 如何解决网站301重定向制作成功 那就是我们用站长工具-找到HTTP状态查询-输入网址。如图 如果状态码出现301,就代表制作成功。(图为王志廷自媒体博客没有解析不带www所以查询会出现400)。 来源:王志廷自媒体博客
导读:现在全球的经济都在下滑,企业却不断的增多,优胜劣汰的市场规则,严重威胁到处于传统模式的中小型企业,如果不立即改变营销模式,那只有被市场所淘汰,网络营销对于中小型企业来说,是个不错的转型方式,不仅可以帮助中小型企业扩充销售市场,也多一个销售渠道,打造网络品牌,在互联网这块都是平等,没有大企业、小企业之分的,只要把互联网营销做好,让更多的潜在客户知道企业,一定的可以获取更多的订单,利用营销型网站具备的优势,挖掘潜在客户,那么营销型网站建设公司选择哪家更好呢?今天站三界导航小编与大家分享。一、为什么要建设营销型网站就拿搜索引擎来说,现在国内主流的搜索引擎百度、360、搜狗有着大量的用户群体,在这众多用户群体中,就有许多我们的潜在客户,做网络营销就是在搜索引擎中做推广,把企业的信息传递给潜在客户,当用户搜索相关关键词,引导进入营销型网站中,利用营销型网站特有的优势,转化成成交客户;二、如何选择专业的建站公司1、看建站公司的策划能力营销型网站策划做的好不好,决定后期网络营销的成效,网站要是没有营销力,就不能很好的吸引访客,这是模板型网站缺陷,没有专业的策划,不能访客与企业之间加强信赖感,别说询盘了,每一个询盘背后都是一个高额的订单,如果不能做到询盘转化,那意味着网络营销是失败的,所以要清楚的了解建站公司的策划能力;2、看建站公司的美工设计能力美工的能力决定营销型网站留给用户的第一印象,现在的消费者不缺乏内容,缺乏的是视觉,现在市面上的网站都是千篇一律的,当访客户,发现一个不一样的网站的时候,就会加深其对你企业的印象,不由自主的就是深入浏览,吸引用户,提升目标客户对企业的好感;3、看建站公司的建站能力作为专业的营销型网站建设公司,都会有拥有自己的拥有自己核心技术和建站系统,现在市面上许多的建站公司都是复制别人的,能够把外观做到类似,但是后台系能却相差万里,许多的仿站的建站公司,用的都是dedecms模板程序,这种对于建站公司来说非常方便,对于用户来说是不方便的,操作起来非常复杂,而且安全性差,容易被攻击;4、看建站公司的团队水平专业的建站公司都会有自己的拥有自己核心技术、核心研发团队、核心的建站系统,并且针对客户的需求,不断的去更新、完善建站系统,在保证营销型网站的安全性下,又能够让用户快速上手掌握相关操作,这是市场上许多建站公司都不具备的;5、看建站公司优化能力做网络营销就是做搜索引擎优化推广,而企业的营销型网站超过80%访客是来自搜索引擎,所以营销型网站的关键词选择决定了后期能够带来多少精准客户,只有选择适合的关键词,布局到每一个页面,做优化参与搜索引擎排名,这样当潜在用户搜索关键词,搜索引擎展现相关的网站,这样用户才能有机会进入网站,这也就要求建站公司的优化能力要强,就那站三界导航来说,都会没每一家用户选取精准关键词,布局每一个页面;总结,营销型网站不仅用户体验好,也符合搜索引擎需要,结合了现代营销理念,能够快速的讲潜在客户抓化为顾客,前期的策划、网站定位、关键词选择、页面的设计都考虑到用户的实际的需求,为后期的网站推广打好基础。
首先给大家介绍一下,我们在做织梦Cms移动化友好度建设要注意哪些:1、网页的篇幅不要太长因为手机的屏幕较小,如果页面过长,第一会影响网页的加载速度,第二用户需要多次向上滚动才能看完整个网页,这个是一种不好的体验,一个移动站点的首页最好是控制在2-3屏,这样能把一些重点简单明了的展示在首页,同时也不会对网站加载造成太大的负担。2、网页使用静态页面用过织梦Cms的站长都知道,织梦后台有生成静态页面的功能,相较于动态页面,静态页面对于SEO友好度要好得多,所以建议站长在做手机站的时候尽量使用静态化的页面,这样有利于提升网页的加载速度,同时对于网站安全也有帮助,织梦怎么快速有效的建立移动优化站,之前站长学院给出了相关教程(参考:《干货分享:Dedecms网站移动化分几步?五步搞定!》),在这里我就不多加介绍了。3、做好PC站适配跳转这一点我认为尤其重要,因为在早期很多网站没有移动化站点,也并没有做自适应的处理,这样就导致m.baidu.com在收录时,是被百度收录了的PC页面或者被百度转码,所以我们在做了移动站点后第一件要做的事情就是做好适配,这里介绍了三种适配的方式(参考:《移动适配工具该怎么用、如何提升适配效果等》),在做完网站的适配之后,站长也可以将pc站和移动站一一对应的关系在百度站长平台后台进行提交。4、图片单独处理因为在织梦程序里要做手机站是需要和PC端公用一个数据库,这样就会导致手机上调用的图片和PC一致,但是PC站上的图片的尺寸和大小显然不能满足移动友好度的要求,这个地方站长可以针对手机单独进行处理,比方说在上传图片的时候按照比例上传多张图片供不同的设备使用。5、移动网站的分页现在很多网站流行使用ajax加载的方式加载网站列表,这种方式固然是对用户体验的一大提升,但是现在百度是不抓取JS内容的,所以到时你加载的内容是不被百度蜘蛛抓取的,所以建议站长尽量使用分页6、链接区域放大因为手机屏幕小,所以如果链接区域偏小,会很容易影响点击,同时链接与链接之间要保持好距离。这个可以根据官方文档里面给出的建议进行调整7、手机站尽量少用多媒体元素因为对于手机站而言,加载速度对于移动化友好度极为重要,所以我建议各位站长尽量少用或者不用多媒体元素,同时要注意的是,百度蜘蛛目前为止抓取还是以文字为主,所以从网站优化角度而言,也应少用多媒体。如果上面几点站长对于自己网站调整还无从下手的话,可以通过站长工具里面的移动友好度进行评测,根据评测结果进行网站调整。 以上就是对织梦移动化友好度建设注意事项总结全部内容的介绍,更多内容请继续关注站三界导航!
随着互联网建站尤其是自助建站热潮不断高涨,建站行业涌现出越来越多的自助建站平台,这些平台普遍都提供网站模板可选。网站模板的大量出现,使得建站步骤变得便捷,深受一大批用户的喜爱。比如,最近很受用户追捧的微企点就为用户提供上千套网站模板免费使用,这些模板网受到广大用户的喜爱,且成了企业建站的首选。虽然模板建站深受用户好评,站三界导航还是要提醒大家小心网站模板行业中的陷阱! 警惕网站模板建站三大“陷阱” 无论是免费模板还是付费模板,它的制作成本低,不排除在这个行业中的企业仅仅是利用模板来赚钱,他们并不对模板的质量进行负责和保障,甚至有些模板是经过多手购买,加以修改和转卖的,在你使用模板之前一定要注意以下几点: (1)当你使用某个建站平台的网站模板进行建站的时候,应先进行考察,不要被此网站上漂亮的图文广告,营销手段所蒙蔽。 (2)在购买模板之前对行业所能提供的服务进行咨询,以免造成出现问题时无人问津的结果,甚至有些应用插件也有二次付费的情况。 (3)对程序代码要有一定的了解,尤其是在想要搭建一个需要做优化的网站的时候,应该选择符合优化规则的模板。 从模板库中选择适合的模板网站,不仅要模板好,还要服务好!微企点提示用户:在选择网站模板建站的时候,一定要擦亮双眼,警惕一些潜在的陷阱。 以上就是网站模板建站三大“陷阱”,大家一定要警惕,希望能对大家有所帮助!
面包屑导航(BreadcrumbNavigation)这个概念来自童话故事"汉赛尔和格莱特",当汉赛尔和格莱特穿过森林时,不小心迷路了,但是他们发现在沿途走过的地方都撒下了面包屑,让这些面包屑来帮助他们找到回家的路。所以,面包屑导航的作用是告诉访问者他们目前在网站中的位置以及如何返回。 当网站的子页面分类较多的情况下,一般都会选择使用面包屑导航作为页面的辅助和补充,有效帮助用户在网站中快速找到返回的路径,尤其体现在电商网站上,运用最为广泛,用户可以在众多产品类型中确定自己的位置以及找到目标产品,在一定程度上提高了用户体验。 网站使用面包屑导航虽然有它的优势所在,但并不是所有的页面都适合使用,毕竟它不能在网站上占据主导地位,以免造成对用户的误导,那么,网站应如何正确使用面包屑导航呢? 首先,在设置面包屑导航的关键词是一定要统一,每一个主目录和子页关键词都要精简且唯一,存在辨别性,这样能让用户在浏览网站或者电商购物网站中购买商品时产生疑问,且对自己的当前位置一目了然。同时,所有的分类面包屑的关键词都不能存在有歧义的词现象,避免重复性。譬如淘宝网的面包屑导航,每一个分类都清晰明了。 其次,认识分类少则不使用面包屑的误区。有些网站认为子页内容分类少,就没必要使用面包屑,其实这是一种错误的观念,奇亿网络认为,页面中只要有两个以上都分类页面,都有必要使用,毕竟用户在点击层级页面时总会有返回上级页面的需要,且在没有记住每个页面相关内容时,很容易忘记上级页面内容是什么,因此每次要靠返回按钮进行操作的话会更加麻烦一些,使用面包屑导航则可对当前页定位,帮助用户回到各层级页面。 再者,则是做好主导航与面包屑导航之间的区分,主导航始终承载整个网站的主导地位,而面包屑导航则是起辅助作用,因此用户在辨识面包屑导航时应起到更加精准的作用,而不是重复主导航已经存在的栏目分类,又或者说用户在点击主导航时会犹豫面包屑导航对其产生的干扰,否则面包屑就是去了本该有得价值和意义。 最后,在设计面包屑导航时无论分类是否复杂,但都要尽可能的精简层级,对产品分类或者概括要综合言简,避免太多太细的分类让用户浏览时容易疲劳,当然,这样的面包屑也有利于网站优化,容易被搜索引擎抓取,同时对提高用户体验有一定的帮助。 面包屑导航对于每一个网站来说,并非必须品,但却是精品,最常见的是在电商网站中,有它的存在就像给用户装上了另一个指示灯,帮助用户在网站上找到浏览的轨迹并让他们的需求快速得到满足。但前提是使用面包屑一定要注意正确的方法。