Hello world, again

Blogging is always something I cherish, something I always want to keep doing, however also something I never could keep doing on a regular basis. I registered the domain mudkip.me many years ago. As time goes by, I toggled between various blogging platforms and the most recent one is Tumblr.

I chose Tumblr because it’s convenient, fun and modern in 2011. Tumblr respects the ownership and personality of its users. It does social just right. However Tumblr is no longer great for me as a blog platform today. I have to use ‘display:none’ CSS to hide the banner to promote Tumblr app. I can’t get rid of a lot of tracking scripts. And I want more freedom with the domain I own.

This blog is now powered by Hexo, a powerful static blog framework. It’s hosted on GitHub and updated with Git. I set up a webhook to automatically deploy to GitHub Pages when I push my hexo repository. I’m also building an iOS blog workflow with Ulysses, Working Copy and Workflow. And as always, I love writing and I wish I could write more.

My previous posts is still available at Tumblr. They might be migrated here someday. :)

μ’sic forever

今が最高!

参加了4月1日上海浅水湾q.house的转播。

今年1月30日的上海Fan meeting结束后,充满满足和快乐的很长一段时间都没有Final会来临的实感,BD抽选没中后就没在意后来一般贩售,春节忘记把港澳通行证带回去续签也就没计划去香港看转播。直到传出上海浅水湾转播正在审批的消息和广州转播场的传闻才下定决心,如果内地有转播就要全力争取机会去看。

3月19日中午很紧张,校对好时钟把发抖的食指放在淘宝App购物车的结算按钮上然后默默倒计时,然而按下的时候已只有灰色的确认按钮。不过因为15分钟内付款的规定就一直不停刷购物车,重复了几次「刷到购物车亮了—结算—确认失败」的过程后终于在半小时后买到一张4.1 q.house的转播票。所以下一次即使没抢到也一定不要放弃希望。(嗯,还会有下次的。)后来和朋友聊起来被问到为什么不写个程序抢,我说毕竟信仰的事情是不能作弊的。

然后当天下午看到微博和贴吧里关于台北Fan meeting的repo,看到emitsun说「因为是最后一次了所以哭也没关系了」,看到台湾LLer的これから应援影片,终于有了Final来临的实感。一边是有幸看转播的兴奋和期待,一边是希望这一天晚些来临的不舍…这十多天一直持续着这样的心情。

这其间看到kssn和rippi的LA之行DVD里聊起未来的人生时的一丝迷惘;南酱说不知道Final之后,因为LoveLive!而喜欢她的粉丝会不会继续支持她;Pile在自己专辑里藏着的对小真姬的感谢;以及μ’s全员对Final LoveLive!的寄语,「我…我们追随着穗乃果她们的脚步,在有限的时间里尽全力绽放光辉」这句话从剧场版到访谈到Live重复了很多次,这就是LoveLive!这个企划的真谛吧。

终于到了3月31日晚准备出发,在地铁上看着第一日Live的文字直播结束终于有种悬着的心终于放下的感觉(其实更多是担心南酱的膝盖),火车上也因为复杂的心情很晚才睡着。


4.1当日,到达浅水湾的时候已经接近10点,场贩自然是没希望了,整理券排到了270多号。有些遗憾的是,由于这次转播票的供需严重不平衡的原因,现场除了Loveliver,也有一类很讨厌的人存在,下午入场时还听到楼下发生了很恶劣的事件,不过机智的staff和Loveliver很妥善地处理了。

排整理券的时候有位LLer小哥一直拿着一叠现钞走来走去说「2000元求出一张票吧」,有点让人心疼(后来贴吧有贴出他是某周边店的店长);下午也有很多没有买到票的LLer在门外应援。

中午附近的面馆一直在放LoveLive!的歌,还推出了所谓Loveliver套餐(其实就是普通的2荤2素)。开场前在楼梯听到有LLer聊到了fS的white forces和黑之宣告动画。

q.house这个比想象中还小的场地挤了近400人,转播开始前重复了几次「啊—(大概是手游抽到UR/SR)」然后全场举着荧光棒欢乐地喊「劝退!劝退!劝退!」;还以为自己的身高站后排也还好但视线前面有1.9m的同学所以有时候还需要踮起脚。


终于在欢呼声中PV动画开始了,剧情从音乃木坂学院的羊驼——生了小羊驼开始;然后说到举办Live的地方大家大声喊DOME,然后花阳用和剧场版一样的语气说「ドゥーム」,然后从1st的场地横滨blitz开始传递气球,直到东京巨蛋,中间好像看到了不少CP福利。PV动画中成员的家人们也登场了,妹妹组的出现的时候全场喊了「大法好」,然后妈妈们出现的时候全场包括身边一群女生都在喊岳母(23333)。

然后一单开场,当时想的只有「这些人好美啊好美啊好美啊」——并不是说之前看3rd4th5th和fan meeting没有这样的感觉,但是这次真的有特别的不一样的ギラギラ的感受,而且服装与其说是1单的服装更像是Final Single的服装或者1单的高清重制版(..)。然后OP1就是和fan meeting一样的幸福感。

然后自我介绍的时候就是惯例的ちょっと待っててー和Yellow哒哟还有だぢづでど和最响亮的唔—和Fight哒哟,森森森讲话的时候Pile好像在做什么的样子反正好像是糖(?)。因为在看转播,当听到「ライブビューイングの皆さん」的时候感觉完全和看BD不同,很幸福。彩彩在MC不知道为什么哭着停不下来,看着好心疼,大家应援了很多次终于用哽咽的声音说出了把你变成小鸟的点心,南酱和emitsun也一直不停地安慰,说完后彩彩就背对着舞台擦泪,有点担心也有点曾经见过的感觉。

转到南酱的时候很多人都喊了お帰り,エリチカ大概也是喊得最响亮的一次——终于回来了呢。然后是小楠的たっぷりたっぷり和期待已久的にっこにっこに~。

然后是夏色天台,哦不,夏色笑颜12跳,看到这里就想说soramaru好可爱好可爱好可爱,她从女神X变回了女神呢(当然这一首服装还原的梦想就永远不可能了)。接着HiHiススメ和友情不找零,不对,友情永不变,然后花车和南酱出现的一瞬间太棒了,记不清哪些成员抱了南酱www。

然后到了休息时间投影屏上开始放6年前开始的回忆,因为这时开始就是HP=1的状态所以蹲了下来…其实staff提醒是不许坐在地上的不过HP基础得点为0实在没办法。(..)

然后满怀恶意,不,爱意接近中的女仆装!女仆装!女仆装!,可爱的只能紧盯投影屏不知道荧光棒该怎么举了。说起来这场Live最大的亮点之一就是各种服装和现场的还原,真的非常用心。6单之后开始了动画歌曲的串烧。

Wonder Zone的时候镜头突然切到了花车上,南酱手里拿着两只羊驼毛绒出现了,小楠手里不知怎么也有了两只羊驼。Love wing bell的气氛好棒,大家一起喊变身,但是,但是如果我没记错的话,虽然只有几秒的镜头,但看到了妮姬偷偷十指相扣不小心哇的叫了一下。接着继续回忆环节。

