最后更新于 .

接着上一篇文章说吧。
在这之后,差不多快到年底吧,经过朋友的介绍认识了现在的合伙人,做产品策划和运营。
之前也只是打电话聊了一下,不能说一见如故吧,但是聊下来之后也是仔细考虑了好几天,才决定是不是要进行这样的合作。
后来当面聊了一次,决定先以比较浅的合作方式试一下,就开发现有产品的某个模块,互相也都彼此磨合一下,如果感觉不错的话就再往下走。
这样差不多搞到年后,终于决定了以技术合伙人的身份进入团队,基本形成了目前创始人团队铁三角的关系。
之后开始招人,当时还在小黑屋内,而且还在烧自己的钱,所以招人的成本和质量控制的都很严格。
不过现在想起来,当时的严格对现在的我们还是有很大的好处,当时招的同事承担了当时基本所有客户端的开发,他后来又介绍了一位朋友,也是客户端开发,也很不错,现在两人都是公司的骨干。
当然,说是以技术合伙人身份加入,其实说白了还是写代码,然而现在的自己还是很怀念那时候可以酣畅淋漓写代码的日子的。
当时工作极其的辛苦,每天都在12点之后下班,当时公司一共3个人,后来又找了俩兼职,我基本每天都是12点半开车把大家送到家,然后自己才到家。
其实现在想起来那段日子也蛮难为自己媳妇的,基本都见不到几次面。(当然现在晚上也还是很晚,只是比当时12点这种量级还是好一点了)
后来,因为政策上的一些问题,公司产品出了点问题。
我们三个合伙人决定引入投资。
因为人脉上的关系,这次的投资引入的还是蛮快的。
我们三个一块见了次投资人,其他事情基本就另外两个合伙人在跑了。
这里的事情就不细说了。
投资进来之后,公司几个月内的生存暂时不是问题,但是压力也相应而来,毕竟拿了别人的钱 ...

最后更新于 .

算起来,从离开腾讯自己创业已经过去一年半了,其中经历了太多事情,也有太多的东西想要记录和分享给大家,所以开了这个系列,希望能记录下来。
先说一下目前自己处于的状态,因为目前的状态会严重影响我对事情的判断,而很可能一年后的自己看到自己今天写的话会觉得全是扯淡。
目前公司已经拿到投资。
公司总共17个人,其中创始人包括我共3个,分别负责渠道、产品、技术。
研发团队分3个组,分别是android、cocos2dx、后端,人数分别是4、3、3;产品 2人;美术1人;渠道1人。
挤在一个130平的房子内,周一至周六都上班,周一~周五都是最早10点下班,周六让大家早点走,6点吧。
研发的进度的话,android来开发一个完整的棋牌游戏在1.5月左右。
cocos2dx也是这样一个时间表。
我们后端是用的python,所以开发会很快,一般在一周内就能写出一个可玩的牌桌内逻辑。
现状大体就是这样,先在这临时存个档,一会再读回来。
先从1年半前说起吧。
2013年3月份,自己从腾讯正式离职,当时还处于国内互联网“开放”吵得比较火的时候,而自己手里是有几款能盈利的pc应用的,所以相当于自己给自己发工资,日子过的还不错,也没怎么觉得多有压力。
到4月份,自己其中的一个产品被腾讯下线;再到8月份,自己另一款产品也被腾讯下线。
话说被下线的当天 ...

最后更新于 .

在很早的时候,就听网上的文章说:

python有GIL,所以在单进程内,即使使用多线程也无法利用到多核的优势,同一时刻,python的字节码只会运行在一个cpu上。

以前也是奉为真理,直到今天在对自己的python server做性能测试的时候,发现一个python进程的cpu居然达到了120%。

当用c++编程的时候,如果使用多线程,那么确实进程cpu超过100%非常正常,但是对python来说,似乎这样就和网上的文章冲突了。

所以还是决定自己亲身试验一下,编写代码如下:

from thread import start_new_thread

def worker():
    while 1:
        #print 1
        pass

for it in range(0, 15):
    start_new_thread(worker, ())


raw_input()

 

运行环境为: centos6.4 64位, python 2.7.

得到的结果如下:

E588C2D7 1608 42CC B800 AD5338C87F47

可以清楚的看到,pid为31199的python进程cpu达到了787.9%,接近理论能达到的最大值 800%。

