分类存档: game-game - 第3页

好吧,一个makefile的初学者学习skynet中

1、第一步就是项目的组织方式。skynet经常要更新,所以要尽量避免在自己项目共用同一个git。从群中和云风的文章中了解到,使用submodule引用skynet是一种比较理想的方式。我一个makefile基本为0的人要理解submodule的编写很不容易,而且也不知道过程对不对,但现在至少已经可以初步达到目标了。

# hello game
#

.PHONY : all clean skynet

CC ?= gcc
PLAT ?=linux

LUA_CLIB_PATH=/opt/git/hellogame/luaclib
CSERVICE_PATH=/opt/git/hellogame/cservice

SKYNET_BUILD_PATH ?=/opt/git/hellogame

all : skynet

skynet :
        cd module_skynet && $(MAKE) CC=$(CC) SKYNET_BUILD_PATH=$(SKYNET_BUILD_PATH) LUA_CLIB_PATH=$(LUA_CLIB_PATH) CSERVICE_PATH=$(CSERVICE_PATH) linux

clean :
        cd module_skynet && $(MAKE) CC=$(CC) SKYNET_BUILD_PATH=$(SKYNET_BUILD_PATH) LUA_CLIB_PATH=$(LUA_CLIB_PATH) CSERVICE_PATH=$(CSERVICE_PATH) clean

写的很差,先用着吧。module_skynet是引用的skynet

2、复制module_skynet/example/config到本地目录。

然后修改config中的lua地址:

root = "./"
thread = 8
logger = nil
harbor = 1
address = "127.0.0.1:2526"
master = "127.0.0.1:2013"
start = "main"  -- main script
bootstrap = "snlua bootstrap"   -- The service for bootstrap
standalone = "0.0.0.0:2013"
luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua;".."module_skynet/service/?.lua;"..root.."module_skynet/test/?.lua;"..root.."module_skynet/examples/?.lua"
lualoader = "lualib/loader.lua"
-- preload = "./examples/preload.lua"   -- run preload.lua before every lua service run
snax = root.."examples/?.lua;"..root.."test/?.lua"
cpath = root.."cservice/?.so"
-- daemon = "./skynet.pid"

只修改其中 luaservice的地址。

3、启动 ./skynet config,提示找不到lualib/loader.lua,又建立了一个软连接指向module_skynet/lualib,可以顺利解决问题。

4、以上方式不保证是最合适的,但至少可以进行开发了。

syslog接收客户端发送的日志

仅仅是这一个简单的功能,不想再重新再用java重新做。

直接用nginx+php往syslog中写,syslog往mysql中输出,使用log查看工具查看日志。

php中打开syslog输出:

1、编辑php.ini

取消下面一行的注释

error_log = syslog

2、重启nginx+php

3、写php测试一下:

<?php
        openlog('php', LOG_CONS | LOG_NDELAY | LOG_PID, LOG_USER | LOG_PERROR);
        syslog(LOG_INFO, 'hello php');
?>

4、在/var/log/message中可以看到输出:

php[21641]:  hello php
php[21642]:  hello php
php[21643]:  hello php

rsyslog接收日志写入mysql配置

$EscapeControlCharactersOnReceive off

$template TraditionalFormat2,"%msg%\n"
$template TraditionalFormat3,"%syslogtag% %msg%\n"
$template TraditionalFormat4,"%syslogtag% %msg%\n"
$template StdSQLFormat,"insert into bi_action(id,serverId,`date`,`%msg:R,ERE,1,DFLT:\w+ \w+ (\w+)--end%`) values(%msg:R,ERE,1,DFLT:(\w+)--end%,%msg:R,ERE,1,DFLT:\w+ (\w+) \w+--end%,%$year%%$month%%$day%,1) on duplicate key update `%msg:R,ERE,1,DFLT:\w+ \w+ (\w+)--end%`=`%msg:R,ERE,1,DFLT:\w+ \w+ (\w+)--end%`+1  ",SQL



        if re_match($syslogtag,'^moon[0-9]+-[a-zA-Z_]+.log$') then {
                $ActionFileDefaultTemplate TraditionalFormat2
                $template DynFile2,"/opt/logs/router-log/%syslogtag:R,ERE,1,DFLT:(.*)-.*.log--end%/%timegenerated:1:10:date-rfc3339%/%syslogtag:R,ERE,1,DFLT:.*-(.*).log--end%.log"
                *.* -?DynFile2
                $ModLoad ommysql
                *.* :ommysql:127.0.0.1,Syslog,root,
                stop
        } else if re_match($syslogtag,'^moon[0-9]+$') then {
                        $ActionFileDefaultTemplate TraditionalFormat3
                        $template DynFile3,"/opt/logs/router-log/moon-alert.log"
                        *.* -?DynFile3
                        stop
        } else if re_match($syslogtag,'^moon[0-9]+\\-BI$') then {
                        $ActionFileDefaultTemplate TraditionalFormat4
                        $template DynFile4,"/opt/logs/router-log/moon-BI.log"
                        *.* -?DynFile4
                        *.*     >127.0.0.1,Syslog,root,;StdSQLFormat

                        stop
        }