To be continued之后是动画中的Dancing stars on me,虽然这次没有还原动画,但是女仆装上贴了一层南瓜好有趣,这次的服装设计师们真的要给1000个10ハラショー。kssn好可爱好可爱好可爱,Happy maker后动画串烧结束。

小队曲开始Printemps的服装还原了WAO-WAO Powerful day封面(继续赞服装师),中间MC的一瞬间emitsun露出了有点像盟约彼方(emitsun个人单曲)封面的冷酷表情,最后一首就是好吃好吃很好吃都感觉肚子饿了一下w

lily white最大的亮点就是全场变樱花,东蛋粉色和白色的全景就像樱花满开一样,当然我们转播会场的樱花也盛开了。这里想起了5th上kssn生日吹蜡烛的情景,其实不仅snow halation,LoveLive!的很多细节都是「大家一起实现的故事」呢。

然后是期待已久的BiBi,其实本来以为第一天有小队曲还在遗憾第二天大概看不到了,Psychic fire就是都在疯了一样乱喊,脑子里只剩下bibibibibibibi了。最后空丸像4th一样请南酱带BiBi call,然后Pile然后空丸自己,这时候的心情大概只有快乐和兴奋了。然后错觉Crossroads也很棒,对了lily white和BiBi的服装也都特别特别棒。

终于是剧场版的Angelic Angel,服装再度完美还原,南酱太美了太美了太美了,全场一片水蓝色的应援,所有的舞蹈也都和剧场版动画中完全一样,太棒了——然后最棒的最意外的是海未头上那两个圈的完美还原,mimorin太棒了太棒了!然后辉夜城和噫无情,周围有人起哄说「要看下楼梯了」不过没有注意到,虽然投影屏并不大但一直实在太美了不知道该看哪里w

然后回忆到了动画二期,这里开始有些虐心了,没有完全听懂emitsun说的话但好像提到了动画里毕业和解散的事情,to be continued。

不过马上就开始欢呼了,剧场版的年级曲开始,rippi出现的一瞬间总觉得不是rippi而是凛酱本人——说不清的感觉,其实整场Live都觉得她们9人与她们9人已经完全融合了,那个μ’s有17人的梗已经不在了因为只剩下9人——Pile从一辆Taxi里出来,小鹿从椅子上站起来,都完全和剧场版一样,对了服装也完全还原了。

然后三年级搞笑组合(搞笑组合不是BiBi么),从墨镜到表情到动作都很疯2333——哎我怎么就这么喜欢这群家伙啊。二年级一家的校服也好棒,咦之前的Live还原过校服么。

接着她们换上了Sunny day song的服装开始了「这是我们的奇迹」,这首听过最多的歌,大家的应援也非常整齐,不过和红白一样只有8人。然后9人版的ミはμ’sicのミ,最后大家都跟着喊出「忘れないで 君と僕の足跡」。然后Super love super live又是非常燃,终于No brand girls的时候气氛达到了顶峰,之前有点难过的心情也完全散去了,只有一进一跳,hihihihi、oh yeah和全心全灵的喊声,也因为一点特别的原因,No brand girls有点特殊的意义。

不记得这个环节的哪里,kssn跑着冲到南酱怀里,大家眼睛都被闪瞎了。最后是同样很期待的Sunny day song,舞步也和动画里完全一样非常美。不过教学比起ミミミ难了不少,32手势没有做出来。


Encore是START:DASH和Snow halation,第二次成为奇迹的橙色海洋的一部分,后来媒体放出现场摄影图华丽极了,微博上有和1st的现场对比,我们10人真的从那里走到很远的地方了啊 :)

和Fan meeting一样又是从どんなときもずっと开始就控制不住情绪抽泣,也几乎没办法跟唱,真的对这首歌一点抵抗力都没有。说起来今年每隔一个月都哭了一次(1月Fan meeting,2月宝可梦中文化,然后Final LoveLive!),这种幸福和苦涩交织的心情不知该如何形容,大家应该都懂吧。

到MC的环节,心情已经完全和Encore前不同了。听到rippi说“凛酱看到了吗?我做到了啊!”的时候全场泪崩,身后的两位女生大哭起来然后蹲下了;小楠问“喜欢LoveLive!吗,喜欢μ’s吗,喜欢希吗”大家都很用力的喊「大好き」;Pile说μ’s,然后大家哭喊“愛していばんざーい!”;南酱说绘里她们过了今天也还在某个地方生活着;森森森说和园田海未相遇真是太好了;彩彩说今天不是饰演南小鸟,而是要成为南小鸟;emitsun说穗乃果她们9人,我们9人都是在有限的时间里,尽全力去绽放的光辉,但「私たちはずっとμ’sです」,我们永远都是μ’s,然后说虽然形式会改变,虽然还不能约定下来,但总有一天我们还会再相见,只要大家心里记着μ’s,μ’s就会一直存在。

有这句话就够了,有这句话就够了。MC的环节她们都很坚强地忍住眼泪,没有说离别的话,大家又一次喊了Fight哒哟。终于是最后一曲,μ’s的Final Single「Moment Ring」。这首里屏幕上有成员和角色在一起做出相同动作的画面,不舍的同时又有一点暖意。


然后是哭声和嘶哑的喉咙喊出的もう一回,然后出现了成员的感言,这里记得最清楚的是空丸说很多年后大家去卡拉OK也会点μ’s的歌就好了,然后是忧伤的bgm和6年的回忆,身旁每个人的脸颊都是泪光。

接着是剧场版最后仆光的报数,大家小声跟着说1 2 3 4 5 6 7 8 9之后用最大声喊出了10,μ’s music start!莲花舞台升起,花瓣展开,9人出现在花瓣上,完全再现剧场版的Ending。

东蛋和转播场的大家都全程跟唱了这首歌,尤其是用尽全力去喊的「今が最高」,因为现在最好了是最真实的心情。结束后,跟着bgm大家又跟唱了一次,台上9人也和大家一起喊了「今が最高」,然后一切都结束了。

东蛋里灯亮起来了,但没有人愿意离开,当音响里传出微弱的声音时我们也一起喊「μ’s!μ’s!μ’s!」,希望她们能再次回到台上。然而之后投影屏上只有本次转播已经结束的提示。

后来q.house里和Fan meeting时一样合唱了一小段爱万岁和最后的lalala lalalalalalala,然后一段掌声然后对staff说了お疲れ様。

走出剧场就像做了一场梦,只是没有人愿意醒来。浅水湾楼梯和场外大家喊了很多μ’sic forever,喊了很多今が最高,又合唱了一段爱万岁,合唱了一段snow halation,终于渐渐散去。


晚餐时发现喉咙完全发不出声音了,只能用手指点餐;回到酒店心情很复杂,有种无助的感觉有种失去了什么的感觉。明明是第一次看到μ’s完整的Live,本应是非常幸福的事情,为什么会变成这样呢。

