1. 程式人生 > >微服務--webapi實現,脫離iis,脫離tomcat

微服務--webapi實現,脫離iis,脫離tomcat

前言

微服務,顧名思義就是微小的單一的服務程式,單一流程,單一發布,開發和部署都可獨立;

這是我的理解;

但基於web的服務,不管是webservice還是webapi等類似的服務都需要基於iis或者tomcat,

本文介紹重點繞過iis或tomc部署基於http服務明文程式;

所謂明文程式就是原始碼釋出;當然你也可以不必是原始碼釋出,這個可以個人需求;

序言

請不要問我為什麼不直接使用web現成的架構,進行開發部署,

第一:我的專案有這樣的需求;原本就是一個服務程式,提供socket tcp協議資料服務;並且需要提供socket http協議服務;

第二:梳理自己的知識;

第三:對微服務和webapi概念進行強化和模擬實現;

正文開始

在閱讀這篇文字之前建議優先檢視之前文章,比如執行緒,指令碼,socket 服務等;

本文先從java版本開始講解;稍後依然會寫上C#,但是程式碼機制都是一樣的;本程式習慣作風,java和C#雙版本共存;

 本人程式碼風格習慣,:

專案主包下面包含功能塊實現;功能塊裡面包含單例管理器,如果需要有指令碼介面處理iscript裡面包含介面的處理形式

我們優先建立檔案IWebApiScript

 1 package net.sz.game.test.webapi.iscript;
 2 
 3 import net.sz.game.engine.nio.nettys.http.NioHttpRequest;
4 import net.sz.game.engine.scripts.IBaseScript; 5 6 /** 7 * 8 * <br> 9 * author 失足程式設計師<br> 10 * blog http://www.cnblogs.com/ty408/<br> 11 * mail [email protected]<br> 12 * phone 13882122019<br> 13 */ 14 public interface IWebApiScript extends IBaseScript { 15 16
/** 17 * 獲取路由設定。自動註冊版 18 * 19 * @return 20 */ 21 String getRoute(); 22 23 boolean action(String url, NioHttpRequest request); 24 25 }
View Code

 建立WebApiManager

 1 package net.sz.game.test.webapi;
 2 
 3 import java.util.ArrayList;
 4 import net.sz.game.engine.nio.nettys.NettyPool;
 5 import net.sz.game.engine.nio.nettys.http.NettyHttpServer;
 6 import net.sz.game.engine.nio.nettys.http.NioHttpRequest;
 7 import net.sz.game.engine.nio.nettys.http.handler.IHttpHandler;
 8 import net.sz.game.engine.scripts.IBaseScript;
 9 import net.sz.game.engine.scripts.manager.ScriptManager;
10 import net.sz.game.engine.szlog.SzLogger;
11 import net.sz.game.test.webapi.iscript.IWebApiScript;
12 
13 /**
14  *
15  * <br>
16  * author 失足程式設計師<br>
17  * blog http://www.cnblogs.com/ty408/<br>
18  * mail [email protected]<br>
19  * phone 13882122019<br>
20  */
21 public class WebApiManager {
22 
23     private static SzLogger log = SzLogger.getLogger();
24     private static final WebApiManager IN_ME = new WebApiManager();
25 
26     public static WebApiManager getInstance() {
27         return IN_ME;
28     }
29 
30     public void init() {
31         /*獲取http繫結*/
32         NettyHttpServer addBindHttpServer = NettyPool.getInstance().addBindHttpServer("127.0.0.1", 9527);
33 
34         /*新增黑名單 禁止訪問名單*/
35         //addBindHttpServer.addBlackIP("");
36         /*新增白名單 必須包含的訪問*/
37         //addBindHttpServer.addWhiteIP("");
38         addBindHttpServer.addHttpBind(new IHttpHandler() {/*使用匿名物件*/
39 
40             @Override
41             public void run(String url, NioHttpRequest request) {
42                 /*每次都是獲取最新集合*/
43                 ArrayList<IBaseScript> evts = ScriptManager.getInstance().getBaseScriptEntry().getEvts(IWebApiScript.class.getName());
44                 if (evts != null && !evts.isEmpty()) {
45                     for (int i = 0; i < evts.size(); i++) {
46                         IWebApiScript iWebApiScript = (IWebApiScript) evts.get(i);
47                         /*查詢需要處理的明文指令碼 webapi 路由*/
48                         if (iWebApiScript.getRoute().equalsIgnoreCase(url)) {
49                             /*返回值也行有其他用途*/
50                             boolean action = iWebApiScript.action(url, request);
51                             /*跳出迴圈*/
52                             break;
53                         }
54                     }
55                 }
56                 /*回覆客戶端請求*/
57                 request.respons();
58             }
59         }/*處理程式*/, 10/*執行緒量提高併發處理*/, "*"/*監聽狀態*/);
60         /*socket 使用*/
61         addBindHttpServer.start(4);
62     }
63 }

