java--遊戲後端--項目開發總結--服務端

  1. 功能
    1. 客戶端交互
      1. 客戶端獲取服務器列表客戶端
      2. 獲取公告
    2. CDN服務
      1. 資源包上傳
      2. 更新資源
    3. 服務端交互
      1. 服務端驗證登陸
      2. 支付分發給服務端
    4. 數據配置
    5. GM功能
    6. 數據統計
  2. 技術
    1. 高級語言--Java8
    2. 框架--SpringBoot2.0
    3. 項目管理--Gradle
    4. 緩存--redis
    5. 數據庫Mysql5.6
    6. 通訊框架--Netty
    7. 傳輸框架--Protostuff
  3. 啓動流程
    1. 不佔用端口啓動
    2. 經過註解獲取協議進行初始化
    3. 初始化線程池用於有序處理客戶端消息
    4. 初始化遊戲數據
    5. 向後臺獲取遊戲配置數據
    6. 初始化定時任務用於定時更新數據
    7. 啓動Netty
  4. 關閉流程
    1. 實現接口ApplicationListener<ContextClosedEvent>
    2. 配置中註冊監聽
    3. 服務器關閉前處理臨時數據落地到數據庫
  5. 開發總結
    1. 關於緩存
      1. 緩存使用的redis
      2. 使用Jackson2JsonRedisSerializer替換了value的序列化與反序列化,可是對應map的序列化若是有排序要求,即便使用ConcurrentSkipListMap有序的集合,依然在反序列化的時候回出現順序錯誤,在redis可視化工具看到的數據順序是對的
    2. 關於成就設計
      1. 成就採用的是spring自帶的事件系統
      2. 業務處理完回到數據完成後能夠提交事件
      3. 在成就或任務系統中對事件進行處理
    3. 關於線程池
      1. 重寫了拒絕策略
      2. /**
             * 在線程池提交任務的最後一步——被線程池拒絕的任務,能夠在拒絕後調用隊列的put()方法,讓任務的提交者阻塞,直到隊列中任務被被線程池執行後,隊列有了多餘空間,調用方纔返回
             */
            private static class BlockCallerPolicy implements RejectedExecutionHandler {
                @Override
                public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                    try {
                        executor.getQueue().put(r);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
    4. 關於業務初始化
      1. 使用了接口
      2. /**
         * 初始化接口
         *
         * @date :2019/3/14 17:15
         */
        public interface InitBaseHandler {
            /**
             * 實現此方法將在服務器啓動時進行初始化操做
             */
            void init();
        }
      3. 此接口能夠在應用初始化時調用,將調用實現此接口的全部實現類
      4.         LogHandler.info("no2.初始化遊戲數據......");
                applicationContext.getBeansOfType(InitBaseHandler.class).values().forEach(InitBaseHandler::init);
    5. 關於定時器
      1. 先使用的每分鐘一次的定時器
      2.     /**
             * 定時更新
             */
            @Override
            public void init() {
                LogHandler.info("初始化定時任務");
                int second = Calendar.getInstance().get(Calendar.SECOND);
                ExecutorHandler.scheduledExecutorService.scheduleAtFixedRate(() -> {
                    Calendar calendar = Calendar.getInstance();
                    int minute = calendar.get(Calendar.MINUTE);
                    if (minute % INTERVAL == 0) {
                        playerService.updatePlayer();
                        playerService.updatePlayerData();
                        globalService.updateGlobalData();
                    }
                }, 60 - second, 60, TimeUnit.SECONDS);
            }
      3. 後期會優化爲擴展性更高的相似linux的cron月日時分定時器
        1. 沒有考慮年
        2. 若是須要能夠增長季度
        3. 沒有考慮秒
        4. 聊天隊列會單獨使用秒定時器
相關文章
相關標籤/搜索