第二天中午返程,经过检票口后发现上海开始下雨了——这两天的天气与和1月30日及之后的第二天完全一样。不过在火车上补了一期希绘里花园广播,补了一期果海鸟+妮生放送,在Twitter看到她们在Live结束后的事情,心情就完全恢复了。

是啊,μ’s原来从来都没有离开,只是她们的奇迹和梦想已经完全实现了;6年里发生的事情,还有很多需要补习;未来的某一天,总会再相见的,嗯。


南酱去做了印有LOVE、LIVE、水蓝色和μ’s9色图案的指甲。

没有Twitter帐号的小鹿在Instagram画了写着μ’sic forever的气泡(最后的画伯属性呢),一年级感情很好的rippi和Pile很快帮她转到了Twitter。

空丸在blog里说Final LoveLive!的庆功之后,μ’s9人许下了今后也要定期会面的约定。

三森和空丸所在的milky holmes组合宣布了新的活动。

小楠没有休息,马上开始二专和新声优出演的工作,看到她努力和忙碌会有些安心呢。

Emitsun和彩彩今天去了新宿一家影院的重播,她们第一次不是作为μ’s在台上看到,而是作为第10人的Loveliver在台下完成了Snow halation的变色。

日本文部科学大臣馳浩先生受Bushiroad社长邀请穿着Final LoveLive!的场T去看了两天的Live,之后他说「希望东京奥运会的开幕式或者闭幕式能邀请到LoveLive!」。

赐予μ’s名字的御儿勇马今天在神田神社的绘马写下「μ’s Final LoveLive!成员和工作人员都辛苦了!GS杂志还在连载9人活跃的漫画,大家不要错过!」。


另外想谈一点成为Loveliver的经历吧。其实从前对追星啊偶像宅啊爱豆啊没有什么概念甚至不太能理解,第一次觉得「アイドル」好厉害的时候,大概是看到一位宝可梦节目主持人姐姐写的一本书,发现原来成为アイドル的存在的人,也是有很多和自己相似之处,喜欢同样的事物的普通的孩子。

14年初第一次看了一部有关アイドル的动画,大家当时谈论更多的是有关某个失意的监督的事,不过很喜欢那部动画,以及为了纯粹的梦想而努力的心情。后来LoveLive!已经逐渐成为了话题,无论是好的意义上还是不好的意义上。由于「想要看看LoveLive!为什么会被成为邪教」的好奇心驱使,在14年秋补了两期动画。

然后就被感动了。然后去开始玩手游,虽然直到现在也还是手残(笑)。14年跨年时看了那个LoveLive新年特番,第一次见到了声优9人当时还不能完全记住名字,但记得她们说想要去海外开Live,想要周榜第一,想要9人一起吃饭,然后记得真姬的声优说想要LoveLive!的活动能延续到2016年,今天这些都实现了。后来去看了4th视频,看到「居然可以这样」的橙色海洋,然后就彻底地成为Loveliver,但是lantis祭已经没有机会去了。

但之后就很想去一次Live,想要在真实的世界寻找梦想和奇迹,后来第一次去听Live是去年6月的初音未来Expo;后来11月去了日本,去了秋叶原和神田神社巡礼,在神田许下了「想要去μ’s的Live」的心愿。


願いを抱いて 紡いでゆく夢の糸 きらきら
素敵なことさ ほら心はつぎの物語をさがして
君は光をどこまで追いかけるのだろう
一緒に見ると決めた輝きは 胸の僕の宝石になったよ
ああきっと君も…おなじ気持ち…!

作为μ’s的第10人,我们和她们一样已经走到了很远的地方。
无论是和她们相遇的近两年来,还是从6年前开始,都可以自信地说自己走在梦想中的道路上,并且实现了很多梦想。
今后,为了再见时是能自信的说「我成为了更好的人」,为了让她们有一天能比东京巨蛋的两日更加闪耀,继续为了自己的梦想努力,并继续支持她们的个人事业吧 :)

μ’s Fan meeting in Shanghai

之前提到过一件事,11月时去了秋叶原的神田神社,在神社参拜的时候,心里一直在默念「μ’sのライブ行きたい」,说起来那是第一次在神社参拜,只是模仿着周围人的动作。

然后1月30日这个梦想实现了。


彻底觉得自己成为了LoveLiver的时刻,大概是近一年前看4th Live的视频,看到Snow Halation从白色变为橙色的一瞬间。

然后1月30日,自己成为了那片橙色奇迹海洋的一部分。