當前我們並沒有實現路由註冊,

我們看看效果將會是怎麼樣的;

 

當我們在瀏覽器輸入的時候,不會有任何回覆產生;

接下來我們試試明文指令碼的路由自動註冊效果來回復請求;

我們新建專案,保持專案路徑一直;

net.sz.game.test.scripts

我們在webapi的指令碼目錄下建立index路由監聽

 1 package net.sz.game.test.scripts.webapi;
 2 
 3 import net.sz.game.engine.nio.nettys.http.NioHttpRequest;
 4 import net.sz.game.engine.szlog.SzLogger;
 5 import net.sz.game.test.webapi.iscript.IWebApiScript;
 6 
 7 /**
 8  *
 9  * <br>
10  * author 失足程式設計師<br>
11  * blog http://www.cnblogs.com/ty408/<br>
12  * mail [email protected]<br>
13  * phone 13882122019<br>
14  */
15 public class IndexScript implements IWebApiScript {
16 
17     private static SzLogger log = SzLogger.getLogger();
18 
19     @Override
20     public String getRoute() {
21         return "index";
22     }
23 
24     @Override
25     public boolean action(String url, NioHttpRequest request) {
26         /*新增輸出內容,html資料,json資料,txt資料,xml資料,自己定義就好*/
27         request.addContent("我是明文webapi自動註冊路由");
28         return true;
29     }
30 
31 }

實現路由自動註冊我們需要在啟動main函式加入指令碼初始化函式呼叫 

 1 package net.sz.game.test.main;
 2 
 3 import java.util.ArrayList;
 4 import net.sz.game.engine.scripts.manager.ScriptManager;
 5 import net.sz.game.engine.szlog.SzLogger;
 6 import net.sz.game.test.webapi.WebApiManager;
 7 
 8 /**
 9  *
10  * <br>
11  * author 失足程式設計師<br>
12  * mail [email protected]<br>
13  * phone 13882122019<br>
14  */
15 public class Test_App_Manager {
16 
17     private static SzLogger log = SzLogger.getLogger();
18 
19     public static void main(String[] args) {
20 
21         /*載入所有指令碼檔案,預設載入專案路徑 -scripts 檔案下面所有問題*/
22         ArrayList<String> loadScripts = ScriptManager.getInstance().reload();
23         String join = String.join(",", loadScripts);
24         log.error(join);
25         /*初始化監聽*/
26         WebApiManager.getInstance().init();
27     }
28 }

 啟動程式測試

 啟動程式以後我們看到首先刪除了程式專案下面之前的指令碼臨時檔案,然後重新載入最新指令碼檔案;成功載入指令碼:net.sz.game.test.scripts.webapi.IndexScript, net.sz.game.test.webapi.iscript.IWebApiScript

在瀏覽器輸入http://127.0.0.1/index

成功輸出;

繼續新增login監聽;

 1 package net.sz.game.test.scripts.webapi;
 2 
 3 import net.sz.game.engine.nio.nettys.http.NioHttpRequest;
 4 import net.sz.game.engine.szlog.SzLogger;
 5 import net.sz.game.test.webapi.iscript.IWebApiScript;
 6 
 7 /**
 8  *
 9  * <br>
10  * author 失足程式設計師<br>
11  * blog http://www.cnblogs.com/ty408/<br>
12  * mail [email protected]<br>
13  * phone 13882122019<br>
14  */
15 public class LoginScript implements IWebApiScript {
16 
17     private static SzLogger log = SzLogger.getLogger();
18 
19     @Override
20     public String getRoute() {
21         return "login";
22     }
23 
24     @Override
25     public boolean action(String url, NioHttpRequest request) {
26         /*新增輸出內容,html資料,json資料,txt資料,xml資料,自己定義就好*/
27         request.addContent("我是明文webapi自動註冊路由 login 歡迎登陸");
28         return true;
29     }
30 
31 }
View Code

看看結果:

其實這個自動註冊我們目前依然需要重啟服務;或者不夠智慧;

