空山雪林通用模塊工作室

           

          高可用性服務端的設計與實現

          本文的客戶端基于我們的GQT開源項目:http://cxlh.iteye.com/blog/2021463

           

          本人拙見,如有不同意見,歡迎拍磚,同時獻給特別有對服務端跨語言需求的程序猿們!

          客戶端(GQT Demo V3(服務端配套版).rar)太大請挪步到QQ群下載(群號:101189702),注明:GQT或Java,C++等;

          Java工程代碼請挪步下載:http://cxlh.iteye.com/blog/2074307 


          總體設計思路: 

           

          1. 高可用性:每個業務服務端都是獨立的個體,任何一個業務服務器Crash時,都不會影響服務,并且業務服務器可以按需增加,業務服務端使用Java代碼實現,主要是為了考慮更好的數據庫操作,更好的事務支持,更好的社區支持以及可用更多的開源服務,提高開發效率;
          2. 自動負載均衡:當某個接口頻繁調用,增加的響應服務器自動分流接口調用壓力,也就說我們的異步的請求/響應模式下,有一個Broker仲裁程序決定客戶端發來的請求交由哪個Java業務服務器來處理,這個Broker程序我們采用C++代碼實現;
          3. 客戶端(包括桌面或移動端)網關:根據策略選取遠程Socket服務器連接,Socket服務器與服務器之間的消息通訊通過地址尋址遠程路由,以便連在不同Socket服務器上的用戶之間可以相互通訊,典型的應用就是聊天程序;
          4. Sub/Pub類消息:客戶端訂閱服務端的服務,服務端有多個Pub服務器(Java編寫),交由Socket服務器將客戶端Sub的消息Push給Client,此時Socket服務只作為Proxy用;

            好了,其實這里只有2個C++核心組件(Socket服務器,Broker仲裁程序)和N個Java業務服務器(請求處理服務器,Pub服務器),以下介紹用法(需要一定的客戶端編程知識和一些腳本只是):

          客戶端發送請求,異步收取,編寫業務代碼步驟:

           

          編寫Java服務端,比如我們編寫一個按關鍵字讀取股票列表等接口(依賴注入用的Spring):

          @Repository @CacheNamespace(implementation = org.mybatis.caches.ehcache.EhcacheCache.class, readWrite = true) public interface StockDao { 	@Select("select SYMBOL,SHORT_NAME from `master`") 	public List<Map> listStock(); 	 	@Select("select SYMBOL,SHORT_NAME from `master` where SHORT_NAME like '%${k}%' or SPELL_NAME like '%${k}%' or SYMBOL like '%${k}%' limit 0,10") 	public List<Map> listStockByKeyword(Map<String,String> map); 	 	@Select("select SYMBOL,SHORT_NAME from `master` where exch_id=8") 	public List<Map> listAllSh(Map<String,String> map); 	 	@Select("select SYMBOL,SHORT_NAME from `master` where trade_date=#dt#") 	public List<Map> listStockByDate(Map<String,String> map); }

          編寫Java服務就這么簡單:

          package com.gqt.demo;

          import java.io.File;
          import java.io.FileInputStream;
          import java.io.InputStream;
          import java.util.Properties;
          import java.util.ResourceBundle;

          import org.apache.logging.log4j.LogManager;
          import org.apache.logging.log4j.Logger;

          import com.gqt.server.BaseReqServer;
          import com.gqt.server.ReqCallBack;

          public class StockServer extends BaseReqServer {
              private static Logger logger = LogManager.getLogger(StockServer.class.getName());
              
              final static Properties prop = new Properties();
              static{
                  InputStream is = null
                  try {
                      String c_path = StockServer.class.getResource("/").getPath();
                      logger.info("c_path:{}",c_path);
                      is = new FileInputStream(new File(c_path+"config.properties"));
                      prop.load(is);
                  } catch (Exception e) {
                      e.printStackTrace();
                  }

              }
              public StockServer(String ip, String port, ReqCallBack callback) {
                  super(ip, port, callback);
              }
              public static void main(String[] args) {
                  logger.info("=============StockServer========");
                  new Thread(){
                      @Override
                      public void run() {
                          ReqCallBack callback = new StockCallBack();
                          String ip = prop.getProperty("gqt-reqserver-ip");
                          String port = prop.getProperty("gqt-reqserver-port");
                          final StockServer ss = new StockServer(ip,port,callback);
                          ss.startServer();
                      }
                  }.start();
              }
          }

          編寫客戶端C++或腳本:

          gw.req("命令代碼"."命令代碼對應的參數列表"); //回調函數 gw.s_cb_gw.connect(function(trcode,msg){ 	log("-----------------------------------------------------------------"); 	log("<p>gqt server異步方式獲取數據,回調信息:trcode=" + trcode + ",msg=" + msg+"</p>"); });

           

          效果如下:

           

           

           

           

          這樣做的好處:

           

          1. 桌面或移動的客戶端再也不用編寫繁瑣的網絡通信相關的程序,只需要發送請求/訂閱,處理響應/訂閱數據包即可,也不用關心底層的數據分包合包,客戶端代理,網絡傳輸的加解密和壓縮等;
          2. 客戶端開發人員也幾乎不用和服務端程序員溝通,通過JSON解析請求透傳給Java,Java響應的數據帶上包頭和響應給客戶端,客戶端解析JSON即可;
          3. 跨語言的服務端雖然會損失一定的性能,但似乎這點ZeroMQ已做的足夠好;

           

          Demo程序部署步驟:

           

          1. 創建一個MySQL Demo數據庫,數據庫名:stock,utf-8編碼,導入output下的stock.sql;
          2. 配置output下的config.properties文件,指定機器IP,配置jdbc.properties,確保數據庫配置正確;
          3. 點擊runStockServer.bat,運行stock的Java Demo服務器,可以開任意個;
          4. 配置gqt-server-communicator(cpp)下的config_ims.ini文件,IP地址全部換成機器IP;
          5. 啟動ss_server.exe,ss_zserver.exe;
          6. 點擊客戶端GQT程序,配置config_ims.ini中的IP地址,切換到gateway的標簽頁,enjoy it!


           

          posted on 2014-05-30 16:15 徐靈 閱讀(1235) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          導航

          友情鏈接

          最新評論

          主站蜘蛛池模板: 博客| 泗洪县| 巴东县| 吉木萨尔县| 绿春县| 上林县| 南投县| 光山县| 雷波县| 视频| 莫力| 卓资县| 四平市| 溧阳市| 东阿县| 淮滨县| 新密市| 涡阳县| 慈溪市| 阿尔山市| 土默特右旗| 吉首市| 温州市| 乌兰浩特市| 襄垣县| 徐水县| 乃东县| 乐清市| 皋兰县| 金溪县| 澳门| 山阴县| 武平县| 拜城县| 霍山县| 丁青县| 天气| 五河县| 陆河县| 喜德县| 白朗县|