forthxu 发布的文章

手游上线流程

手游上线非常麻烦,有客户端,需要跟渠道紧密沟通,下面是我之前总结的产品上线流程,并不适用所有团队,仅供参考。

上线前一个月

运营工作

  • 游戏信息确定
    • 确定游戏名字
    • icon做多个版本进行测试
    • 截图准备做多个版本进行测试
  • 法律流程
    • 申请软件著作权
    • 申请软件产品登记
    • 美术相关申请美术作品版权登记
  • 游戏官网(适应移动端浏览)
  • 游戏视频制作开始筹备
  • 游戏资料整理(初版)
  • 第三方账号申请
    • 百度贴吧申请
    • 微信账号申请
    • 微博账号申请
    • QQ空间账号申请
  • 提交运营通用需求(详情在另外一个文档)
  • 后台功能需求
    • 领取活动
    • 兑换活动
    • 充值,消费活动
    • 转盘活动
    • 公告
    • 邮件
    • 配置商城
    • buff类活动(经验加成,掉率加成)
    • 特殊掉落活动
  • 游戏设计验证
    • 不同系统投入产出比
    • 扭蛋概率
    • 宝箱概率
  • 第三方SDK接入
    • talkingdata数据统计后台
    • 广告效果跟踪campaign
    • 广告SDK
    • 事件添加

市场工作

  • 推广计划制定
  • 新闻素材整理
  • 早期产品曝光

上线前1周

运营工作

  • 确定icon
    • 尺寸:1024、512、120、114、90、72、48、36
  • 确定截图
    • 横版,竖版各一套
    • 尺寸:1136*640、1024*768、960*640、800*480、480*360、480*320
  • 游戏介绍
    • 简版200字
    • 完整版无字数限制(带图)
  • 游戏攻略(至少3篇)
    • 新手攻略(多篇)
    • 花钱攻略
    • 游戏资源产出图
  • 百度贴吧内容填充
    • 游戏资料区
    • 攻略区
    • 精品区
  • 微信素材填充
    • 游戏资料
    • 攻略链接到官网
    • 自定义回复
    • 自定义菜单
  • 游戏官网资料填充(未来不断更新)
  • 准备20个服务器名称
  • 开通QQ群
  • 检查后台数据准确性
    • 事件记录
    • 自己游戏后台和talkingdata对比
  • 删档封测活动
    • 游戏内活动
    • 社群刷楼活动
    • 好评活动
    • 加Q群活动
    • 加微信活动
  • 渠道接入完成,可上线状态
    • 给渠道提交客户端
    • 充值联调完毕
    • 游戏专区建设完毕(icon,截图,介绍,关键字)

市场工作

  • 产品新闻
    • 上线新闻
    • 游戏特色
    • 故事背景
    • 游戏评测
    • 制作人专访
    • 制作团队探班
    • IP合作新闻
  • 渠道资源准备
    • 确定删档封测的推广资源
    • 软文
    • 媒体合作
    • 外部活动合作(激活码,礼包码,找bug活动,实物奖励活动)
  • 广告投放前期准备
    • 广告素材
    • 短链生成

上线前1天

运营工作

  • 游戏删档
  • 配置好所有活动并测试
  • 检查游戏设置
    • 不开充值
    • 商城测试
    • 服务器名
    • 游戏版本
    • 游戏公告
    • qq群,微信推荐

上线当天

运营工作

  • 提前1小时检查客户端是否上架,游戏介绍页是否正常
  • 上线前10分钟开放服务器,进游戏检查
    • 商城
    • 活动
    • 公告
    • 功能
    • 充值
  • 上线后频繁关注
    • 新增玩家
    • 下载量和激活玩家对比
    • QQ群
    • 在线数据
    • 微信
    • 游戏内聊天
    • 事件数据

市场工作

  • 检查广告资源
    • 媒体新闻是否上线,位置是否正确
    • 广告位是否正常
    • 链接,包是否正确