動態載入路由指令碼;無需重啟服務

 1 package net.sz.game.test.scripts.webapi;
 2 
 3 import java.util.ArrayList;
 4 import net.sz.game.engine.nio.nettys.http.NioHttpRequest;
 5 import net.sz.game.engine.scripts.manager.ScriptManager;
 6 import net.sz.game.engine.szlog.SzLogger;
 7 import net.sz.game.test.webapi.iscript.IWebApiScript;
 8 
 9 /**
10  *
11  * <br>
12  * author 失足程式設計師<br>
13  * blog http://www.cnblogs.com/ty408/<br>
14  * mail [email protected]<br>
15  * phone 13882122019<br>
16  */
17 public class ReloadScript implements IWebApiScript {
18 
19     private static SzLogger log = SzLogger.getLogger();
20 
21     @Override
22     public String getRoute() {
23         return "reload";
24     }
25 
26     @Override
27     public boolean action(String url, NioHttpRequest request) {
28         /*重新讀取路由指令碼*/
29         ArrayList<String> loadScripts = ScriptManager.getInstance().reload();
30         String join = "動態載入結果:" + String.join(",", loadScripts);
31         log.error(join);
32         request.addContent(join);
33         return true;
34     }
35 
36 }

reload監聽裡面處理指令碼路由的更新操作;

之所以沒有使用檔案更新狀態進行操作,是因為那樣不可控;或許我現在只是釋出,但是不需要更新;等待指定時間更新;

重新訪問login

敘述

以上程式碼我們完成路由自動註冊,

值的注意的有幾點:

1,我們通過的指令碼化實現的路由自動註冊功能;所以程式碼是明文的,破壞危險,掛馬危險,較高;

2,我沒有加入驗證機制;這個可以自行約定;確實了iis或tomcat的sesstion 和cokie的這種快取機制;但好處在於可控性很高,不管是快取,資料流向,自定義格式;不受iis或Tomcat限制;

3,但是我們可以做到動態釋出,動態更新,在不重啟服務的,不影響其他服務的情況下,劃分出了,功能獨立開發,獨立部署,互不干涉的情況;

之所以我文章開頭定義微服務也就是這個原理,可以實現服務介面的動態增加刪除,獨立開發,獨立部署,單一流程;當然可以相互協調呼叫服務介面;

C#.net

在我的版本庫或者叫框架裡面依然實現了netty的呼叫的;

 1 using Net.Sz.Framework.Netty;
 2 using Net.Sz.Framework.Netty.Http;
 3 using System;
 4 using System.Collections.Generic;
 5 using System.Linq;
 6 using System.Text;
 7 using System.Threading.Tasks;
 8 
 9 namespace CApp_Webapi
10 {
11     class Program
12     {
13         static void Main(string[] args)
14         {
15 
16             HttpServer httpserver = NettyPool.AddHttpBind("127.0.0.1", 9527, 2);
17 
18             httpserver.AddHandler("*", new ActionHttpHandler((session) =>
19             {
20                 session.AddContent("<html><body>webapi!</body></html>");
21             }));
22 
23             httpserver.AddHandler("login", new ActionHttpHandler((session) =>
24             {
25                 session.AddContent("<html><body>login holle !</body></html>");
26             }));
27 
28             httpserver.Start();
29 
30         }
31     }
32 }

所以就簡單測試,不在過多的去實現和講解理論,都是一樣的;

C#版本,不管你是基於控制檯專案,from專案還是service專案;都可以完美的執行;

總結

之前在iis裡面建立static變數的共享資料的時候web專案在程式池沒有被回收的情況下,static的資源沒有了;需要加入到web.cache集合裡面進行載入和呼叫;

同樣也是,我是做遊戲後端開發的,不管是socket的tcp協議還是socket的http協議,都需要進行處理;但是程式肯定是放在一起,不能經過iis等再次進行呼叫;

這篇文章在於,實現socket http請求,路由自動註冊概念,微服務概念;已經指令碼化的明文處理介面實現;

至於指令碼的實現機制;大家可以檢視框架程式碼或者翻看之前的文章,但是之前的文章裡程式碼有很多已經和現在服務框架程式碼不經相同了;

C#版本的下面測試程式碼基本放在了

test的資料夾下面可以直接檢視專案對應的測試程式碼;

java專案則有所不同,都是maven專案,每一個專案下面都有測試包;

已經測試程式;所以沒有單獨專案;

老鐵們不點個推薦,評論一下嘛?

長友,巨友,段友;天王蓋地虎,寶塔鎮河妖;