然后是很多记忆的片段。

  • 9时从北京南站出发,14点抵达上海,16点到了梅奔现场不过场贩的CD已经买不到了(据说错觉CROSSROADS提前到早6点排队都买不到)
  • 遇上了11月bilibili东京团的小伙伴,还有借KBX棒连接线的LLer帮我们调整了配色;之前只设置了9色,还担心换色按错,原来白色两边都设置为橙色就没问题了(好机智!)
  • 附近很多地方都在循环播放μ’s的歌,连剧场版的歌也听到了;梅奔的会场也在循环着9色。在等入场的时候有阿姨问了我们今天有什么活动,解释了一番后阿姨一脸迷惑地说「真好呢」
  • 有很多LLer在发call本和「爱上你万岁」的歌词和合唱注意事项,现场看到各种各样的战袍和痛车
  • 入场前大家就开始跟着背景音乐练习,在snow halation的时候就完成了很整齐的换色,那一刻全场一阵欢呼。那是第一次在现场看到这个奇迹,因为想着「开场前都可以做到这样了,真正的snow halation一定会更棒呢」所以欢呼起来了w,后来小姐姐也提到了
  • 「这是我们的奇迹」开始的一瞬间,无法用语言描述的激动会永远记着的
  • 自我介绍的时候里P果然十分熟练,用中文说出了「星空凛」和「饭田里穗」;Love Arrow Shoot全场扑的一下十分整齐;一开始空丸好像有点紧张,niconiconi都忘记了;EMI接过话来全场「唉?」了一下空丸才想起来于是一脸不知所措的(可爱的)表情
  • 第一个Talk环节是介绍自己的角色与喜欢的动画场景,里P一开始就拉面拉面拉面直到大家提醒她要介绍凛酱而不是拉面,里P最喜欢的是凛和妮可追着松鼠摔下山的蠢萌场景。另外这次翻译姐姐很棒,也是Loveliver自己人
  • 三森介绍海未的时候用中文说了「大和抚子」,可是全场大笑于是三森继续各种颜艺;说起喜欢的场景是海未抱怨演出裙太短的时候,三森自己也会经常对造型师说要把裙子做的更长,这一点上两个人重合了
  • EMI说穗乃果就像一个leader一样勇往直前,最喜欢的场景是ススメ→トゥモロウ,然后吐槽说不要学动画里在路上唱歌www
  • 彩彩自我介绍的时候全场抗议了一把官译,彩彩说「原来ことり的汉字是琴梨啊,也蛮可爱的」,全场一片「唉?」然后把荧光棒比划成x,然后彩彩很可爱的模仿小鸟振翅全场欢呼,「果然是这个ことり啊」。虽然因为有一部分神奇宝贝的原因比较倾向支持官译,但这样可爱的互动也很有趣不是么。后来日香也有完全相同的画面
  • 彩彩最喜欢的场景是三个人的First Live,提到后来μ’s的其他成员当时也在那个几乎空无一人的场地里,想起后来无论动画中还是现实中她们取得的成功,都是从那里开始的;另外还记得自我介绍让海鸟党大满足ww
  • 然后Pile的发言是毫无预警的爆炸。之前看过EFC和其他生放送总觉得Pile是就像傲娇的真姬一样提到妮姬就转移话题回避,当Pile若无其事地说「不知不觉妮可就一直在真姬身边了」全场就很长一段时间欢呼,以及一片红色和粉色荧光棒的海洋,换色后抬头看舞台Pile和空丸已经一脸幸福地抱在一起了www
  • 然而这里并没有结束,Pile说最喜欢的场景是花阳来到真姬家的时候;右边的妮可脸色瞬间变了,喊了声「妮可都没有去过!」然后两人就开始了磁力花园的「看这里干啥」…不过过了几秒她们就和好了然后手牵在了一起www…于是全场又一阵粉色和红色的欢呼
  • 最后德井妮可自我介绍的时候因为补充了很多マキパワー所以完全不紧张了,提到刚才忘了niconiconi就补上了一次让大家满足,不过这次是模仿凛的「说起妮可的话?」然后妮可喜欢的场景是扑到妈妈怀里的时候,展现出大姐姐的妮可撒娇的另一面呢。另外在翻译的时候,空丸的嘴巴也一直在动,让全场爆笑(果然是搞笑艺人)
  • 在读信的环节,有LLer提到希果百宝箱里EMI说了中文「牛奶」,然后EMI说在她中学时,曾经问一位中国交换生的男同学牛奶用中文怎么说,于是就一直记得这个词…求全场果厨的心理阴影面积
  • 另一封信中提到他们全班有1/3的LLer,于是彩彩说真好呢,如果1/2的同学都是LLer就更好了所以加油布教吧ww最后一封信是问最难的舞蹈,彩彩出来示范了一番,摄影师也好棒(
  • 接下来的环节是quiz,里P这时候(其实从一开始也是)就像大姐姐一样安定地介绍了游戏规则和上海的土特产,虽然是μ’s中最小的动画中也只有一年级,但大家都能感受到她像love wing bell中的成长吧
  • quiz的问题有「中文中勉强是什么意思」「哪个不是上海的名产」「穗乃果衣服上的字是」「μ’s所在的社团是」,有一个「偶像学习部」的选项,空丸就立刻现学现卖说「唉?如果叫偶像学习部的话,中文里不就是我们勉强着做偶像的意思了么」
  • 最后四道题毫无意外的答对,小姐姐们抱走了大白兔奶糖、梨膏糖、中国结、大闸蟹味的百力滋、中国茶等土产
  • talk结束的时候EMI说Fan Meeting要用当地的方言说「开始」,于是全场一起用中文喊出「开始」
  • talk和live中间屏幕上在放「μ’s推荐的适合做家务的时候听的歌曲」,当出现南酱和绘里的名字的时候,虽然只有很短的一瞬间,但全场一片欢呼并且看到了水蓝色的海洋;后来小鹿和くっすん的名字出现的时候也是
  • Live有OP1、1单、宝物、No brand girls和Snow halation,大家都很努力地应援,大屏幕上有几次出现了场内的画面真的非常绮丽。no brand girls的时候一直在喊的oh yeah与hi hi hi以及像4th的教学一样大家作出拍照的手势都非常整齐,snow halation变色的一瞬间,就像置身在琦玉超级竞技场
  • Encore是ミはμ’sicのミ与どんなときもずっと,ミミミ的教学环节之后EMI说请不要打到旁边的人(然后戳了三森的脸);不要戳到前面的人(然后戳了三森的背);不要抱到前面的人(然后抱住了三森)…果皇你是借机揩油吧www
  • ED2有一瞬间屏幕上出现了6个人手持羽毛的画面,然后舞台上的6个人的手上也不知如何出现了羽毛,突然就泪奔了;享受到了这一刻真的太好了,两个多小时的时间对全场几千人来说,一定是最棒的回忆呢
  • 结束后大家都自发把荧光棒切到红色,然后合唱了「爱上你万岁」开始的一小段,虽然由于会场广播等原因合唱并没有太成功,不过大家的心意一定传达到了

回酒店后看到大家一致的好评,小姐姐们也很开心地玩着赠送的腕表,bushiroad的社长在Twitter上也说「有种在日本Live的错觉」。梦想实现的时候,「それは僕たちの奇跡」

第二天去了复兴中路523的 LoveLive! Cafe,11月来过的相同的地方,当时是初音Miku主题餐厅;没想到过了不久就有幸又来到这里。在Maki的桌子上果断点了Nico的套餐,一直以来希冀的蛋包饭和「变好吃的魔法」也终于实现了www

2月1日结束旅行离开上海,在浦东机场找到了Fan Meeting上看到的同款大白兔奶糖和梨膏糖,不过只看到一家店有卖百力兹但一问大闸蟹口味的已经卖光了。

虽然已经过了3天,手臂的酸痛还记得1月30日所有的幸福,然而也不禁想起,工作忙碌的她们9人,已经开始为6th排练的她们9人,5年半来的辛苦,尤其是膝盖有伤的南酱。

みんなと出会えたこと嬉しくて
離れたくないよ本当だよ
涙はいらない このまま踊ろう
手を振ってもっと振って
光を追いかけてきた僕たちだから

现在回忆起仆光的旋律已经不再感伤了,因为已经经历很棒的梦,因为いまが最高。

Letters.

You’ve always been kind of a brat, Fennekin. But I’m jealous of the way you’re chasing your dreams. –Lombre

Try not to eat too much. Take care. –Raticate

Ven you are feeling lonely, remember ze village. –Hippopotas

A child’s dream can’t be destroyed by adults. Best of luck to you. –Simipour

Let’s see, how can I put this? Even if you were problem children. If you work hard, maybe you won’t be so problematic. And on that note, good luck! –Watchog

Good luck. Feennekin and Swam, I believe in you! –Audino

I was quite surprised when I heard the news yesterday… I’m glad you opened up to me! Good luck! –Farfetch’d

Good luck! Follow your dreams! –Sunkern

School is important, but it’s important to go after what you want in life, too! Take good care of yourselves… and good luck! –Roselia

We have a shop in Lively Town, too. So you have nothing to worry about! Good luck! –Kecleon

Time to let these cute kids fly away on their journey! Hy-krah! –Hawlucha 

Be brave and never give up! Take care! And good luck! –Kangaskhan

Go on, Fennekin. See you when you get back. Your adventurous spirit can’t be contained. If you think you’re ready, go see your dreams through to the end. –Carracosta

Good luck to you, Swam. We just happened to meet, and you came to live with me… I reckon it sure enough was fun havin’ you around, Swam. I reckon I can’t help but worry. But I’m cheerin’ for you. Take care. –Nuzleaf

2015.11 关都地方圣地巡礼记

从很久很久以前开始,「去日本旅行」就是一个非常非常重要的梦想,但因为总有一天会去实现,就一直没有付出行动。不知不觉时间已经到了2015年,终于在堆积了越来越多的愿望后,去办了护照,然后去找合适的旅行团,然后去Bilibili报了名,然后很快到了出发的日子。

Day 0

浦東空港 → 成田空港 → 秋葉原ホテル → 秋葉原ツアー(STEINS;GATEの巡礼/そば屋/メイド喫茶店/ポッ拳を遊ぶ)

11月13日清晨,仍然沉浸在一周前ASCOT之行的快乐回忆中,一边刷着久违的任天堂直面会情报,清醒过来的时候已经和几个同行的小伙伴集合,抵达了浦东国际机场。在Bilibiliyoo大白带领下领了随身Wi-Fi路由,换了日币,然后办了乘机手续,过了安检,乘上了一架波音777飞机。

说起来,这次旅行不仅是第一次出国,也是第一次乘飞机的经历。虽然想要装成不是第一次的样子,但降落的时候没有经验弄得耳膜好痛。下午3点多钟抵达成田机场,入境后就看到了漫游娘的旗帜和接下来几天带领我们的老司机。

然后乘京成电铁的车票抵达市区,从上野站走出看到地面的时候,虽然不到5点钟,不过由于冬天的原因已经天黑了。

乘JR来到了秋叶原,由于酒店就在秋叶原的中心,所以有充足的时间可以游览这个御宅圣地,同时秋叶原也是「命运石之门」「Love Live!」「俺妹」等很多作品的取景地。办理入住手续后,老司机就带我们游览一圈。

在JR车站不远处就看到了「世界的广播馆」,命运石之门中整个故事开始的地方,现在楼顶已经没有了5年前出现的时光机。

原来消失的是时光机被搬运到了这里。另外,整个秋叶原随处可见新作「命运石之门0」的宣传海报,然而想到PV里消失的助手和封印的凶真会有一点心酸呢。

逛到一家荞麦面馆吃了晚饭,说起来虽然秋叶原并不是吃货的圣地,但这几天吃到很多好吃的面已经很满足了w。接着去@home cafe女仆咖啡店喝了美味的抹茶拿铁,啊我才不会把合影交出来www。

走一家电玩店门口看到小朋友们在玩神拳于是就冲了进去。街机在日本仍然非常有活力,画面完全不输家用机。玩了几场对战感觉太棒了,尤其是假面皮卡丘。嘛期待Wii U版~

最后路过的一个卡拉OK店看到了「请问你要来点兔子吗?」中的纱路酱。

iOS 的 hitTest 和 pointInside 小结

iOS 应用中,处理和触摸有关的事件是一个必不可少的工作。UIKit 本身提供了丰富的常用 UIControl 控件,如 UIButton、UISwitch 等,使用这些控件时只需用 addTarget:action:forControlEvents: 或在 Storyboard 拖出一个 IBAction 就可以轻易实现事件响应;另外,各种各样的 UIGestureRecognizer 也可以为任何 UI 元素添加手势,实现所需的事件处理。

然而,许多场景下需要 App 干涉的 UI 元素的事件响应过程。例如,某个 UIButton 在设计中 frame 很小,而希望它的响应区域更大;或者,App 需要在某些情况下忽略 UIView 的层级关系决定响应 Tap 的元素。

iOS 采用一种叫 Hit-Testing 的方式决定接收触摸事件的元素,并提供了 hitTest:withEvent:pointInside:withEvent: 方法允许 View 决定自身是否接收事件,或具体接收事件的 subview,两个方法第一个参数均为一个相对于 View 自身 bounds 的 CGPoint

一般来说,UIView 在响应到触摸事件时会进行如下判定,同时这也是 hitTest:withEvent: 默认的实现:

  • 调用自身的 pointInside:withEvent: 方法
  • 若返回为 NO,则拒绝接受该事件,hitTest:withEvent: 返回 nil,Game Over
  • 依次调用自身所有 subview 的 hitTest:withEvent:,调用的顺序从最上层的 subview 开始,直到最底层的 subview 或中途返回了非 nil 的 UIView。
  • 如果在这个过程中遇到了非 nil 的 UIView,则把这个触摸事件交给它,自身的 hitTest:withEvent: 也会成功返回这个 UIView,到此为止。
  • 如果所有 subview 的 hitTest:withEvent: 方法返回均为 nil,则自身处理这个触摸事件,hitTest:withEvent: 方法也会返回 self。

pointInside:withEvent: 默认实现想必正如字面意思,判定触摸的 CGPoint 是否位于自身 bounds 内。另外需要注意的是,userInteractionEnabled 为 NO 的元素不会响应事件,如 UILabel 和 UIImageView 默认为 NO。

回到之前提到的场景,当 UIButton 自身 frame 过小,如何扩大它响应触摸的区域。一个最常见的做法是改变它的 frame,同时使用 imageEdgeInsetscontentEdgeInsets 等方式为它增加 padding,使 UIButton 的 frame 扩大而不增大它其中的内容。

但个人认为这并不是一种非常优雅的方式,设计师同学在设计时,考虑的一般是内容边缘距离父级元素或同级其他元素的距离,对应到用 Auto Layout 开发时,也就是一个相同数值的 NSLayoutConstraint。但若为了改变它的事件处理而改变 frame,配置约束时就会变得复杂和混乱。

而重载这个 UIButton 的 pointInside:withEvent: 方法就可以很好地解决这个问题,由于这个方法的第一个参数是相对于自身 bounds 的 CGPoint,只要判定这个点位于自身 bounds 外围指定距离内的 CGRect 内时返回 YES,就可以在 UIButton 外围响应触摸事件。

横滑滚动多个可以纵向滑动的 UIScrollView(UITableView)也是很多 App 中一个经典的交互设计。而若当这些纵向的 UIScrollView 需要一个公共的 ‘headerView’,并且在它们上滑的时候,希望 UIScrollView 中的内容能遮盖或推走这个 headerView,甚至这个 headerView 还存在可以响应事件的按钮的时候,问题就变得稍微有点微妙。

由于这个 ‘headerView’ 并不希望它属于每个纵向的 UIScrollView,不随着横向滑动而移动,所以它应当独立于横向滑动的 UIScrollView(UICollectionView)之外;由于希望纵向的 UIScrollView 滑动时可以用内容遮盖 headerView 的内容,所以它的层级应该位于横向的 UIScrollView 之下;另外,纵向的 UIScrollView 应该用 contentInset 或透明的 tableHeaderView 让下层的 headerView 露出来。

看到这里,我想很多同学会疑问“为什么不用两个纵向的 UIScrollView 嵌套起来”,不过想象一下在滑动内层的 UIScrollView 如何处理就变得头大了吧。

此时,这个 ‘headerView’ 由于位于下层,无法响应事件,如果其中有 UIButton,也无法被点击。而利用重载横向滑动的 UIScrollView hitTest:withEvent: 方法,在点击区域位于“本应属于 headerView”的位置时返回 nil,就可以很好地解决这个问题,它的 superview 也自然会把这个事件交给下一个 subview,即这个 headerView 来处理,而这个 headerView 亦会把事件交给对应的 UIButton,最终完成按钮的点击。我在处理这个问题时利用了一个透明的 tableHeaderView,在 hitTest:withEvent: 中调用了它的 super 方法,如果拿到的 UIView 正是这个 tableHeaderView,就直接返回 nil,否则返回 super 的结果。

关于这两个问题,我写了一个简单的 Demo,需要的童鞋可以移步 GitHub,有不同的想法欢迎扔 Issue : )