ryzomcore 开源游戏代码

https://bitbucket.org/ryzom/ryzomcore

 

开始进行服务器调优,记录一下过程

开始进行服务器调优,记录一下过程,以便以后参考

1、服务器512M内存。mysql本地,日志rsyslog输出至远程。

2、直接往服务器发送10000个注册用户的请求,单socket,发送用了80毫秒,服务器处理完消耗89秒。

2.1) 关闭log后只需要27秒。但因为平时要使用log进行记录,不应该关闭log

2.2) 使用@Async标签,将db操作设置为异步,在dao上设置的@Async,未生效,处理时间还是一样长。

2.2) 1万个帐号注册只需要1分半,已经可以接受了。

3、测试1万帐号同时登陆。

3.1)需要同时开启10000个runnable,先试下同时开10000个socket的速度

3.2) 同时开始10000个socket,感觉速度还可以接受。

3.3)直接无限向服务器发送包,直接达到积累至几百万的消息包,先暂停优化。

3.3.1) 关闭log后,处理速度提升了两个数量级,发ping包,可以一次处理几十万也不会产生积累。但我写的机器人却卡死了,出现: GC overhead limit exceeded。jdk中自带的jvisualvm是个好东西。查找一下是哪里导致的挂掉。

3.4) 10000帐号同时并发登陆,好吧,直接卡死了。明天来解决。

3.5) 慢,非常慢。很耗时。

3.6) 猜测是否因为db读取慢的原因。测试db读取随机1万帐号只需要16秒。不是db读取的问题。

3.7) 打开日志,查看日志,发现一个现象:log处理中出现5秒的空白间隔,没有处理任何消息,经常出现。

3.8) 查找代码:

((InetSocketAddress) context.channel().remoteAddress()).getHostName();

问题出现在这里了,这里是阻塞方法,会去通过dns反查hostname。

修改为如下:

((InetSocketAddress) context.channel().remoteAddress()).getAddress().getHostAddress();

现在1万帐号登陆消耗38秒。

3.9 )  关闭日志后,1万帐号登陆只消耗11秒,已经可以接受了,上面测试的1万db读取需要16秒,这里更快是因为服务器是8线程同时处理登陆。

3.10) 关闭日志后,单socket发送1万帐号注册,处理完成31秒。这里有改进余地。暂时已经可以了。

3.11) 关闭日志后,多线程socket发送1万帐号注册,处理完成30秒。看这里主要是db io在消耗性能。

Android Asynchronous Http Client

loopj : http://loopj.com/android-async-http/

Android Asynchronous Http Client

学习下makefile

.PHONY : mingw ej2d linux undefined

CFLAGS = -g -Wall -Ilib -D EJOY2D_OS=$(OS)

// CFLAGS gcc接收的参数

// -g 生成调试信息,可用来gdb调试

// -Wall 输出gcc翻译时生成的警告信息

// -Ilib 将lib目录添加至编译查找路径,用来查找头文件

// gcc中命令行以tab开头

LDFLAGS :=

SRC := \
lib/shader.c \
lib/lshader.c \
lib/ejoy2dgame.c \
lib/fault.c \
lib/screen.c \
lib/texture.c \
lib/ppm.c \
lib/spritepack.c \
lib/sprite.c \
lib/lsprite.c \
lib/matrix.c \
lib/lmatrix.c \
lib/dfont.c \
lib/label.c \
lib/particle.c \
lib/lparticle.c \
lib/scissor.c

UNAME=$(shell uname)
SYS=$(if $(filter Linux%,$(UNAME)),linux,\
$(if $(filter MINGW%,$(UNAME)),mingw,\
$(if $(filter Darwin%,$(UNAME)),macosx,\
undefined\
)))

all: $(SYS)

undefined:
@echo “I can’t guess your platform, please do ‘make PLATFORM’ where PLATFORM is one of these:”
@echo ”      linux mingw macosx”