而上方的8个cpu也分别达到了近100 ...

最后更新于 .

最近在做游戏服务分层的时候,一直想把mysql的访问独立成一个单独的服务DBGate,原因如下:

  1. 请求收拢到DBGate,可以使DBGate变为无状态的,方便横向扩展
  2. 当请求量或者存储量变大时,mysql需要做分库分表,DBGate可以内部直接处理,外界无感知
  3. 通过restful限制对数据请求的形式,仅支持简单的get/post/patch/put 进行增删改查,并不支持复杂查询。这个也是和游戏业务的特性有关,如果网站等需要复杂查询的业务,对此并不适合
  4. DBGate使用多进程模式,方便控制与mysql之间的链接数,进行mysql访问量阀值保护
  5. 方便在DBGate上进行访问量统计,慢查询统计、权限控制等等一系列逻辑
  6. 目前是使用python,以后要使用其他语言进行mysql操作时,只要进行标准的http请求即可,不会出现不兼容的情况

当然坏处也是有的:

  1. 首当其冲就是单次请求的响应时间变长,毕竟中间加了一层服务,并且还是http格式
  2. 部署上比原来复杂了一些,很多对mysql直接操作的思维需要进行转变,一开始可能会有些不适

不过总的来说,还是利大于弊,所以最终还是决定搭建DBGate

当然,我们不可能去手工挨个写每个库表对应的restful服务,值得庆幸的是django和flask都提供了对应的解决方案,我们一个个介绍.

Flask

参考链接: flask-restless

flask-restless使用方法比较简单,我直接贴一下代码即可:

# -*- coding: utf-8 -*-

import datetime
from flask ...

最后更新于 .

最近在调整游戏的后台架构,之前因为需要快速出产品,所以整个代码都揉成一团,也基本没有做任何分层处理。现在服务器端的开发也开始逐渐招进来,所以打算打算换一套统一的架构,以后做新游戏只要做其中的业务逻辑即可。

其实之前在腾讯的时候,基本不会用到message queue这种,所有的分布式处理都是由自己写c++ server来互相通信的。这样的处理虽然开发量稍微大一点,但是性能和灵活性确实很高。

现在自己在外面做,虽然自己已经封装了一套server的框架出来,但是毕竟还有太多的轮子需要自己制造,所以就想到了之前一直有了解过celery,来看一下这种基于message queue的任务系统能达到什么性能。

RabbitMQ

celery首推的mq是rabbitmq,所以需要先安装一下:

在mac下用brew 安装:

brew install rabbitmq

安装成功之后,即可启动server了。

不过在这之前,我们先把后台管理的插件打开:

rabbitmq-plugins enable rabbitmq_management

之后执行如下命令,启动server:

rabbitmq-server

这个时候就可以通过 http://127.0.0.1:15672/ 来访问后台管理端了,默认的用户名和密码是guest guest,可以自己在页面上修改。截图如下:

NewImage

 

Redis

celery也支持redis作为broker和backend,所以redis也需要安装一下 ...

最后更新于 .

测了一下django、flask、bottle、tornado 框架本身最简单的性能。对django的性能完全无语了。

django、flask、bottle 均使用gunicorn+gevent启动,单进程,并且关闭DEBUG,请求均只返回一个字符串ok。

tornado直接自己启动,其他内容一致。

测试软件为 siege,测试os为cenos6 64位,测试命令为:

siege -c 100 -r 100 -b http://127.0.0.1:5000/

django测试结果为:

Transactions:		       10000 hits
Availability:		      100.00 %
Elapsed time:		       18.51 secs
Data transferred:	        0.02 MB
Response time:		        0.18 secs ...

最后更新于 .

上一篇文章聊了下数据存储和常用的传输协议,不过对于自定义传输协议这里留了个坑,正好有点时间,就抓紧填上:)

既然选择原生socket,那么有个基本的选择就是tcp/udp的问题.

这个其实还是看业务自己的选择,只是如果选择了udp的话,那么很多问题都可以不用考虑,比如粘包问题。但是udp有个限制是每次传输的数据大小不能超过64K,这个要注意。

为了考虑复杂的情况,我们还是主要说tcp的实现,这篇文章先说下socket使用相关的一些库和代码吧

Android端开发

对于android端,我们有两个主要选择:阻塞socket和非阻塞socket。