Parallels Worlds.

「如果说,有一个和我们所在的世界不同的丰缘地方,神奇宝贝的进化有点不同,也许不存在超进化,也许三千年前没有那场灾难。」——那同样是一个不能破坏的安宁的世界。

「或许存在另一个世界,你阻止了的人是我。」——在他的梦中,被唤醒的超古代神奇宝贝是另一只。

祐树来到未白镇的这一天,神奇宝贝多功能领航员上出现了未曾谋面,但却熟悉的面孔,通信画面上接下来的一言一行,都似记忆深处早已发生的真实。110号道路与小遥的对战,在强烈的既视感之中「再次」完败——唯一不同的只有沼跃鱼倒下前的神态。

在历史的长河中,总有许多命运的分界点上,自然亦或某个生命做出不同的选择,产生了错综复杂,但又相似收束的世界线。在某个时空中,紫菫没有成为室内都市,但那里的游乐场也没有因不能说的理由关闭;在某个时空中,关都四天王有不同于正义使者的过去;在某个时空中有会说话的喵喵和两人组成的三人组。

每一个生命都或多或少有种「命运探知」的能力,相信不只是曼珠、主角和敌对组织首领,每个人都有过Déjà vu的体验。如AG086,一个时空中某个虚构作品,恰是另一个时空的真实。如果能读到其他世界线中自己的记忆——甚至像XY036中一样,和另一个自己见面,一定可以「创造」或者「改变」什么。