mingw : OS := WINDOWS
mingw : TARGET := ej2d.exe
mingw : CFLAGS += -I/usr/include -I/usr/local/include
mingw : LDFLAGS += -L/usr/bin -lgdi32 -lglew32 -lopengl32 -L/usr/local/bin -llua52
mingw : SRC += mingw/window.c mingw/winfw.c mingw/winfont.c

mingw : $(SRC) ej2d

linux : OS := LINUX
linux : TARGET := ej2d
linux : CFLAGS += -I/usr/include -I/usr/local/include $(shell freetype-config –cflags)
linux : LDFLAGS +=  -lGLEW -lGL -lX11 -lfreetype -llua -lm -Wl,-E
linux : SRC += posix/window.c posix/winfw.c posix/winfont.c

linux : $(SRC) ej2d

macosx : OS := MACOSX
macosx : TARGET := ej2d
macosx : CFLAGS += -I/usr/X11R6/include -I/usr/include -I/usr/local/include $(shell freetype-config –cflags) -D __MACOSX
macosx : LDFLAGS += -L/usr/X11R6/lib  -lGLEW -lGL -lX11 -lfreetype -llua -lm -Wl,-E -ldl
macosx : SRC += posix/window.c posix/winfw.c posix/winfont.c

macosx : $(SRC) ej2d

ej2d :
gcc $(CFLAGS) -o $(TARGET) $(SRC) $(LDFLAGS)

// gcc需要以tab开头

clean :
-rm -f ej2d.exe
-rm -f ej2d

.PHONY : all clean 

CFLAGS = -g -Wall 
LDFLAGS = -lpthread -llua -lm

uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
ifeq ($(uname_S), Darwin)
	SHARED = -fPIC -dynamiclib -Wl,-undefined,dynamic_lookup
// -fPIC 生成的地址改为相对地址,生成共享库时需要指定为相对地址
// -dynamiclib darwin系统中生成动态链接库参数
// -Wl,option 将option当做一个参数传给linker
else
	LDFLAGS += -lrt -Wl,-E
	SHARED = -fPIC --shared
endif

ifneq ($(uname_S), FreeBSD)
	LDFLAGS += -ldl
endif

all : \
  skynet \
  service/snlua.so \
  service/logger.so \
  service/gate.so \
  service/client.so \
  service/master.so \
  service/multicast.so \
  service/tunnel.so \
  service/harbor.so \
  service/localcast.so \
  luaclib/skynet.so \
  luaclib/socketdriver.so \
  luaclib/int64.so \
  luaclib/mcast.so \
  luaclib/bson.so \
  luaclib/mongo.so \
  client

skynet : \
  skynet-src/skynet_main.c \
  skynet-src/skynet_handle.c \
  skynet-src/skynet_module.c \
  skynet-src/skynet_mq.c \
  skynet-src/skynet_server.c \
  skynet-src/skynet_start.c \
  skynet-src/skynet_timer.c \
  skynet-src/skynet_error.c \
  skynet-src/skynet_harbor.c \
  skynet-src/skynet_multicast.c \
  skynet-src/skynet_group.c \
  skynet-src/skynet_env.c \
  skynet-src/skynet_monitor.c \
  skynet-src/skynet_socket.c \
  skynet-src/socket_server.c \
  luacompat/compat52.c
	gcc $(CFLAGS) -Iluacompat -o $@ $^ -Iskynet-src $(LDFLAGS)

luaclib:
	mkdir luaclib

service/tunnel.so : service-src/service_tunnel.c
	gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src

service/multicast.so : service-src/service_multicast.c
	gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src

service/master.so : service-src/service_master.c
	gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src

service/harbor.so : service-src/service_harbor.c
	gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src

service/logger.so : skynet-src/skynet_logger.c
	gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src

service/snlua.so : service-src/service_lua.c service-src/luacode_cache.c service-src/luaalloc.c
	gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ -Iskynet-src

service/gate.so : service-src/service_gate.c
	gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src

service/localcast.so : service-src/service_localcast.c
	gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src

luaclib/skynet.so : lualib-src/lua-skynet.c lualib-src/lua-seri.c lualib-src/trace_service.c lualib-src/timingqueue.c | luaclib
	gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ -Iskynet-src -Iservice-src -Ilualib-src

service/client.so : service-src/service_client.c
	gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src

luaclib/socketdriver.so : lualib-src/lua-socket.c | luaclib
	gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ -Iskynet-src -Iservice-src