封测期间:

  • 收集玩家反馈,整理bug,游戏优化建议
  • 整理玩家行为数据,发现前期卡点,提出前期优化建议
  • 提出新的后台需求,完善后台功能
  • 跟活跃玩家深入交流,保持长期沟通
  • 用户访谈(不同类型玩家)
  • 重点优化留存数据

收费内测:

  • 首服作为测试服,可较大改动,改到数据理想为止
  • 查看消费结构,优化游戏付费
  • 针对性的写一些消费攻略和引导
  • 搭建好玩家管理团队,管理贴吧,qq群
  • 接一个小渠道做专服,用来做玩家测试服,每次版本更新先更新测试服
本文来源:原文链接

skynet线上使用的数据,解答性能问题

记录一下MMZB的运维运营数据

陌陌争霸已经运行9个多月,记录一下现在的运维运营数据:

总用户460万,集群服务器共30台,其中Game Server
9台,redis集群内存占用接近900G,mongo集群磁盘占用接近5T(定时删除旧数据,所以增长速度趋缓了)。
redis集群内存每周增长20G,很快突破1T。后期会上线leveldb落地redis冷数据的方案,有望把redis内存占用削减到现在的三分之二,则600G左右。使用TokuMX替换Mongo后,减少了的磁盘空间占用压力,已经处于恒定状态。

统观项目状态,资源需求已经趋于平稳状态,运维方向可向更高层次的调优和架构改造偏重。

从最近的两次崩溃所总结出的及我的2013

公司的手游项目(注:手游 陌陌争霸)上线了半个多月,一直运行的稳定,开始的测试过程中也出现了零零散散的几个小坑,都顺利跨过了。能实现单机支持3W在线用户的水平,按云风GG的说法,这结果出乎之前的预算,有那么一点小鼓舞。
过去的这个周末和今天周一连续出现了两次集群中一台服务崩溃的情况,晓靖和云风GG很快找到了梗所在,并迅速修复了这个坑,让我们对这个项目更加充满了希望,我相信合作方也与我们一样。
说回运维层面的东西,首先我想说的是,好的代码和架构能为运维节省大量的工作并同时提升运维效率,从这一点上,skynet和与之配合的各模块都出色的达到了这个标准:完善的日志输出、高效但并不复杂的架构设计,我还是遵循我一向的标准,只要是简单、高效、安全的设计,就是优秀的设计。

web服务系统连接状态

系统

1.查看TCP连接状态

netstat -nat |awk '{print $6}'|sort|uniq -c|sort -rn
netstat -n | awk '/^tcp/ {++S[$NF]};END {for(a in S) print a, S[a]}' 或
netstat -n | awk '/^tcp/ {++state[$NF]}; END {for(key in state) print key,"\t",state[key]}'
netstat -n | awk '/^tcp/ {++arr[$NF]};END {for(k in arr) print k,"\t",arr[k]}'
netstat -n |awk '/^tcp/ {print $NF}'|sort|uniq -c|sort -rn
netstat -ant | awk '{print $NF}' | grep -v '[a-z]' | sort | uniq -c

2.查找请求数请20个IP(常用于查找攻来源)
netstat -anlp|grep 80|grep tcp|awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -nr|head -n20
netstat -ant |awk '/:80/{split($5,ip,":");++A[ip1]}END{for(i in A) print A[i],i}' |sort -rn|head -n20

3.用tcpdump嗅探80端口的访问看看谁最高
tcpdump -i eth0 -tnn dst port 80 -c 1000 | awk -F"." '{print $1″."$2″."$3″."$4}' | sort | uniq -c | sort -nr |head -20

4.查找较多time_wait连接
netstat -n|grep TIME_WAIT|awk '{print $5}'|sort|uniq -c|sort -rn|head -n20

5.找查较多的SYN连接
netstat -an | grep SYN | awk '{print $5}' | awk -F: '{print $1}' | sort | uniq -c | sort -nr | more

6.根据端口列进程
netstat -ntlp | grep 80 | awk '{print $7}' | cut -d/ -f1

日志