2014年接触了很多平行世界题材的作品,Ever17的轮回,Virtue’s Last Reward的选择,命运石之门的跳跃;那些为了重要的东西努力改变世界线的故事,每一作都有很深刻的感动。至ORAS变幻篇章的最大收获,不仅仅是坚持「相信」喜欢的世界的存在,而且对于「哪一个」才是「真实」,也有了答案。

不过呢,在这个世界线变动率附近的范围内,现在这个数值就刚刚好呢: )

圣诞快乐。

参考:AzzyFox

Sootopolis

In Sootopolis City, after the end of the extreme weather event.

Finally, it’s just two of us again.
I’ve got to say…thanks for everything you’ve done for our region, Swam.
You know, I thought we were supposed to have set out from Littleroot together, but…
But you, Swam…
It seems like you just keep getting further and further ahead of me…
I even started to feel like you’d gone somewhere I can’t even reach.
It’s pretty lonely, you know?
Not!
What would you think if I really said something like that?
Hee hee!

My dear May. Do you know what I’m thinking?

I mean, everything I were able to have done, begins with our first battle near the pool of Route 103, just like you said in Lilycove. I were merely a careless boy who knew nothing about Hoenn, but you welcomed me with the most beautiful smiling face on that day, and taught me how to battle, how to creep near Poochyena. You helped me and encouraged me every time.

I never feel I’m ahead of you. When we met at Lilycove, I noticed your Pokédex was nearly completed. You must have made great efforts to achieve this, and that’s the thing I lag behind you a lot. You are my best friend, and you are never alone.

So…When our journey comes to a new chapter, I wish we get back to Littleroot together, and I want we understand everything about each other and our Pokémon and share our journey together.

And…May we be together forever.

Zero Escape: Virtue’s Last Reword

一周多前终于完成了3DS上的「Zero Escape: Virtue’s Last Reword」(極限脱出ADV 善人シボウデス)这部作品。40小时的游戏时间过后,虽然很多谜题和真相解开了,但是留下的困惑和谜题更多了,希望续作(如果有的话)能够一一释疑吧。

两年多前玩过DS上的前作「9小时9个人9之门」;VLR本作是美版发售就买来了,但因为等Bug修复补丁等了很久(现在也没出)加上胆小不能在平时玩(?)就拖了一年多,然后最近终于想起来一定要体验这作,差一点就错过了。

故事发生在2028年12月25日,前作的一年后,主角和其余8人被绑架到神秘的设施中,被迫参与密室逃脱以及囚徒困境的AB(Ally or Betray)游戏。9个人在游戏开始被佩戴了计数为3的腕表,当在进行几轮AB游戏后计数达到9时就可以脱出游戏,而计数小于等于0时则会遭到「处罚」。和前作一样,这场脱出游戏只是精心设计的密谋,并不是故事的真相。

以下内容涉及剧透,没有玩过本作品的同学请直接前往任天堂3DS eShop商店购买(或PSN购买Vita版),在完成全部结局后再回来看吧。这里推荐下载版是因为传说3DS版有在某个密室(PEC)存档可能损坏存档的Bug(其实我觉得也可能是Feature),下载版可以随时备份存档避免悲剧发生时的损失。

希望

其实一开始对极限脱出系列有兴趣有制作商Spike Chunsoft的原因,某种程度上「9小时9个人9之门」能找到「神奇宝贝不可思议的迷宫 时/暗之探险队」的影子,剧情中贯穿着隐藏的线索,时间和空间的融合,以及真相结局中包含着的「希望」。

两年前玩999的时候,相当喜欢「四叶草」的设定,四叶草书签的希望·信赖·爱·幸运是大家最终走到真相所必需的东西。而本作也有「希望」的要素,日文标题中的「シボウデス」可写作「死亡」不过也可以写作「志望」吧。

但是游戏的结局并没有看到「希望」,更多的是一种「宿命」的束缚,意识回到过去的Sigma的阻止根号6病毒扩散拯救世界的努力失败,而对45年间的Sigma来说,这一切是过去发生的事实,也因此(?)需要付出45年的努力实施阻止根号6病毒扩散的AB计划。

本作四叶和Alice登场的原因仅仅是为了增幅Sigma和Phi的能力,加上四叶的结局一如既往(?)是最惨痛的多少有些遗憾。但是四叶的人设依旧喜欢就是了,对于主角某些不合年龄(?)的表现的反应也是有趣的地方。

视点

在最终章「Another Time」中玩家的视角变成了K,但K却知道很多他「不该知道的事情」,茜最后表示「你不是K,你不需要遵守我们的规则,你是我们的系统里一个独特的变量」的时候,瞬间想到了打越钢太郎另一部作品「Ever17」中的设定,然后看到Wiki中讲PSV版中完成最终章的成就叫做「A Certain Point Of View」证实了我的猜测。