luaclib/int64.so : lua-int64/int64.c | luaclib
	gcc $(CFLAGS) $(SHARED) -Iluacompat -O2 $^ -o $@ 

luaclib/mcast.so : lualib-src/lua-localcast.c | luaclib
	gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ -Iskynet-src -Iservice-src

luaclib/bson.so : lualib-src/lua-bson.c | luaclib
	gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ 

luaclib/mongo.so : lualib-src/lua-mongo.c | luaclib
	gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ 

client : client-src/client.c
	gcc $(CFLAGS) $^ -o $@ -lpthread

clean :
	rm skynet client service/*.so luaclib/*.so

找到一个编辑json表格ajax grid控件

jQuery UI Widgets

策划还是比较喜欢原来的类似表格来编辑,不喜欢直接编辑json格式。

在网上找到了jqwidgets,里面的grid控件正好满足需求。

<script type="text/javascript">
        $(document).ready(function () {
        	var url='<c:url value='/gm/Gm/readParameter?id=${parameter.id}'/>';
            var source =
            {
                datatype: "json",
                datafields: [
                    { name: 'id', type: 'int' },
                    { name: 'name', type: 'string' },
                    { name: 'gmLoginUrl', type: 'string' },
                    { name: 'ip', type: 'string' },
                    { name: 'port', type: 'int' },
                    { name: 'status', type: 'int' },
                    { name: 'recommend', type: 'bool' }
                ],
                id: 'id',
                url: url
            };
            var dataAdapter = new $.jqx.dataAdapter(source);
            $("#jqxgrid").jqxGrid(
            {
                width: 1200,
                source: dataAdapter,
                columnsresize: true,
                editable: true,
                columns: [
                  { text: 'id', datafield: 'id', width: 50 },
                  { text: 'name', datafield: 'name', width: 150 },
                  { text: 'ip', datafield: 'ip', width: 120 },
                  { text: 'port', datafield: 'port', minwidth: 120 },
                  { text: '状态', datafield: 'status', minwidth: 50 },
                  { text: '推荐', datafield: 'recommend', maxwidth: 50,columntype: 'checkbox' },
                  { text: '后台连接', datafield: 'gmLoginUrl', width: 280 }
                ]
            });
            $("#jsonExport").jqxButton({});
            $("#jsonExport").click(function () {
                var gridContent=$("#jqxgrid").jqxGrid('exportdata', 'json');
                $("#editParameterForm_json").val(gridContent);
                $("#editParameterForm").submit();
            });
        });</script>

在使用grid导出json时,数字被3个一组分组了,12345被格式化为 12,345 生成后面一堆错误。

最终未找到的完美的解决方式,只好设置这一列为字符串,避免被分组。

 

java上的协程

最近几天,有时间查看了一下java的中协程。

在java中大大小小的协程框架竟然有20多个,-.-!

总的来说java本身不支持协程,因此需要在vm级别进行修改才可以支持协程。

vm修改,分为两种,一种是直接修改生成的class bytecode如kilim之类。

另一类是直接运行在vm上的语言级别的支持,比如:akka。

kilim和akka也是目前公认的性能最好的框架。

我先测试了一下kilim,确实非常不错。多线程完全避免了线程切换和内存锁,而且使用url和sleep也不会阻塞线程运行。

我的电脑是8核cpu,在kilim中使用sleep,达到8个时会被线程阻塞。查找下解决方案。

我在kilim中使用的是Thread.sleep,如果改为使用kilim自带的sleep,则不会阻塞线程。

基本上搞明白了,kilim只是将线程改为了协程,避免了线程的上下文切换,但如果计算会阻塞,依旧会阻塞kilim,看来,httpclient及数据库操作和io需要改为non-blocking,才可以发挥kilim的全部性能。

kilim中还需要解决同步访问数据库、操作文件等问题,这些都必须改为non-blocking。

接着尝试下将server改为kilim,比较下性能。

学习小记

今天跑通了ejoy2d。

了解到了mingw的功能,真是c/c++开发必备利器。基本上无缝移植至linux系统。

了解到了glew,跨平台的opengl开发工具包。不过好像只支持windows,linux,ios,android的支持未发现。

下载了powervr sdk,看起来powervr sdk支持所有平台,需要试一下。

另外需要学习luabinding。

 

 


Warning: Use of undefined constant XML - assumed 'XML' (this will throw an Error in a future version of PHP) in /opt/wordpress/wp-content/plugins/wp-syntaxhighlighter/wp-syntaxhighlighter.php on line 1048