1.获得访问前10位的ip地址
cat access.log|awk '{print $1}'|sort|uniq -c|sort -nr|head -10
cat access.log|awk '{counts[$(11)]+=1}; END {for(url in counts) print counts[url], url}'

2.访问次数最多的文件或页面,取前20
cat access.log|awk '{print $11}'|sort|uniq -c|sort -nr|head -20

3.列出传输最大的几个exe文件(分析下载站的时候常用)
cat access.log |awk '($7~/.exe/){print $10 " " $1 " " $4 " " $7}'|sort -nr|head -20

4.列出输出大于200000byte(约200kb)的exe文件以及对应文件发生次数
cat access.log |awk '($10 > 200000 && $7~/.exe/){print $7}'|sort -n|uniq -c|sort -nr|head -100

5.如果日志最后一列记录的是页面文件传输时间,则有列出到客户端最耗时的页面
cat access.log |awk '($7~/.php/){print $NF " " $1 " " $4 " " $7}'|sort -nr|head -100

6.列出最最耗时的页面(超过60秒的)的以及对应页面发生次数
cat access.log |awk '($NF > 60 && $7~/.php/){print $7}'|sort -n|uniq -c|sort -nr|head -100

7.列出传输时间超过 30 秒的文件
cat access.log |awk '($NF > 30){print $7}'|sort -n|uniq -c|sort -nr|head -20

8.统计网站流量(G)
cat access.log |awk '{sum+=$10} END {print sum/1024/1024/1024}'

9.统计404的连接
awk '($9 ~/404/)' access.log | awk '{print $9,$7}' | sort

10. 统计http status.
cat access.log |awk '{counts[$(9)]+=1}; END {for(code in counts) print code, counts[code]}'
cat access.log |awk '{print $9}'|sort|uniq -c|sort -rn

11.蜘蛛分析查看是哪些蜘蛛在抓取内容。
/usr/sbin/tcpdump -i eth0 -l -s 0 -w - dst port 80 | strings | grep -i user-agent | grep -i -E 'bot|crawler|slurp|spider'

12.按域统计流量
zcat squid_access.log.tar.gz| awk '{print $10,$7}' |awk 'BEGIN{FS="[ /]"}{trfc[$4]+=$1}END{for(domain in trfc){printf "%s\t%d\n",domain,trfc[domain]}}'
效率更高的perl版本请到此下载:http://docs.linuxtone.org/soft/tools/tr.pl

13.按步骤分析请求时间
curl -o /dev/null -w %{time_namelookup}::%{time_connect}::%{time_starttransfer}::%{time_total}::%{speed_download}"\n" "http://joke.4399pk.com"

数据库篇

1.查看数据库执行的sql
/usr/sbin/tcpdump -i eth0 -s 0 -l -w - dst port 3306 | strings | egrep -i 'SELECT|UPDATE|DELETE|INSERT|SET|COMMIT|ROLLBACK|CREATE|DROP|ALTER|CALL'

系统Debug分析篇

1.调试命令
strace -p pid

2.跟踪指定进程的PID
gdb -p pid

原文
使用netstat和awk命令来统计网络连接数

一道php引用问题

<?php
    $arr = array('a','b','c');
    foreach($arr as $key=>$val){
            $val=&$arr[$key];
            print_r($arr);
    }
?>

执行结果为:

Array 第一次循环,使$val是$arr[0 ]的引用
(
[0 ] => a
[1 ] => b
[2 ] => c
)
Array 第二次循环,因为$arr[1 ]赋值给$val,而$val是$arr[0 ]的引用,因此数组被改变。 同样第二次循环使$val是$arr[1 ]的引用
(
[0 ] => b
[1 ] => b
[2 ] => c
)
Array 同理
(
[0 ] => b
[1 ] => c
[2 ] => c
)

PHP底层运行原理初探

PHP是一种适用于web开发的动态语言,但从研究PHP实现来讲她就是一个用C语言实现包含大量组件的软件框架。