「我」就是「视点」,四次元生物「Blick Winkel」,在Sigma博士的影像中其实也暗示了更高次元智慧的存在;但是无论如何套用Ever17中Blick Winkel的所作所为,并不能拯救VLR中的世界,比起挽救两个人的生命,改变整个45年的历史对「视点」来说要难得多。

薛定谔的猫

Reality is shaped by what we believe reality should be.

在接触这作很久之前我就是薛定谔的猫的不科学解释(?)的支持者,因此从来回避体检一类的事情。本作引出了薛定谔的猫(如果外部世界是装着猫的盒子,这个密封设施是观察者),Phi线中也应用了一次这个理论(茜这次并没有被Dio所杀),最终章Alice说茜提到了解决悖论的办法就是「薛定谔的猫」,不过如何应用薛定谔的猫来拯救世界就要等到续作了。

Bluebird

Bluebird是Sigma送给Luna的音乐盒,来源于「メーテルリンクの青い鳥 チルチルミチルの冒険旅行」,包含了笼子里的鸟、幸福得而复失的寓意。

2028年12月31日究竟发生了什么,E路线的世界是否可以存在,Santa在做什么,Phi的真实身份等等谜题都需要在下一作中揭示。但由于日本销量不佳的原因,Spike Chunsoft暂停了极限脱出第三作开发。玩家为了表示对系列的支持发起了Operation Bluebird行动,很短的时间内就得到了上万支持;打越钢太郎目前正在进行其他作品的工作,如果顺利的话,之后极限脱出第三作恢复开发并不是不可能。

所以相信VLR续作一定会登场,比起整个AB计划,Operation Bluebird的成功要容易得多呢。

如何用得起 MediaWiki

MediaWiki 最初为运行维基百科而设计的开源程序,目前服务于超过一万的 Wiki 站点。神奇宝贝百科自2010年9月起运行于 MediaWiki,3年多来积累了很多心得,虽然内容和访问量迅速增长,但服务器开支依然保持在负担得起的范围。水跃希望在这里记录和分享。

日志标题中「用得起」的假设是运行在一台 1GB RAM 虚拟(云)服务器,日页面访问量在一百万以内。市场上 1GB RAM 的 VPS 价格约 10 ~ 30 美元每月。MediaWiki 并不适合运行在共享虚拟主机,或内存不到 512MB 的服务器中。

另外,MediaWiki 官方网站提供了一些基本的优化方式,非常值得参考。

MediaWiki 很耗资源么

是的。相较其他流行的 PHP 开源应用,MediaWiki 可以认为更耗资源,尤其是 CPU 使用,一篇包含复杂模板嵌套的文章,在无缓存状态下的渲染时间可能长达数秒,甚至数十秒。

经历了十多年的发展,MediaWiki 也是一个架构设计优雅的工程,具有非常强大的功能和可定制性,其性能开销往往是必要的。合理运用多重优化手段方式,可以有效降低 MediaWiki 的性能开销。

使用高性能的 Web 服务器程序

如果在生产环境使用最新版本的服务器程序,往往会引起很大的争议。但事实上,开源程序往往可以保持对较新版本系统环境很好的兼容性,新版本的系统环境往往具有更少的 Bug 和非常大的性能提升。

52Poké 所在的虚拟服务器采取了较为激进的做法,自2011年后一直使用 Arch Linux 操作系统,其滚动升级的特性可以让包管理(pacman)安装的应用都保持在最新版本,同时 Linode 也默认提供了最新版本的 Linux 内核。虽然对基础服务大版本的升级危险较大,但两年多来数十次 pacman -Syu 并未带来很大麻烦,除了在某几个凌晨造成数十分钟的不可用(都是由于较长时间未升级造成跨度较大并且操作失误)。

回到主题,对 MediaWiki 而言,高性能的 Web 服务器程序除了意味着 PHP 5.5,MySQL/MariaDB 5.5+;也包括使用 PHP 5.5 内置的 OPcache 加速,以及使用 Nginx + php-fpm 代替 Apache,Memcached 和/或 Redis 缓存等。

当前支持神奇宝贝百科的服务器程序为 PHP 5.5.7,MariaDB(MySQL 对社区友好的一个变体)5.5.34,Nginx 1.4.4 以及 Memcached 1.4.17。

合理的配置文件

MediaWiki 的默认配置(LocalSettings.php)并不适合生产环境,这里简要介绍一个低能耗的 MediaWiki 系统需要增加的配置项:

  • $wgDisableCounters = true; 关闭内置的统计功能,如需要统计访问量可以使用 Google Analytics 等外部服务。
  • $wgWellFormedXml = false; 以及 $wgHtml5 = true; 打开 HTML5 标签输出并关闭兼容 XML 语法,可以降低页面的体积。
  • $wgShowIPinHeader = false; 关闭未登录用户在右上角显示 IP 地址,以便使用静态缓存。
  • $wgUseGzip = true; 开启 gzip 压缩,降低页面体积,另外也可在 Web 服务器中配置开启 gzip。
  • $wgMiserMode = true; 关闭实时生成特殊页面;建议同时在 cron 里配置定时任务,定期生成特殊页面。
  • $wgJobRunRate = 0.01; 减少执行任务的频率(即每次请求有1%的几率运行任务);MediaWiki 的任务往往需要耗费数秒的时间执行,默认运行频率为1,一旦插入任务就可能导致 PHP 进程全部被占满;这里同样建议在 cron 里配置定时任务运行 MediaWiki 的任务,以免使任务队列积累过多。
  • $wgInvalidateCacheOnLocalSettingsChange = false; 关闭修改 LocalSettings.php 使所有缓存失效的特性;MediaWiki 的缓存完全失效是非常可怕的,几乎可以迅速致服务器僵死。

服务器端缓存

MediaWiki 的稳定运行,opcode 缓存、object 缓存和页面缓存都是必不可少的。

opcode 缓存

opcode 缓存用于加速 PHP 脚本的执行。PHP 5.5 内置了 OPcache(即之前的 ZendOptimizer+),比起 eAccelerator、XCache 和 APC 有更好的性能,只需在 php.ini 中引用 opcache.so 即可使用,同时 OPcache 也可单独安装在 PHP 5.4 或 5.3 环境中。另外需要注意 PHP 5.5.1 及 5.5.2 内置的 OPcache 和 MediaWiki 存在兼容问题,5.5.3 以上版本已解决。

object 缓存

MediaWiki 可以利用 object 缓存存储包括界面语言文字、文件信息、模板生成的中间产物、最终页面渲染 HTML 等数据。MediaWiki 支持使用 APC、XCache、Memcached、Redis、MySQL 数据库方式缓存数据,但配置中默认未开启 object 缓存功能。在这几种缓存方式中,除 MySQL 数据库外都需要在内存中存储,其中前3种存储方式无法持久化。