阻塞socket就是正常的socket,当调用recv的时候,会阻塞住直到返回数据。

非阻塞socket在android上可以直接使用nio,因为自己之前一直是做c++和python,所以其实一开始nio的时候真心有些不太使用,把几个要注意的点列一下:

1. 当网络断线的时候,有些手机如S4,会出现这个问题,channel.finishConnect()会一直等超时 60秒。之后会抛出一个 TimeoutException.

解决方法是:

channel.socket().setSoTimeout(5)

来设置成只等5秒。

比较诡异的是,明明是异步io了,为什么还是会有等待超时的情况。还要在研究下。

2. 当网络不在线的时候,启动connect,依然可以进入isConnectable的判断中,并且可以调用finishconnect。

解决方案:finishConnect之后 ...

最后更新于 .

经过这么久在android客户端和服务器端的开发,感觉还是积累了不少东西想要和大家分享一下,但是好想单独拎一个点出来又不太值得,所以就汇集到一起写成系列吧。

一. 关于用户数据存储

首先在注册的协议里,定义如下公共传输字段:

version: 这个其实是xml中配置的versionCode。versionName个人认为没有什么必要,所以就不传了。

channel:  用户渠道,这个和xml中的UMENG_CHANNEL 是共用的,因为一直在使用umeng,所以这样定义反而清楚一些。

device_id: 设备ID

os: 操作系统类型,这里默认传入android

os_version: 操作系统版本

对于小数据量,用户数据存储在mysql中是相对较好的选择,这里直接以django的model为例:

from django.db import models
class User(models.Model):
    device_id = models.CharField(max_length=255, null=True, blank=True)
    version = models.IntegerField()
    channel = models.CharField(max_length=64, null ...

最后更新于 .

12年的时候入了macbook pro,之后就一直用到现在,只是一直把机械硬盘当作ssd用,盖了盖子直接就带着到处跑,结果最近就给杯具了。

文章可能写的比较散,我就给分成几节吧

一. 发现问题

现象倒是比较常见,死机频繁,并且开chrome一直chrome内核的ide必然死机。一开始以为是10.9系统的问题,后来想来想估计是内存或者硬盘的问题。

在网上下了个神器:TechTool

大家如果对自己的硬盘不放心也可以去检测一下~ 检测的结果:

SMART检查失败 硬盘存在不可修复的硬件问题,请更换硬盘

得,这直接判了死刑了。

赶紧去网上买了块硬盘,以及一个硬盘盒。

又从朋友那边接了拆mac的专用螺丝刀盒。

为了保险起见,从朋友那里借了个移动硬盘,把所有数据备份了一下。

二. 制作系统

话说因为买mac的时候并没有赠送系统盘之类的东西,所以去网上淘了一下,比较庆幸已经有人做好了: Mac OS X 10.9 Mavericks U盘复刻版,将其导出为U盘即可。

导出为u盘的方法也简单说下:

  • 准备一个8G的U盘
  • 执行系统自带的磁盘工具,将下载的DMG恢复到准备的U盘上
  • 喝杯咖啡,等半个小时,搞定

三. 更换硬盘,安装系统

拆硬盘还是比较简单的 ...

最后更新于 .

终于把博客成功迁移到阿里云上了,怎么样,感觉速度快多了吧?

其实自己与阿里云结下缘分也近3年了,可以说看着阿里云一步步变好,所以也才最后决定把自己所有的服务都迁移到了阿里云服务器上,包括自己的应用服务器、游戏服务器、乃至最后自己的博客。

话说阿里云给每个老客户貌似都分配了专门的客户经理,这个感觉还是很爽的,哈哈。

好了,算是免费给阿里云打个广告,接下来说说迁移的事情。

wordpress的迁移对于程序员来说是很简单的,无非是搭建个php环境,迁移一下mysql的数据就可以了。

具体使用的各组件如下:

nginx
supervisor
php
mysql

 

nginx的配置很多网上写的都不太对,所以这里贴出来给大家:

    server {
        listen       80;
        server_name  vimer.cn *.vimer.cn;
    
        root         /data/release/vimer;
		
		# 客户端上传大小
        client_max_body_size 20m;
        
        rewrite /wp-admin$ $scheme://$host$uri/ permanent;
    
        location / {
            index index.php index.html;
            if (-f $request_filename ...