PHP说简单,但是要精通也不是一件简单的事。我们除了会使用之外,最好要知道它底层的工作原理。那么了解PHP底层实现的目的是什么?

  • 动态语言要像用好首先得了解它,因为理解底层才能真正用好上层
  • 内存管理、框架模型值得我们借鉴
  • 通过扩展开发实现更多更强大的功能,优化我们程序的性能。

- 阅读剩余部分 -

获取apk的name,icon,version,permissions,RSA等信息

https://gist.github.com/forthxu/f42113205494abd54453

#!/bin/bash
#@author forthxu.com
#说明
#找到获取apk信息有两种方式
#一种解压后读取AndroidManifest.xml,解压最好不要通过unzip因为获取的是压缩过的内容,读取不准确,可用apktool反编译解压
#另外一种可通过aapt也就是官方sdk中提供的工具读取信息
#aapt和apktoool工具 https://code.google.com/p/android-apktool
#可能存在的问题 http://www.qiansw.com/centos-apk-apktool.html
#扩展阅读,汉化apk http://bbs.dospy.com/thread-9991523-1-354-1.html

#如果使用unzip解压的方法还可以通过以下方法解析XMl文件
#java可用 java -jar AXMLPrinter2.jar AndroidManifest.xml > AndroidManifest2.xml
#AXMLPrinter2.jar下载 https://code.google.com/p/android4me/
#AXMLPrinter2 php版http://blog.katcin.com/archives/69

#获取apk
if [ ! -s "${1}" ];then
    echo "usage:bash ${0} some.apk";
    exit;
fi
#获取文件后存储的位置
ex=./ex/;

echo "-----apk信息----";
#apk信息
badging=`aapt d badging $1`;
# echo $badging;

echo "-----apk icon----";
#获取apk icon
icons=`aapt d badging $1 | grep -E "application-icon|application:" | sed -e 's/.*\(res\/\w\{1,\}\-\w\{1,\}\/\w\{1,\}\.png\).*/\1/' | uniq`;
# echo $icons;
for icon in $icons;do
    echo $icon;
done

echo "-----解压图标 到 ${ex}----";
#解压图标
unzip -o $1 $icons -d $ex

echo "-----apk name----";
#获取apk name
name=`aapt d badging $1 | grep -E "application:" | sed -e "s/.*label='\(\w*\)'.*/\1/"`;
echo $name;

echo "-----apk 权限----";
#获取apk 权限
permissions=`aapt d permissions  $1 | awk -F " " '/uses-permission/ {print $2}'`;
# echo $permissions;
for permission in $permissions;do
    echo $permission;
done

echo "-----apk sdkVersion----";
#获取apk sdkVersion
sdkVersion=`aapt d badging $1 | grep -E "sdkVersion:" | sed -e "s/.*:'\(\w\{1,\}\)'.*/\1/"`;
echo $sdkVersion;

echo "-----apk targetSdkVersion----";
#获取apk targetSdkVersion
targetSdkVersion=`aapt d badging $1 | grep -E "targetSdkVersion:" | sed -e "s/.*:'\(\w\{1,\}\)'.*/\1/"`;
echo $targetSdkVersion;

echo "-----apk versionCode----";
#获取apk versionCode
versionCode=`aapt d badging $1 | grep -E "package:" | sed -e "s/.*versionCode='\(\w\{1,\}\)'.*/\1/"`;
echo $versionCode;

echo "-----apk versionName----";
#获取apk versionName
versionName=`aapt d badging $1 | grep -E "package:" | sed -e "s/.*versionName='\(\S\{1,\}\)'.*/\1/"`;
echo $versionName;

echo "-----apk package----";
#获取apk package
package=`aapt d badging $1 | grep -E "package:" | sed -e "s/.*name='\(\S\{1,\}\)'.*/\1/"`;
echo $package;

echo "-----apk supports-screens----";
#获取apk supports-screens
supports=`aapt d badging $1 | grep -E "supports-screens:" | sed -e "s/.*supports-screens:\(.\{1,\}\)/\1/"`;
echo $supports;

echo "-----解压证书 到 ${ex}----";
#解压证书
unzip -o $1 META-INF/CERT.RSA  -d $ex

