1 of 21

Гонки на Erlang

SPBHUG 14.03.2012

Антон Ланцов

anton.lantsov@gmail.com

2 of 21

http://vk.com/app468346

3 of 21

4 of 21

5 of 21

6 of 21

7 of 21

PHP

//5600 строк кода

while(true){

  for(socket in getSockets()){

     while(socket.hasMessage){

        handle(socket.next());

     }

  }

}

8 of 21

Сервер на JAVA

9 of 21

Erlang

10 of 21

процессы

  • Заезд
  • Менеджер заездов
  • Чат
  • Клиент
  • Чтение сообщений
  • Отправка сообщений

11 of 21

Создание заезда

12 of 21

handle_cast({createLobby, LobbyInfo, FirstClientPID, FirstClientInfo, User}, State) ->

removeFromAllLobbies(FirstClientInfo#clientInfo.clientID, State),

NewState = case checkLobbyPossibility(LobbyInfo, FirstClientInfo, User) of

ok ->

NextLobbyID = State#state.nextLobbyID,

Type = if State#state.cityID =:= 3 andalso LobbyInfo#lobbyInfo.league =/= 4 ->

team;

true ->

normal

end,

NewLobbyInfo = LobbyInfo#lobbyInfo{id=NextLobbyID, type = Type},

{ok, NewLobbyPID} = lobby:start(NewLobbyInfo, State#state.cityID, self()),

erlang:monitor(process, NewLobbyPID),

lobby:addClient(FirstClientPID, FirstClientInfo, NewLobbyPID, joinLobby),

NewLobbies = dict:store(State#state.nextLobbyID, {NewLobbyPID, NewLobbyInfo}, State#state.lobbies),

NewState1 = State#state{nextLobbyID=NextLobbyID+1, lobbies=NewLobbies},

NewState1;

{error, {Reason, Message}} ->

FirstClientPID ! {createLobby, error, {Reason, Message}},

State

end,

{noreply, NewState};

13 of 21

14 of 21

15 of 21

16 of 21

Обработка ошибок

  • Удаление мусора
  • Перезапуск важных процессов

17 of 21

Проблемы с сетью

terminate(Reason, State) ->

State#state.clientPID ! {socketClosed, Reason},

ok.

18 of 21

Другие проблемы клиента

terminate(Reason, State) ->

  • if State#state.currentCity =/= undefined ->
  • cityManager:removeClient(State#state.currentCity, State#state.clientID);
  • true -> ok end,
  • timer:cancel(State#state.pingTimer),
  • if State#state.lobbyPID /= undefined ->
  • lobby:removeClient(State#state.clientID, State#state.lobbyPID);
  • true ->
  • ok
  • end,
  • if State#state.socket =/= nosocket ->
  • gen_tcp:close(State#state.socket),
  • exit(State#state.socketSenderPID, kill);
  • true -> ok end.

19 of 21

init([ConfigPath | _Args]) ->

Config = utils:readConfig(ConfigPath++"server.cfg"),

SecureConfig = utils:readConfig(?SECURE_CFG_PATH),

mneser:start(),

Log = {log, {log, start_link, [get(Config, logBasePath)]},

permanent, 2000, worker, [log]},

QueryCache = {queryCache, {queryCache, start_link, []},

permanent, 2000, worker, [queryCache]},

SystemStats = {systemStats, {systemStats, start_link, []},

permanent, 2000, worker, [systemStats]},

Vkontakte = {vkontakte, {vkontakte, start_link, [...]},

permanent, 2000, worker, [vkontakte]},

CityManager = {cityManager, {cityManager, start_link, []},

permanent, 2000, worker, [cityManager]},

CitySupervisor1 = {citySupervisor1, {citySupervisor, start_link, [1]},

permanent, 2000, supervisor, [citySupervisor]}, X3

Backuper = {backuper, {backuper, start_link, [get(Config, backupPeriod)]},

permanent, 2000 , worker, [backuper]},

ServerSocket = {serverSocket, {serverSocket, start_link, [get(Config, gamePort)]},

permanent, 2000, worker, [serverSocket]},

FlashSecurity1 = {flashSecurity1, {flashSecurity, start_link, [get(Config, flashSecurePort)]},

permanent, 2000, worker, [flashSecurity]},

Children = [Log, QueryCache, Vkontakte, CityManager, CitySupervisor1..3, Backuper, ServerSocket, FlashSecurity1..2],

{ok, {{one_for_one, 3, 10}, Children}}.

20 of 21

статистика

  • 17000 LOC
  • Uptime > 4 месяцев
  • до 600 пользователей онлайн
  • ~ 30 таблиц

21 of 21

вопросы?