歸檔 2014

最后更新于 .

這幾天的心情非常好,主要原因是我們把服務器端的架構升級到了 2.0,這樣最大的一個好處就是:

Server重啟完全不會影響外網服務

所以,也是想趁此機會,服務器端整個發展的歷程,跟大家分享一下,干貨比較多,框架代碼也會全部開源:)

 

一. 農業時代

創業最重要的就是一個“快”字,所以最開始的時候,所有的架構都以快速出模型為前提。

而常看我博客的朋友應該知道我對python情有獨鐘,所以自然的,python成為了我開發服務端框架的語言。

python自帶的多線程tcp服務器框架非常簡單:ThreadingTCPServer,即每個鏈接一個線程的模式:

import SocketServer

class RequestHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        f = self.request.makefile('r')

        while True:
            message = f.readline()
            if not message:
                print 'client closed'
                break
            print "message, len: %s, content ...

最后更新于 .

還是繼續聊創業的話題,發現關于創業,的確可以聊的東西太多了。

今天主要聊聊招人和培養的事情。

一.一分錢一分貨

之前一直在招聘上蠻控制成本的,招進來的人能力都比較差,甚至很多都是畢業生。導致團隊內無論是開發進度、質量都十分的差,而由于員工的心理成熟度和職業化程度不夠的原因,從而導致一系列管理成本的提升,如離職、負能量傳遞、情緒不穩、責任感不強等。

所以最后算下來,我發現,看起來在省錢的事情,其實最后都是在賠錢。

其實解決這個問題的方法很簡單,簡單到和個人處事的方式一樣:不要妄想占便宜。

一分錢一分貨,不要指望物美價廉,更多的時候,必要的付出是完全值得的。

所以后來,客戶端這邊我們招了一個能力蠻強的人進來,結果發現客戶端這邊的架構搭建、任務分配跟蹤等,我都不用像以前那么操心了,而且開發進度和質量也比之前好了幾個數量級。

二. 對應的人,對應的事,對應的錢

前面提到了牛人在團隊里的作用,那是不是就該盡量多的招牛人呢?

未必,畢竟創業除了理想,還是得腳踏實地現實點,而這個現實就是你有多少錢?

遇到一個牛人,愿意接受創業公司那點薪水,又能和你志同道合一起為渺茫的理想拼搏,這本身已經是一件可遇不求的事情了。

所以如果一旦出現一個就該牢牢抓住,別讓他跑了。

但是大多數情況下,我們只能在簡歷庫里搜索一份份平淡無奇的簡歷,從中篩選出你想要的那些人。

所以,更多時候 ...

最后更新于 .

敲上了這個標題,還是理不清自己想寫下什么。 其實我只是想真實記錄下自己創業路上的感受,前面三篇可能更系統些,畢竟帶有總結的性質。而這篇可能就更隨性一些。 公司從成立開始就不停的有人離職,自己也已經開掉兩個人了。 無論是被員工炒還是炒掉員工,感受都不是那么好。 一開始收到辭職申請的時候,自己還是蠻難受的,尤其是那個人可能還是你想培養的人的時候。 但是慢慢的,也就習慣了。 本來就表現不好的,當天提了離職,當天就讓他交接完事情,第二天就走。表現好一些的,示程度一起聊聊天,挽留一下。 但是挽留基本也都是沒啥用的,反正目前在我這還沒有成功過一個。 其實我始終認為離職,就跟男女分手一樣:分手的原因一點都不重要,重要的是結果。 所以基本上離職我都會問一下,對公司有什么看法,也許離職唯一的用處就是可以讓我能夠清晰的聽到他們對公司真實的看法,來杜絕之后類似事情的發生。 這幾天連續處理了幾個離職的事情,乃至于今天又聽到離職申請的時候,我都已經不想再談理想,談職業規劃,談收益。 但接下來我還是和他聊了兩三個小時,因為這個就屬于我認為重要的那部分員工。 員工和老板也許真的很難站在對方的角度上思考。 就像我不能理解: 為什么我允許你上班遲到15分鐘,中午有兩個小時午休,醒的卻還是晚半個小時,但晚上讓你加班到10點之后幾分鐘,就有人吵著說要回去? 員工的角度上只能看到自己的利益,全盤的利益是看不到的。 員工看到那個被我辭掉的員工,會自動把那個人替換成自己,從而同情那名員工,而認為我做的很殘忍;但是卻看不到因為一塊短板的存在,導致整體的進度收到影響,從而影響了他自己最終的收益 ...

最后更新于 .

發現自己經常會一篇文章寫了(一)之后,很久都不寫(二),搞得最后自己都快要忘記了,所以這次趕緊把統一支付的文章給補上。

上次的文章中將統一支付的v1版本已經講解ok了,但是還剩下兩個問題:

  • 服務器端沒有辦法做分布式
  • 客戶端對支付sdk進行插件式管理十分困難

?

我們一個個來說

一. 解決服務器端分布式的問題

解決這個問題的核心思路比較簡單:

之前我們是把event的通知放在進程內存中,現在我們做成網絡通信