王垠:程序员的心理疾病

  说实话,虽然似乎为之奋斗了十多年,在真正进入软件行业的短短一年之后,我已经对它感到相当的厌倦了。这并不是说这个行业没有前景,而是在这个行业工作,其实很难得到心理上的快乐。

  人们说女怕嫁错郎,男怕入错行。我并不认为自己入错了行,我仍然很喜欢设计程序和语言,而且我显然是这个领域的王牌之一。然而我却看到了这个行业里的无限混沌,让我觉得喘不过气来。几十年的垃圾设计堆积在那里,却没有人试图把它们清理掉,权威主义盛行。无论你在哪个公司,哪个地方,只要跟程序员说话,十有八九会谈不来。非常扫兴不说,甚至感觉很伤自尊。

  久而久之我发现了,由于程序员工作的性质,他们受到的“熏陶”,形成了一种行业性的心理疾病。这里我就简单的把我所观察到的一些症状总结一下。

- 阅读剩余部分 -

nginx下的php安全隔离

  • 方法1)在Nginx配置文件中加入

fastcgi_param PHP_VALUE "open_basedir=$document_root:/tmp/:/proc/:$document_root/../";

or

fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root:/tmp/:/proc/:$document_root/../";

不同的地方是:php_admin_value(php_admin_flag)命令只能用在apache的httpd.conf文件中,而 php_value(php_flag)则是用在.htaccess文件中的,nginx下相同。

因为使用FastCGI,php不是每次都重新启动,所以每个主机sever都需要加入配置,以便每次访问都设置php的open_basedir。

适用 nginx + php5.3以上,php5.2 此方法不生效。

  • 方法2)在php.ini中加入:

open_basedir=./:/tmp/:/proc/
这种方式的设置需要重启php-fpm后生效

  • 方法3)在网站根目录下创建.user.ini并写入:

open_basedir=./:/tmp/:/proc/

这种方式不需要重启nginx或php-fpm服务。安全起见应当取消掉.user.ini文件的写权限。

关于.user.ini文件的详细说明:
http://php.net/manual/zh/configuration.file.per-user.php

  • 方法4)nginx的chroot

完全隔离php和系统,如果需要系统功能的自己创建系统环境,路径也要配成相对隔离的环境。
http://www.baidu.com/s?wd=nginx%20chroot

目前最好的是适用第一种方法。

设置open_basedir的同时最好禁止下执行命令的函数,比如:
shell_exec('ls /etc')仍然查看到/etc目录的文件列表
shell_exec('cat /etc/passwd')仍可查看到/etc/passwd文件的内容

建议禁止的函数如下:
disable_functions = pcntl_alarm, pcntl_fork, pcntl_waitpid, pcntl_wait, pcntl_wifexited, pcntl_wifstopped, pcntl_wifsignaled, pcntl_wexitstatus, pcntl_wtermsig, pcntl_wstopsig, pcntl_signal, pcntl_signal_dispatch, pcntl_get_last_error, pcntl_strerror, pcntl_sigprocmask, pcntl_sigwaitinfo, pcntl_sigtimedwait, pcntl_exec, pcntl_getpriority, pcntl_setpriority, eval, popen, passthru, exec, system, shell_exec, proc_open, proc_get_status, chroot, chgrp, chown, ini_alter, ini_restore, dl, pfsockopen, openlog, syslog, readlink, symlink, popepassthru, stream_socket_server, fsocket, chdir

php运行的几种运行方式

php本身是一个php代码的脚本执行程序,运行方式是指其运行的方法。整理归纳为一下五种方法:

  • 模块加载运行方式 (Apache)
  • CGI运行方式 (Apache)
  • FastCGI运行方式 (几乎通用Apache nginx lighttp)
  • ISAPI运行方式 (window下Apache)
  • cli运行方式 (就是命令行)

前四种是提供给web服务器来处理php代码文件,其中模块加载的方式其实是最快的的,但FastCGI配合nginx WEB服务是目前的主流,下面主要配合Apache做说明。

- 阅读剩余部分 -