这里推荐使用是 Memcached 和 MySQL 结合的方式,配置方式如下:

$wgMainCacheType = CACHE_MEMCACHED;   
$wgMemCachedServers = array('127.0.0.1:11211');  
$wgParserCacheType = CACHE_DB;

Memcached 由于将数据存储在内存中,读写速度非常快;存储相同内容的数据占据的内存空间也是几种方式中最小。但 Parser Cache 由于包含了页面完整的 HTML 文本,需要的体积非常大,同时一旦失效则会需要重新解析所有页面,带来巨大的 CPU 开销;在内存有限的条件下更适合存储到较为持久的 MySQL 数据库中。

神奇宝贝百科在2013年初使用 Memcached 曾频繁遇到 Segfault,因此更换到 Redis + MySQL 结合的方式,但 Redis 耗费了更多内存(仅指在 MediaWiki 的使用方式下),也有相对较大的 I/O 使用。2013年12月 Memcached 发布了 1.4.17 更新,解决了不稳定的问题,因此目前又换回使用 Memcached。

页面缓存

作为一个 Wiki,对未登录用户而言页面几乎是静态的,所以页面缓存可以非常有效;MediaWiki 提供了 File cache 功能,另外也可以使用 SquidVarnish 的功能。而对于只有一台服务器的站点而言,这里更推荐使用 Nginx 自带的 FastCGI 缓存功能。

MediaWiki 默认会根据请求头中的 Accept-Language(即用户浏览器语言)、Cookie 等因素区分不同的页面缓存(可见响应头中的 Vary 行)。但对于单一语言、没有文字变种的 Wiki,只要已登录用户不使用页面缓存,未登录用户访问则看到相同的页面内容即可。

以下是神奇宝贝百科的 FastCGI 缓存配置,为便于介绍去掉了中文简繁处理相关的内容。这里缓存有效期为5小时,可以根据实际情况修改。另外,特殊页面不宜开启静态缓存(如最近更改和随机页面)。

http {
    ...
    fastcgi_cache_path  /var/cache/nginx/wiki levels=2:2 keys_zone=wiki:128m inactive=5h max_size=2048m;

    server {
        ...
        if ($http_cookie ~* "52poke_wikiUserID") {
            set $do_not_cache 1;
        }
        if ($uri ~ "^/wiki/Special:") {
            set $do_not_cache 1;
        }
        if ($args ~ "Special:") {
            set $do_not_cache 1;
        }
        fastcgi_cache wiki;
        fastcgi_ignore_headers Cache-Control Expires;
        fastcgi_hide_header Vary;
        fastcgi_cache_key $uri$is_args$args;
        fastcgi_cache_bypass $do_not_cache;
        fastcgi_no_cache $do_not_cache;
        fastcgi_cache_valid  200 5h;
        fastcgi_cache_valid  301 0;
        fastcgi_cache_valid  404 20m;
    }
}

使用页面缓存就会遇到缓存更新的问题,好在 MediaWiki 提供了 PURGE 功能,配置后只要相应的页面有更新就会发出 HTTP PURGE 请求。LocalSettings.php 中的配置如下:

$wgUseSquid = true;
$wgSquidServers = array('127.0.0.1’);

这里只配置了 127.0.0.1 因 52Poké 只有一台前端服务器,并且和 MediaWiki 程序是同一台。不过 Nginx 默认并不支持 PURGE 请求,可以编译安装 ngx_cache_purge 扩展实现,具体操作步骤可以参考这里

对于具有文字变种,如中文简繁之分的 Wiki,则情况较为复杂,今后这里会详细讨论 MediaWiki 处理中文简繁的问题,本篇就不详述了。

减少模板和文章内容渲染的开销

MediaWiki 提供了非常强大的模板和语法处理功能,尤其是内置的 ParserFunctions 扩展,但语法解析需要非常大的 CPU 开销。

这里建议尽可能减少不必要的模板使用和嵌套。例如对于一些通用的文字、背景颜色、边框样式,更适合在 MediaWiki:Common.css 或小工具中使用 CSS 实现。如果文章在编辑后需要等待很长的时间才能加载出来,则需要对其中使用的模板进行优化,必要时可以考虑拆分文章。

MediaWiki 解析图片信息也需要较大的资源消耗,对于较为固定的图片、尤其是尺寸较小的图片,推荐使用 CSS Sprites 而非通过 Wiki 上传。

MediaWiki 也会对包含过多模板嵌套、或者使用了过多语法呼叫(例如 switch 和 if 语法)的文章自动添加警示的分类。

选择合适的服务商

基础硬件的性能往往是第一位的,对运行 MediaWiki 而言,CPU、内存、I/O 性能、网络带宽都至关重要。其实早在2006年 52Poké 就搭建了 MediaWiki,但在有上百篇文章之后当时所在的虚拟主机就不堪重负,不得不在后来转型使用自建的程序,直到2010年开始使用 Linode。

就 52Poké 使用 Linode(推介链接) 的经历而言,Linode 是一家不错的 VPS 提供商,但并不算完美。Linode 在2013年进行了多次升级,在流量、网络速度、CPU 性能和性价比方面有较大优势。

VPS 有一个不稳定因素是 CPU 和 I/O 性能会受同一台物理服务器的邻居影响,52Poké 曾遇到过 CPU %Steal 过高导致性能较差的问题,不过联系客服很快迁移了另一台物理服务器解决。Linode 的 I/O 性能比提供了 SSD 的服务商要差,目前 Linode 只在纽瓦克数据中心提供了测试版 SSD 服务,亚洲用户较多使用的东京数据中心则尚未提供。

其他和未来

到这里已经介绍了高性能 MediaWiki 站点的必要条件。不过对于拥有较多图片的 Wiki 来说,可能很容易遇到流量超限或 I/O 消耗较大的问题,推荐如有必要添加一台流量较为廉价的 VPS 存放或缓存图片;另外可以考虑将图片延迟加载,即当浏览者滚动到图片位置时再加载,该功能的 MediaWiki 扩展在完成开发后会开源。

关于 MediaWiki,除了性能之外,还有很多值得讨论的话题。比如扩展,小工具(Gadget),中文的繁简问题,条目命名和内容规范,自动化批量建设内容,版权问题,以及作为一个 Wiki 社群的建设和发展。这些就留在以后继续讨论吧。

对于未来,如何支持移动设备,如何进一步减少服务器端模板的开销是水跃在继续思考的问题。MediaWiki 官方提供了 MobileFrontend 扩展,但根据设备输出不同的内容会带来更多的复杂度和资源消耗,而且可能降低了移动设备的体验;所以我更希望有响应式的方案。对于复杂的表格如果可以服务器只在页面中输出元数据,由 JavaScript 在浏览器中渲染的话,就可以减轻服务器的压力。但修改 Wiki 的 JavaScript 和 CSS 的权限往往不会开放给普通用户,这样做对社区并不利。

2014年的第一篇终于啰嗦完了,这里祝各位新年快乐,也希望 MediaWiki 的同好有所收获吧: )