由于支付的請求量本身不屬于高并發,所以就放棄了打算直接寫通知server的想法,轉而看一下有沒有什么簡單的解決方案。

而由于自己之前redis的使用經歷,恰好知道redis有一個pubsub模式,很適合做這種監聽和通知的工作。

python的實現示例代碼如下:

import time
import config
from share.vals import rds
from share.utils import safe_str
from gevent.timeout import Timeout
from urllib import quote, unquote

class RedisPubSub(object):
    """
    用redis訂閱/發布消息
    """
    # 訂閱頻道
    sub_key ...

最后更新于 .

其實想跟大家分享這套支付系統的架構已經很久了,今天總算有時間寫出來了。

先說說這套系統的需求由來吧:

  1. 筆者公司的游戲產品已經有幾款了,每次上各種渠道都是要搭配不同的計費方式,并且每開發游戲都要重復一遍痛苦的接入sdk流程
  2. 游戲的支付需要出各種報表以及統計,每個游戲單獨去做對人力的消耗巨大

基于以上幾點,我這邊設計了統一支付系統。

這個系列一共會分兩篇文章,分別對應系統的v1版和v2版,我們這一篇先從v1起介紹。

在仔細分析了國內的大多數支付sdk之后,我們梳理出游戲的支付流程大體可以實現為兩類:

  • 第三方sdk服務器進行支付結果通知
  • 第三方sdk客戶端直接返回支付結果通知,沒有服務器支付結果通知。

對于調用方而言,這兩種方式各有好處。

  • 第一種方式更加安全,但是支付調用的時間相對較長
  • 第二種方式速度更快,但是很容易被不懷好意的人破解。參見之前的文章:google支付接口被刷以及解決方案

接下來,我們來看一下我這邊設計的統一支付流程。

客戶端:

1

服務器端:

2

簡單解釋一下:

  • 每次支付開始,都要讓服務器生成一個訂單作為此次支付的記錄,訂單的id即為 bill_id。訂單有4中狀態:訂單生成,支付失敗,支付成功,發貨成功。
  • pay_server即為統一支付系統的服務器端,考慮到調用量和方便調試,使用了簡單的http協議+json+sign的方式

對于服務器內部,唯一麻煩的一點是,《等待pay_server支付結果通知》這個接口。因為這個http請求需要支持掛起,在第三方支付服務器通知了pay_server之后,pay_server 根據通知里面透傳的bill_id 將訂單狀態修改后,再給客戶端結果 ...

最后更新于 .

接著上一篇繼續,前面兩篇算是把從創業開始發展到今天的整個過程大體說了一遍,但是接下來的文字才是真正我想要和大家分享和探討的。

這個話題就是:作為一個技術合伙人,職責到底應該是什么?

其實隨著公司的發展,我就一直在思考這個問題:一方面是來自于擔心公司技術進度失控的不安全感,一方面是來自于自己不再有太多時間編碼,而帶來的對自身技術能力落伍的擔心。

還是按照創業的階段來說吧。

一、創業第二階段-隊長

這個時候,公司可能就3、4個人,一個產品、一個前端、一個后端。什么技術合伙人、技術總監之類的,沒必要在意這個名字,這個時候,唯一的要求就是做出產品。

而這個能力,又分兩塊:

1. 自己編碼的能力

2. 設計架構,主導技術開發的能力

這個時候,更像一個隊長。你要帶領幾個隊員,但你自己也要沖鋒。

你要能夠將產品解構為代碼實現,你要熟悉整個產品的研發,無論前端還是后端。

這個階段,是非常關鍵的為團隊打基礎的時間。

在產品的實現過程中,要逐漸規劃出自己的技術框架,將底層、公共邏輯拆分出來,為下一個階段做準備。

而隊長,就是要將這些東西,在這個階段盡快沉淀、積累下來。

舉個例子,服務器端語言用什么?python。web框架用什么?django ...

最后更新于 .

接著上一篇文章說吧。 在這之后,差不多快到年底吧,經過朋友的介紹認識了現在的合伙人,做產品策劃和運營。之前也只是打電話聊了一下,不能說一見如故吧,但是聊下來之后也是仔細考慮了好幾天,才決定是不是要進行這樣的合作。 后來當面聊了一次,決定先以比較淺的合作方式試一下,就開發現有產品的某個模塊,互相也都彼此磨合一下,如果感覺不錯的話就再往下走。 這樣差不多搞到年后,終于決定了以技術合伙人的身份進入團隊,基本形成了目前創始人團隊鐵三角的關系。 之后開始招人,當時還在小黑屋內,而且還在燒自己的錢,所以招人的成本和質量控制的都很嚴格。不過現在想起來,當時的嚴格對現在的我們還是有很大的好處,當時招的同事承擔了當時基本所有客戶端的開發,他后來又介紹了一位朋友,也是客戶端開發,也很不錯,現在兩人都是公司的骨干。 當然,說是以技術合伙人身份加入,其實說白了還是寫代碼,然而現在的自己還是很懷念那時候可以酣暢淋漓寫代碼的日子的。 當時工作極其的辛苦,每天都在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 ...

每月存檔

去年

2013

明年

2015