在本文中,我们将详细介绍专访|今日头条2016ByteCup大赛实战经验分享:要充分挖掘模型本身的信息的各个方面,同时,我们也将为您带来关于2018OSC年终盛典,Flutter跨平台框架实战经验分享
在本文中,我们将详细介绍专访 | 今日头条2016 Byte Cup大赛实战经验分享:要充分挖掘模型本身的信息的各个方面,同时,我们也将为您带来关于2018 OSC 年终盛典,Flutter 跨平台框架实战经验分享、B2B网站SEO优化实战经验分享、C++ 递归实战经验分享:代码优化与技巧总结、deployer 实战经验分享的有用知识。
本文目录一览:- 专访 | 今日头条2016 Byte Cup大赛实战经验分享:要充分挖掘模型本身的信息
- 2018 OSC 年终盛典,Flutter 跨平台框架实战经验分享
- B2B网站SEO优化实战经验分享
- C++ 递归实战经验分享:代码优化与技巧总结
- deployer 实战经验分享
专访 | 今日头条2016 Byte Cup大赛实战经验分享:要充分挖掘模型本身的信息
机器之心原创
作者:杜夏德
今日头条技术副总裁杨震原在 2016 Byte Cup 世界机器学习比赛颁奖仪式上说,「我们期望经过算法解决问与答的匹配功率疑问。这个疑问即使是小幅的改善,也会影响到数以百万计的用户。」
近日,由今日头条与中国人工智能学会及 IEEE 中国分会合办的 2016 Byte Cup 世界机器学习比赛颁奖仪式在中国工程院举行。共有 1000 多支队伍参赛,冠亚季军队伍分别是 brickmover、天穹战队和西电战队。
本次比赛的任务是建立模型,将头条问答中普通用户的问题更快更好地推送给专家。与以往比赛不同的是,这次比赛所用数据来自于头条问答真实的用户数据。
颁奖仪式结束后,机器之心对这三支得胜队伍代表成员进行了独家专访,分享了比赛过程中的心得。他们分别是西电战队的郭正肖和郝磊,天穹队的钱乾与 BrickMover 队的庞亮。
学科背景:
庞亮:deep leaning 文本匹配
郭正肖:计算机图形学
郝磊:通信网络
钱乾:数据挖掘工程
首先我们来看看这三支队伍的所用模型和比赛思路
第三名西电战队
他们使用的是 FM 算法,并从算法、协同过滤和模型融合三个方面进行考虑。据该队成员介绍,使用 FM 算法有两个考虑,首先是用一系列因变量模型特征之间的关系,更容易发现特征之间的隐藏,适用于解决推荐系统的问题,二是 FM 算法具有线性,时间复杂度低,运行速度较快。在模型融合上,他们选择 FM 算法预测结果协同过滤算法结果经过加权作为最终的结果。
第二名:天穹战队
第二名的选择算法的过程有些曲折。他们首先考虑了 SVD 与 SVD++模型。在验证了 SVD 对这个问题的效果之后,开始尝试用一个比较通用的 FM 算法来处理这个矩阵的分解问题,并在比赛后期为了满足自定义优化需求,重新实现了 fm 并在优化方法上做了修正,使得预测效果得到很大的提升。
第一名:BrickMover
他们在比赛的前半段都是在设计一个单模型,提升单模型的效果,后半段利用 Blendling 进行模型融合的。具体过程请看下图:
以下是专访内容
机器之心:比赛前你们对自己有什么预期?
郭正肖:我是属于跟着我的队友一起参加比赛。我自己也算是半路出家,实力并不强。我周围的同学都在看这方面的书,没有实践,但我的朋友告诉我可能参加比赛会更有好处。当时我就想参加什么样的比赛比较好?我发现这次比赛进度拉的比较长,从 8 月到 11 月一共是 3 个多月,时间一长我就能对这个比赛有更多的了解,学到更多的东西。当然我也是抱有一些小幻想的,能拿个奖什么的。在比赛过程中,我的两个队友给了我很大的帮助。
庞亮:我当时看了一下这个比赛的数据,与推荐系统相关的。其实与我的领域不是很相关。但是举办方给的数据是文本数据也是个匹配问题。所以最初的想法就是试一下我自己的模型能不能在比赛上 work 一下。我的模型就是那个 Match-SRNN。然后在做的过程中对这个数据有了更多的了解后,又试了一下其他的模型,因为要做一下 Baseline 和 SRNN 的比较。
钱乾:我一开始是跟着我朋友一起来做的,他想用 deep learning 的方法去做到。一开始我也是想能不能不用 deep learning 的方法也能把分数做上去。做着做着就越来越对 FM 这个模型感兴趣,最后用自己的代码去实现了一个自己写的 FM 模型。也算是一个学习的过程和一个验证的过程。然后还是要测试一下将图模型这种东西用在推荐领域上是否可行?那么最终验证出来也是可以接受的。这个基本上也是我的一个初衷吧
机器之心:那你(钱乾)对 FM 这个模型在这次比赛中的表现满意吗?
钱乾:我后来对比了一下自己写的 FM 与 C++写的 FM,在优化以后能够达到与原本用 C++写的 FM 能达到同样的一个精度吧。
机器之心:在参加比赛的三四个月的过程中,有没有一个关键的节点让你们觉得自己的模型有了很大的提升,有信心拿下这个比赛?
钱乾:有两次吧。第一次可能就是尝试使用了 neighbor 的一些数据。并且通过分析之后加了一些 IDF 的一些加权,这个给我的模型带来了一个很大的提升。这是第一个关键点。
第二个关键点是,在我采用 deepwalk 这个算法构建特征以后使用树模型,它也给我的模型带来的提升。
庞亮:我一开始是实现了一个 baseline,一个最基础的矩阵分解模型。发现效果挺不错,基本上可以进前 50 了。后面有提升的地方也是和他一样,加了一些 neighbor 的信息,就是一些 implicit 的 Feedback,再加上两边的 implicit Feedback,就是这样一点点提升上去的。在精简模型的方面用上一些非对称思路,让模型更加鲁棒。还有原来的 SVD++是不对称一种结构,然后就想怎么能把它变成一个对称的一个结构。
机器之心:ASVD++这个算法是你们自己提出来的吗?
庞亮:是的,但不是这一次比赛提出来的。之前在百度的推荐大赛上就使用过,发现它很有效果。这一次是把一部分的 ID 去掉之后,这是新的。
用完 blending 之后,我们又尝试了别的模型,想看看它效果怎么样,不仅仅是为了刷分。比较每一个算法的优劣。
机器之心:这次比赛中有没有对自己不太满意的地方?
庞亮:可能是数据上吧,隐藏掉了一些词的信息,虽然在数据量上的 entry 很多,词表也很大,很多时候我们没法用上我们已经训练好的 word-embeding 信息,这样就导致我直接拿它来用的话会有一些困难,性能上会有损失。但是我相信在文本上挖掘的信息是很有用的。但这次比赛都是用 ID 拿出来的,我们没法 pretrain 这些 ID 的 Word
钱乾:我们就用了一张表,也是没有用上。
(笔者注:据主办方介绍,所给数据本来应该是一个自然语言,但是主要考虑到有一些国外的参赛选手对中文并不熟悉,把文字进行 ID 化的处理,首先进行分词,每个词会有一个 ID,这是唯一标识,对每一字也给了一个 VID,用这种形式作为问题的表征)
庞亮:我们都是希望能把这些信息用全,每个信息都能带来一点提升,然后对比一下每个信息的提升。这一点比较遗憾。
机器之心你们的参赛经验是怎样的?
郝磊:我参加的比较少,也就三四次吧。
钱乾:我一般就参加 kaggle 吧,有六七次的经验。
机器之心:能分享一些比赛经验吗?
图:第二名天穹战队代表钱乾
钱乾:就我个人来说,一开始参加比赛不要特别急躁,不要一上手做到一定程度就想着要去做融合 ensemble,一开始就是要把数据看得特别清楚,到底这些数据代表了什么,隐藏了什么价值,包括怎么去做一些特征工程上的东西。这些东西有时候是需要灵感,但有时候通过一定的分析手段是能看出来的。比赛时一定要先弄清这些事情再去考虑后续的一些步骤。
庞亮:比赛就是一个兴趣吧,有时间就可以参加。借着比赛去实现自己的 Idea,看看它们的表现到底怎么样。而且只有在快结束的时候可能会比较忙,前面的过程不会占用你太多时间。
钱乾:我们做到一定程度以后就没有再动过了。
机器之心:请问第一名从始至终的思路是什么样的?你们是怎么思考问题的?
图:第一名 BrickMover 队代表庞亮
庞亮:我们第一个思路是把传统的模型先做一遍,我们试过 XGBoost 与 FM、还有 SVDfeature 这三个的对比,发现这个问题本身就是一个传统的推荐问题,像 XGBoost 这些都不奏效。然后我们就往那个方向走,你就要去改进模型本身。因为常用的模型大家都有,你能做到,别人也能做到,你能调参,别人也能调参,所以你就要深入到模型本身上去挖掘它剩下的一些信息,然后根据你挖掘到的东西来进行改进,比如说 SVD++,这个是已经成型的模型,你发现 SVD++本身很有效果,那就再继续往下挖嘛。我们有三个人嘛,每个人都有自己的分工,我这边是调理参数和 SVD++这一块,有一个同学是负责挖新的模型,比如说 deep learning 方面的模型,他会去搜索新的 paper,如果有源码实现的最好,如果没有,就 balance 一下,看看最后实现起来怎么样,如果太复杂就放弃了。还有一个同学专门攻 blending 这一块,做几个模型的融合。
不过他也是后面才做的 Blending,之前也在调整 SVDfeature 这块,我自己还试了一下新的模型。
郝磊:你们的模型融合是怎么融合的?
庞亮:我们把所有的分数拿来融合一下,就是结果融合,也就是线性模型嘛。然后用了 cross validation。
整体的思路有几个步骤:首先是分析数据,数据拿来之后,你需要把所有的分布都了解一遍,包括内部分布和特征分布。在专业一点就是你要画出两两 feature 之间的相关性。第二就是把不必要的 feature 和 item 给去掉,做好数据清洗工作。清洗完之后再用模型。先用基础模型,看一下效果,再用复杂的模型,再比较一下这两个模型的差异到底有多大。如果复杂模型表现不好就没必要用它了,直接在基础模型上加 feature 就可以了,这样你只要做 feature engineering 就可以了,完了之后就是 blending。
机器之心比赛过程中专业给你们带来了哪些帮助?
钱乾:对我来说就是编写代码的能力。像 SVD SVD++ MIF 我们都试验了一下,但是没有现成的模型,我们就必须从头开始,把这些东西写下来,还是比较考验编程功底的。
郭正肖:我没有太多,就是一些基础的线性代数。我学的是图形学,对向量的理解会有些不同,我考虑的是空间上的。而且我是计算机技术背景,更多偏向工程。但是参加完比赛之后有了经验就知道要多去看 paper,看看别人是怎么做的。
第三名西电战队代表郭正肖(中)
庞亮:我是学深度学习文本匹配的,在实验室做一些调参建模工作都会培养出对数据的敏感。有了数据敏感性,看一下这个数据的分布大概就知道它的分布了。
©本文为机器之心原创文章,转载请联系本公众号获得授权。
✄------------------------------------------------
加入机器之心(全职记者/实习生):hr@almosthuman.cn
投稿或寻求报道:editor@almosthuman.cn
广告&商务合作:bd@almosthuman.cn
2018 OSC 年终盛典,Flutter 跨平台框架实战经验分享
移动互联网时代,高效、灵活地开发移动应用成为开发者追求的目标。Flutter 的出现,更是给跨平台开发注入了新的活力。本专场将从实际应用出发,探讨如何从百花齐放的移动开发盛景中找到适合自己的最佳选择。
B2B网站SEO优化实战经验分享
导读:实战的文章就是好,图文并茂的讲诉了SEO优化过程,比谈理论的SEO文章要好狠多,手把手教你通过站内、站外的SEO优化,作者接手半年的网站通过优化PR达到4、外链也增加不少,尤其是外链建设,好文章我也愿意给他一条外链。本文适合新人阅读,有干货。
B2B网站SEO优化实战经验分享 网站优化 SEO优化 SEO推广 第1张
(配图:环境在艰苦也要学习SEO)
卢大哥,我是新浪微博和微信中的@小旭依然,,上次在微信朋友圈看到您这个邮箱接受投稿,需要干货。想着网上关于实战经验的文章少之又少,便自己有时间写出这样一篇实战经验的文章,用词也许生硬,但是其中经验对新手来说应该是一个启发。
9月中旬接手了“江西现代服务交易网”这个b2b网站,网站到目前上线已经半年了。
大家都知道,2013年是百度规则大改,seo业界可谓艰难的一年啊!百度石榴算法,原创火星的计划,绿萝算法的推出让站长们胆颤心惊,近乎苛刻的外链审核都似乎在告诉我们外链为王的时代已经过去,而大家强调的以用户点击率评判外链质量的好坏时常让我想到是先有鸡还是先有蛋的问题。
不管怎么样,如果你觉得力不从心,那是因为seoer思维还没有转变过来,抑或说大家都都没有一个系统普遍的seo成功优化方案。对于以上,相信广大seoer都在探索之中,包括我现在负责的“江西现代服务交易网”这个b2b站点,目前仍然在百度的算法不断更新中seo收录仍然非常不正常,表现出索引量近一万,而site值在1000-5000之间巨大的波动。
一、网站9月中旬跟网站现在seo情况
废话说了这么多,切入正题,我是9月份中旬接手这个网站,通过对网站的分析发现,网站在初期seo存在以下不足:
1,网站收录9月中旬仅为147
由于之前负责网站的是另一个seoer,进一步了解到江西现代服务交易网这个B2B网站在上线前2个月收录都没什么动静,第三个月收录才陆陆续续上来,9月中旬的时候收录数量为147。
2,外链数量
外链到9月中旬的时候数量为1000左右,具体查询后,发现指向首页的链接太少,这也造成“江西现代服务交易网”这个关键词在100名以外的原因之一(后面还会提到别的原因)。此外,外链在广度和质量方面还有待提高。
3,关键词排名
网站权重为0,暂时无任何关键词排名。实则具体分析发现,网站核心关键词都没有确定,因此,在前期做的外链锚文本中,都是杂乱,分散。在确定以“现代服务业”为核心关键词后,对网站标题及网站首页添加了几处“现代服务业”关键词,以增加首页关键词密度。
4,内部结构
网站到10月20日的时候,收录为547,收录比率仅为3.65%。尽管,网站也许还在审核阶段,收录不可能很高,但是仍然可以通过采取一些手段增加网站的收录比率。21日通过对网站调整辅助导航(增加了指向首页的链接,从而提高网站权重,这也是造成“江西现代服务交易网”这个关键词上升不了的原因),更改网站文章内页模板标题,增加无关链接的nofollow标签等手段后,仅在4天后,网站收录出现一个大的提升,同比净增长142.92%。当然,在采取这些大的内部结构改动后,网站快照从隔日更新瞬间近半个月维持在10月21日。
这是之前文章内页的标题:
B2B网站SEO优化实战经验分享 网站优化 SEO优化 SEO推广 第2张
网站二级频道【展会信息】的大的标题竟然在文章内页中一起出现,造成文章标题“又臭又长”,影响收录。而这种情况恰恰出现在多个频道的内页中。
B2B网站SEO优化实战经验分享 网站优化 SEO优化 SEO推广 第3张
文章内页竟然没有出现“江西现代服务交易网”这个网站标题,正确的形式应该是“文章标题+栏目名称+网站标题”或者直接“文章标题+网站标题”
修改后:
B2B网站SEO优化实战经验分享 网站优化 SEO优化 SEO推广 第4张
由于在文章内页中缺少“江西现代服务交易网”的后缀标题,“江西现代服务交易网”这个关键词只存在首页及二级频道页面当中,在文章内页中增加后将大大提高网站与“江西现代服务交易网”这个关键词的相关性。要知道,网站名称都在百度找不到的话,意味着这个seo是做的多烂。
内部问题是发现后能得到技术人员的及时改进,这是比较开心的。网站在初期,由于网站主编跟我们seoer的目的不同,他为了填充数量而让编辑填充了大量的低质量的页面,这点在后期网站收录不佳后,问题得到了重视,因此,在一次会议后,调整了策略:减少量,注重质。不过,仍然还存在一些问题没有解决,比如企业黄页的伪静态问题。
二、目前seo情况:
在控制文章质量后,网站质量得到了有效改善,这点从pr可以提现。谷歌pr在12月7日更新,我们欣喜的看到江西现代服务交易网网站pr一下子从无到4,说明了我们工作中取得的一些进步。
B2B网站SEO优化实战经验分享 网站优化 SEO优化 SEO推广 第5张
1、收录和反链。
在12月2日索引量陡争7000多达到近一万后,site值就在2000-5000直接大的跳跃,反链更是在4000-300000直接波动,很多人说,看百度站长后台更加准确,相比站长工具,的确,百度站长平台就显得平稳多了,但是之前站长工具查询数据跟百度站长后台都是同步的,这也从另一个方面反映了百度算法更新对网站的影响。相关seoer从业人员,给我的建议是不要管,专心更新网站内容和外链,我想,也只有这种以不变应万变的方法了,并且也是最稳妥的。
B2B网站SEO优化实战经验分享 网站优化 SEO优化 SEO推广 第6张
百度站长后台索引量,目前近1万
B2B网站SEO优化实战经验分享 网站优化 SEO优化 SEO推广 第7张
百度站长后台外链
2,网站关键词排名
经过网站内部结构整改后,关键词排名一直在20几位,期间有几天上升到第10位维持了几天后又掉下来,中间有一天到第1位。也想不到别的好的办法,继续给网站做“江西现代服务交易网”的锚文本外链,以提升关键词的权重,终于,在12月4日上来了,并且稳稳第一位。
“现代服务业”:这个指数为200左右,竞争程度中等偏下,但是排在前面的几乎都是政府性网站,加上b2b网站首页的特效性,不能在很多地方放置“现代服务业”关键词,且为了用户体验性着想,没有好的栏目来添加“现代服务业”相关文章,给优化关键词方面带来了一定难度。截止到目前,“现代服务业”关键词出现主要在友情链接及博客,论坛当中,而且数量不多。(好吧,说到外链又是我的痛),关键词排名在30上下波动,排名最好的时候在24位。个人一直建议增加“现代服务业”栏目以供专门添加“现代服务业”相关文章,且为二级频道,辅助导航表现为“现代服务业->文章标题”,“现代服务业”直接链接到首页,为不影响首页版面,在首页头部或底部增加“现代服务业”关键词入口,可惜,由于沟通问题,技术一直没有重视及改善。
网站同时优化的还有“江西企业”“江西电商”“企业服务”“中小企业网”“江西企业名录”等关键词。由于本人seo经验的不足,精力,人力各方面的限制,这些关键词排名还不是很理想。其中,“企业服务”“中小企业网”在100名以外,江西企业”“江西电商”“江西企业名录”分别是53,12,28位。
seo心得分享
要问到seo技巧时,大师给我们的建议总是坚持好的原创文章更新,及努力创造高质量的外链。这虽然可以通用,但是,我们更希望的是能给我们一些做关键词排名的方法,进而少走一点弯路。这里我分享一些我从事seo以来的一些心得体会。
1、站内
由于自己曾经做过网站建设,懂得一些源代码,所以这方面的知识对我工作是一个帮助。在优化关键词排名时,尽量在首页增加关键词密度,2%-5%最好,能给我们外链建设减少不少工作,如果不能,就想方设法多做一些好的质量的锚文本外链吧。此外,我们很少接触到项目的初期建设,因此在网站架构方面很多时候都无能为力,比如增加优化专题,关键词布局啊甚至一些更大的改动,所以略过不提。
2、站外外链建设
外链建设是自己一直非常不擅长的,这也是做了这么久的外链才这么点成效的原因。但是仍然可以分享一些经验,哪怕失败的,防止你们多走弯路。
1)论坛。如今seo这个职业深入人心,对于管理论坛的人来说,恐避之不及。因此,论坛外链做起来那是精力花费非常多,效果却不好。有些论坛等级甚至到很高,也努力的发了几个热帖也因为你的一两个外链被管理员无情的永封。因此,论坛这块外链阵地算是没事耕种一下,不可花太多心思。当然,一些权重高的站长论坛如落伍,a5偶尔发一些引引蜘蛛还是不错的。
2)博客。新开博客发链接能快速收录的寥寥无几,哪怕是新浪这样曾经我们seoer公认的发外链的好地方。估计百度算法对新开博客收录审核严格了不少,但是,如果培养起来了,仍然是绝佳的发锚文本外链的地方。建议花心思培养。
3)分类信息发布网站。分类信息网站数量不少,收录的不多,同样是精力多,成效少。
4)B2B网站。权重高能带链接收录还好的B2B网站如今一个手指能数的出来,由于是跟我们网站行业性质相关,我们仍然没有放弃这一阵地。精力花费的也不少。
5) 问答。能带链接还能收录的问答网站有多少,我至今没收集到一个手指头的数量。问答删掉答案的严厉程度不亚于如今的百度百科。
6)其他。其他包括收藏夹,文库等等,自己可以去收集摸索。
以上都是失败的效果不好的经验,那么成功的经验呢?我做外链的过程中,越来越发现“分享”的原则,利用网络各种渠道,去不吝分享你的东西,收到的效果有时会出乎其外的好。分享的渠道目前比较有效的有:
1)投稿。这也是我一有时间就会去做的,目前在站长之家,a5,落伍同时投稿,数量不多,但是外链效果不错。一篇文章一般可以引来10条外链,去掉你外链copy你文章数量的人实在太多了,这也反映了如今seo界的一种不好的现象。因此,我现在要是转载别人的文章,如需附上网址,一定尊重。
2)资料分享,下载。百度文库如今审核很严,至今为止没有一篇通过的。但是360图书馆有一个很好的“来源”可以在发布文章时附上我们的网址,虽然比较隐秘,但是凭借360本身的影响力,图书馆人气很旺。我有一篇文章在其被转载了130多次,也因此被360图书馆加了精。此外,新浪爱问知识人资料下载,豆丁网也是不错的选择。下载的人不少,顺便宣传自己的网站。
3)社会化媒体。有人说,如今就是一个社会化媒体的时代,社会化媒体的本质也是“分享”,如今很火的有微博、微信,空间,由于精力有限,还没有往这方面做努力。建议有精力的朋友不可放弃这一阵地。
从“分享”原则可以看出,Seo变得比以前复杂多了,更多的往网络营销方面走了,借用我另一篇文章中的结语:一位合格是seoer,一位合格的seoer一定要懂用户体验、品牌建设、及外链的社会化。否则,seo将是死路一条。
以上信息由江西现代服务交易网(http://www.jxmstc.org/)原创提供,转载请注明来源,相互尊重
C++ 递归实战经验分享:代码优化与技巧总结
递归优化技巧:尾递归优化:编译器在函数自身调用前进行所有计算,提升效率。记忆:存储先前计算过的输出,避免重复计算。迭代:用迭代算法代替递归,提高可读性和避免栈溢出。
C++ 递归实战经验分享:代码优化与技巧总结
在实际开发中,递归常常被用于解决复杂问题。它允许函数调用自身,从而创建嵌套的调用堆栈。然而,过度的递归调用可能导致栈溢出和程序崩溃。
以下是一些优化递归代码的技巧,并配有实战案例:
立即学习“C++免费学习笔记(深入)”;
1. 尾递归优化
尾递归是指函数在自身调用之前进行的所有计算,并且自身调用是函数的最后动作。对于尾递归调用,编译器可以通过在调用堆栈中替换函数指针而不是压入新的栈帧来优化它。
int factorial(int n) { return n == 0 ? 1 : n * factorial(n - 1); }
通过使用 tail-call 优化标记,编译器可以识别此递归为尾递归并进行优化。
int factorial(int n) __attribute__ ((tailcall));
2. 记忆
记忆是一种技术,用于存储先前提出的相同输入的输出。当递归不断重复相同的计算时,记忆可以显着提高性能。
int fib(int n) { static std::map<int, int> memo; if (memo.count(n) > 0) { return memo[n]; } return memo[n] = n < 2 ? n : fib(n - 1) + fib(n - 2); }
此代码使用 std::map
3. 迭代
在某些情况下,递归问题可以用迭代算法代替。这样做可以避免栈溢出的风险并提高代码的可读性。
int factorial(int n) { int result = 1; while (n > 0) { result *= n--; } return result; }
此代码迭代地计算阶乘,而不是使用递归。
实战案例
斐波那契数列
计算给定索引处的斐波那契数可以作为递归的经典实战案例。使用记忆技术的递归实现如下:
int fib(int n) { static std::map<int, int> memo; if (memo.count(n) > 0) { return memo[n]; } return memo[n] = n < 2 ? n : fib(n - 1) + fib(n - 2); }
使用此代码,我们可以有效地计算大型斐波那契数,而无需担心栈溢出。
以上就是C++ 递归实战经验分享:代码优化与技巧总结的详细内容,更多请关注php中文网其它相关文章!
deployer 实战经验分享
开发完项目,免不了要部署上线。纯手动操作,登录、拉代码、改配置、清缓存、各种服务重启等等一条龙下来,人生宝贵的几分钟就过去了。而且手动操作十分容易出错,遗漏部分步骤都有可能产生一些邪门问题。所以我很早就开始寻求一种能轻松部署 Laravel 项目的办法。
laravel 的官方文档里介绍了 Envoy,之前用过,能满足大部分场景,但仍然有一些限制。直到后来看到了 deployer,大有相见恨晚之感!
deployer 的优势
- 真正解放双手,一条命令完成部署。
- 进行部署的过程中,项目仍然能够正常访问。部署成功完成后才切到新的版本。
- 能十分方便地进行回滚。
- 丰富任务钩子和预置任务可灵活的组合完成各种任务,比如执行前端依赖的安装、构建等。
- 其它骚姿势等你发掘……
使用 deployer 的前提条件
- 本地机器(也就是你执行 dep 命令时所在的机器)能够 SSH 连接到目标机器(代码要部署到的机器,不管是在线的云主机还是局域网中的虚拟机)
- 有登录目标机器并调整一些设置的权限,或者能让负责人协助调整。(使用过程中可能遇到问题需要调整一些设置,后面会提)
- 目标主机有拉取项目仓库的权限。(这个应该都有吧,不然玩个毛?)
- 足够大胆、足够细心、足够有耐性……
deployer 的使用
首先说明下个人实际使用场景。
本人使用 win10 系统,使用 Homestead 作为 PHP 项目的开发环境(vagrant v2.1.1, homestead v7.4.1, virtualbox v5.2.8, homestead 的 virtual box 版本为 v5.2)。
本地开发能完成绝大部分开发和测试任务,但在部署到生产机之前仍然需要先部署到开发机上进行测试。线上测试与生产使用的是青云的云主机,Ubuntu16 系统。
以下的操作都是在 homestead 虚拟机里进行操作!
- 安装
cd /path/to/your/project
composer require deployer/deployer --dev
个人习惯于将其作为项目依赖安装,当然也可以根据需要或个人喜好全局安装。
- 初始化 deployer 配置文件
vendor/bin/dep init
因为我用的是 laravel 输入项目类型 1 后回车,然后会出现一个让设置 git 仓库的,默认是对应项目的 git 远端仓库,不需要修改的话确认就可以了。
完成上面的初始化后,项目要目录下会出现一个 deploy.php 文件,deployer 的配置就靠它了。初始的配置如下,里面显示了一些基本的配置。
<?php
namespace Deployer;
require ''recipe/laravel.php'';
// Project name
// 项目名
set(''application'', ''my_project'');
// Project repository
// 项目仓库地址不解释
set(''repository'', ''git@github.com:tianyong90/xxx.git'');
// [Optional] Allocate tty for git clone. Default value is false.
set(''git_tty'', true);
// Shared files/dirs between deploys
// 分享文件即目录,通常也不用改,默认包含了 storage 目录
add(''shared_files'', []);
add(''shared_dirs'', []);
// Writable dirs by web server
// 可写目录,一般不用改
add(''writable_dirs'', []);
// Hosts
// 目标主机配置,这是最基本的
host(''project.com'')
->set(''deploy_path'', ''~/{{application}}'');
// Tasks
// 这算是个自定义任务示例
task(''build'', function () {
run(''cd {{release_path}} && build'');
});
// [Optional] if deploy fails automatically unlock.
// 如果部署失败,自动解除部署锁定状态,以免影响下次执行
after(''deploy:failed'', ''deploy:unlock'');
// Migrate database before symlink new release.
// 执行数据库迁移,建议删掉,迁移虽好,但毕竟高风险,只推荐用于开发环境。
before(''deploy:symlink'', ''database:migrate'');
- 修改配置
默认的配置肯定是不行的,目标主机啥的还不知道呢。下面直接贴上自己用到的配置,并加入了少量说明。
<?php
namespace Deployer;
require ''recipe/laravel.php'';
// Project name
set(''application'', ''xxx'');
// Project repository
set(''repository'', ''git@github.com:tianyong90/xxx.git'');
// [Optional] Allocate tty for git clone. Default value is false.
set(''git_tty'', true);
// Shared files/dirs between deploys
add(''shared_files'', []);
add(''shared_dirs'', []);
// Writable dirs by web server
add(''writable_dirs'', []);
// 保存最近五次部署,这样的话回滚最多也只能回滚到前 5 个版本
set(''keep_releases'', 5);
// 实践证明,这样能减少一些不必要的麻烦,如出现权限相关的问题,也可将此项设置为 true 后尝试
set(''writable_use_sudo'', false);
// 生产用的主机
host(''172.16.1.1'')
->stage(''production'')
->user(''root'')
->port(22)
->set(''branch'', ''master'') // 最新的主分支部署到生产机
->set(''deploy_path'', ''/data/wwwroot/xxx'')
->identityFile(''/home/vagrant/.ssh/id_rsa'')
->forwardAgent(true)
->multiplexing(true)
->set(''http_user'', ''www'') // 这个与 nginx 里的配置一致
->addSshOption(''UserKnownHostsFile'', ''/dev/null'')
->addSshOption(''StrictHostKeyChecking'', ''no'');
// 测试用的主机
host(''172.16.3.2'')
->stage(''debug'')
->user(''root'')
->port(22)
->set(''branch'', ''develop'') // 一般是把 develop 分支弄到测试机测试,没问题再合并
->set(''deploy_path'', ''/data/wwwroot/xxx'')
->identityFile(''/home/vagrant/.ssh/id_rsa'')
->forwardAgent(true)
->multiplexing(true)
->set(''http_user'', ''www'')
->addSshOption(''UserKnownHostsFile'', ''/dev/null'')
->addSshOption(''StrictHostKeyChecking'', ''no'');
// 自定义任务:重置 opcache 缓存
task(''opcache_reset'', function () {
run(''{{bin/php}} -r \''opcache_reset();\'''');
});
// 自定义任务:重启 php-fpm 服务
task(''php-fpm:restart'', function () {
run(''systemctl restart php-fpm.service'');
});
// 自定义任务:supervisor reload
task(''supervisor:reload'', function () {
run(''sudo supervisorctl reload'');
});
// 自定义任务:部署成功了用 bearychat 发消息给大佬和自己
task(''send_message'', function () {
run(''{{bin/php}} {{release_path}}/artisan deployed'');
});
// 自定义任务:缓存路由,recipe/laravel.php 默认的流程里没有这个,所以加上,息看需要
after(''artisan:config:cache'', ''artisan:route:cache'');
// 执行自定义任务,注意时间点是 current 已经成功链向新部署的目录之后
after(''deploy:symlink'', ''php-fpm:restart'');
after(''deploy:symlink'', ''supervisor:reload'');
// 部署成功后重置 opcache 缓存
after(''deploy:symlink'', ''opcache_reset'');
// 部署成功后调用 laravel 命令行发送通知
after(''success'', ''send_message'');
// [Optional] if deploy fails automatically unlock.
after(''deploy:failed'', ''deploy:unlock'');
- 代码修改完成后运行部署
修改完成后记得先提交并将代码推送到远端仓库。然后执行如下命令进行部署:
vendor/bin/dep deploy debug // 部署到测试机
vendor/bin/dep deploy production // 部署到生产机
过程中如果提示要输入密码,则输入登录目标主机的密码。或者想办法设置 SSH key 实现免密码登录。
- 首次部署后设置 .env,并配置 nginx 站点
默认情况下,首次部署后,.env 文件是不会自动创建的,需要自己创建并修改,同时 nginx 站点配置也需要自己动手。对于 .env 文件,存放于目标主机的 /path/to/project/shared/
目录下。
修改 .env 后记得重新缓存配置 php artisan config:cache
另外需要注意的是配置 nginx 站点时,网站根目录应该为 /path/to/project/current/public
。如果使用 supervisor 之类的,相关的目录在配置时也要注意了。
部署后目录的结构及相关说明
在部署的目标目录下执行 ls -la
,可以看到如下结果:
说明:
| projectname
|--- @current -> releases/<num>
|--- .dep
|--- releases 一个文本文件,里面存着各次部署的时间、次数序号(或者说版本号)信息
|--- releases // 目录下根据配置保存近几次部署,更早的则会被自动清理
|--- 1
|--- 2
|--- .
|--- .
|--- <num>
|--- 目录中是项目的实际代码
|--- 包括 .git, vendor, .env, storage ...
|--- .env, storage 实际通过 symlink 链接到 shared 目录下对应的文件上
|--- shared
|--- storage // 即 laravel 项目的 storage 文件夹
|--- .env // 即 laravel 项目的 .env
每次部署更新,会在 releases 下新建文件夹如 num,拉取对应的最新代码,安装 composer 依赖完成一些其它自定义任务,并将 storage, .env 链接到 shared 文件夹下的那两个上去,然后项目根目录下的 current 通过 syslink 链接到这个新文件夹 num 上,这算是其动作的基本原理,网站在部署过程中能继续访问也得益于此。
.env 和 storage 下的一些未加入代码库中的内部,部署时不会自动更新,因此有些情况下需要手动处理。
其它日常使用技巧
正常情况下,部署过程中 deployer 会自动完成缓存配置、清理已编译的缓存等任务。理论上我们不需要自己再动手,但需要时也可以手动执行
// 缓存路由
vendor\bin\dep artisan:route:cache production
// 缓存配置
vendor\bin\dep artisan:config:cache production
// 清视图缓存
vendor\bin\dep artisan:view:clear production
// 执行自定义任务,如前面提到的重新载入 supervisor
vendor\bin\dep supervisor:reload production
// ssh 连接到主机,hostname 也可以不输入,然后从选项里选
vendor\bin\dep ssh <hostname>
// 列出其它一些可用的命令
vendor\bin\dep list
可能遇到的问题
在 deploy 命令后加上 -vvv 选项可以输出详细错误信息,方便调试。
- 由于部分 php 函数被禁用而报错
目标主机 php.ini
里的 disabled_functions
项里配置了一些被禁用的函数,如果 deployer 用到了这些函数就可能报错,修改 php.ini
解除相关函数的禁用状态就可以了。
- php 执行文件位置引起的错误
目标主要通过 apt-get 命令或 oneinstack 一类的一键包安装的 PHP,可执行文件通常在 /usr/local/php/bin/php
,而 deployer 内使用 /usr/bin/env: php 形式调用,相当于 /usr/local/bin/php
。这就可能出错,一般是报 command -v ''php'' failed
。解决办法很简单,只要加个软链接就可以了。
ln -s /usr/local/php/bin/php /usr/local/bin/php
- 目录主机不在线或者网络连接问题
解决办法当然是打开目录主机并检查网络情况
- 关于缓存清理
deployer 的 laravel 默认部署流程中,会执行 php artisan cache:clear 命令,如果你的项目里使用了 redis 驱动的队列或者一些强依赖于缓存的业务逻辑(如缓存文章阅读数定期再入库),则需要进行一些骚操作了。
比如,你可以在 config/database.php
的 redis
项中为队列链接指定其它的 database。
或者修改 deploy.php
配置默认的缓存清理任务,跳过缓存清理动作。(通常并不建议这么做,因为项目的缓存,应该是可清理的,如果部分业务确实十分依赖于缓存,则应该考虑一些缓存持久化的实现了)
// 覆盖 recipe/laravel 里默认的 artisan:cache:clear 任务,部署时不清缓存
task(''artisan:cache:clear'', function () {
return true;
});
原文地址
今天关于专访 | 今日头条2016 Byte Cup大赛实战经验分享:要充分挖掘模型本身的信息的分享就到这里,希望大家有所收获,若想了解更多关于2018 OSC 年终盛典,Flutter 跨平台框架实战经验分享、B2B网站SEO优化实战经验分享、C++ 递归实战经验分享:代码优化与技巧总结、deployer 实战经验分享等相关知识,可以在本站进行查询。
本文标签: