Java 微服務框架 Redkale 入門介紹
Redkale 功能
Redkale雖然只有1.xM大小,但是麻雀雖小五臟俱全。既可作為伺服器使用,也可當工具包使用。作為獨立的工具包提供以下功能:
1、convert包提供JSON的序列化和反序列化功能,類似Gson、Jackson。
2、convert包提供Java物件二進位制的序列化和反序列化功能,類似Protobuf。
3、source包提供很簡便的資料庫操作功能,類似JPA、Hibernate。
4、net包提供TCP/UDP服務功能, 類似Mina。
5、net.http提供HTTP服務, 類似Tomcat、Netty。
6、ResourceFactory提供輕量級的依賴注入功能, 類似Google Guice。
Redkale 伺服器
Redkale作為伺服器的目錄如下:
bin : 存放啟動關閉指令碼(start.sh、shutdown.sh、start.bat、shutdown.bat)
conf : 存放伺服器所需配置檔案:
application.xml: 服務配置檔案 (必需);
logging.properties:日誌配置檔案 (可選);
persistence.xml:資料庫配置檔案 (可選);
lib : 存放服務所依賴的第三方包,redkale.jar 放在此處。
logs : logging.properties 配置中預設的日誌存放目錄。
root : application.xml 配置中HTTP服務所需頁面的預設根目錄。
Redkale啟動的流程如下:
1、載入 application.xml 並解析。
2、初始化 <resources> 節點中的資源。
3、解析所有的 <server> 節點。
4、初始化並啟動所有<server> 節點的Server服務 (優先載入SNCP協議的Server)。
5、初始化單個Server:
5.1、掃描classpath載入所有可用的Service實現類(沒有標記為@AutoLoad(false)的類)並例項化,然後相互依賴注入。
5.2、Service例項在依賴注入過程中載入所需的DataSource、CacheSource資源。
5.3、呼叫所有本地模式Service的init方法。
5.4、掃描classpath載入所有可用的Servlet實現類(沒有標記為@AutoLoad(false)的類)並例項化 (優先例項化WebSocketServlet)。
5.5、給所有Servlet依賴注入所需的Service。
5.6、呼叫所有Servlet的init方法。
5.7、啟動Server的服務監聽。
6、啟動程式本身的監聽服務。
基於Redkale的開發與除錯
基於Redkale建立一個Java應用程式工程(即使是Web專案也不要建立Java-Web工程),引用redkale.jar 並建立Redkale所需的幾個目錄和檔案。一個普通的Web專案只需要編寫業務層的Service和接入層的HttpServlet的程式碼。資料庫DataSource通過配置檔案進行設定。
編寫完程式碼可以通過啟動指令碼進行除錯, 也可以在IDE設定專案的主類為 org.redkale.boot.Application 或者工程內定義主類進行啟動除錯:
public final class Bootstrap { public static void main(String[] args) throws Exception { org.redkale.boot.Application.main(args); } }
若需要除錯單個Service,可以通過 Application.singleton 方法進行除錯:
public static void main(String[] args) throws Exception { UserService service = Application.singleton(UserService.class); LoginBean bean = new LoginBean(); bean.setAccount("myaccount"); bean.setPassword("123456"); System.out.println(service.login(bean)); }
Application.singleton 執行流程與通過bin指令碼啟動的流程基本一致,區別在於singleton執行時不會啟動Server和Application自身的服務監聽。Redkale提倡接入層(Servlet)與業務層(Service)分開,Service在程式碼上不能依賴於Servlet,因此除錯Service自身邏輯時不需要啟動接入層服務(類似WebSocket依賴Servlet的功能除外)。
Redkale的依賴注入
Redkale內建的依賴注入實現很簡單,只有三個類: javax.annotation.Resource、org.redkale.util.ResourceType、org.redkale.util.ResourceFactory,採用反射技術,由於依賴注入通常不會在頻繁的操作中進行,因此效能要求不會很高。其中前兩個是註解,ResourceFactory是主要操作類,主要提供註冊和注入兩個介面。ResourceFactory的依賴注入不僅提供其他依賴注入框架的常規功能,還能動態的自動更新通過inject注入的資源。
public class AService { @Resource(name = "property.id") private String id; @Resource(name = "property.id") //property.開頭的資源名允許String自動轉換成primitive數值型別 private int intid; @Resource(name = "bigint") private BigInteger bigint; @Resource(name = "seqid") private int seqid; @Resource private ResourceTest.BService bservice; @Override public String toString() { return "{id:/"" + id + "/", intid: " + intid + ", bigint:" + bigint + "}"; } /** 以下省略getter setter方法 */ } public class BService { @Resource(name = "property.id") private String id; @Resource private AService aservice; private String name = ""; @java.beans.ConstructorProperties({"name"}) public BService(String name) { this.name = name; } @Override public String toString() { return "{name:/"" + name + "/", id: " + id + ", aserivce:" + aservice + "}"; } /** 以下省略getter setter方法 */ } public static void main(String[] args) throws Exception { ResourceFactory factory = ResourceFactory.root(); factory.register("property.id", "2345"); //注入String型別的property.id AService aservice = new AService(); BService bservice = new BService("eee"); factory.register(aservice); //放進Resource池內,預設的資源名name為"" factory.register(bservice); //放進Resource池內,預設的資源名name為"" factory.inject(aservice); //給aservice注入id、bservice,bigint沒有資源,所以為null factory.inject(bservice); //給bservice注入id、aservice System.out.println(aservice); //輸出結果為:{id:"2345", intid:2345, bigint:null, bservice:{name:eee}} System.out.println(bservice); //輸出結果為:{name:"eee", id:2345, aserivce:{id:"2345", intid:2345, bigint:null, bservice:{name:eee}}} factory.register("seqid", 200); //放進Resource池內, 同時ResourceFactory會自動更新aservice的seqid值 System.out.println(factory.find("seqid", int.class)); //輸出結果為:200 factory.register("bigint", new BigInteger("66666")); //放進Resource池內, 同時ResourceFactory會自動更新aservice物件的bigint值 System.out.println(aservice); //輸出結果為:{id:"2345", intid:2345, bigint:66666, bservice:{name:eee}}可以看出seqid與bigint值都已自動更新 factory.register("property.id", "6789"); //更新Resource池內的id資源值, 同時ResourceFactory會自動更新aservice、bservice的id值 System.out.println(aservice); //輸出結果為:{id:"6789", intid:6789, bigint:66666, bservice:{name:eee}} System.out.println(bservice); //輸出結果為:{name:"eee", id:6789, aserivce:{id:"6789", intid:6789, bigint:66666, bservice:{name:eee}}} bservice = new BService("ffff"); factory.register(bservice); //更新Resource池內name=""的BService資源, 同時ResourceFactory會自動更新aservice的bservice物件 factory.inject(bservice); System.out.println(aservice); //輸出結果為:{id:"6789", intid: 6789, bigint:66666, bservice:{name:ffff}} }
如上例,通過ResourceFactory.inject注入的物件都會自動更新資源的變化,若不想自動更新可以使用帶boolean autoSync引數的register系列方法(autoSync傳false)註冊新資源。
Redkale 架構部署
通常一個系統會分為三層:接入層、業務層、資料層。對應到Redkale的元件是: Servlet、Service、Source。大部分系統提供的是HTTP服務,為了方便演示Redkale從集中式到分散式的變化,以一個簡單的HTTP服務作為範例。
開發一個極簡單的小論壇系統。包含三個模組:
使用者模組 UserSerivice: 提供使用者註冊、登入、更新資料等功能, UserServlet作為接入層。
帖子模組 ForumSerivice: 提供看帖、發帖、刪帖等功能, ForumServlet作為接入層。
通知模組 NotifySerivice: 提供使用者操作、回帖等訊息通知功能, NotifyWebSocket是WebSocket的Servlet, 且name為 ws_notify,
作為接入層。
其中資料來源有:
DataSource: 在persistence.xml裡配置的資料庫Source的name為demodb ,三個模組都需要使用demodb。
CacheSource: 僅供UserSerivice用於存放session的快取Service,name為 usersessions, 且session只存放使用者ID( int 型別)。
1、單點部署
在早期使用者量很少或者開發、除錯環境中只需部署一個程式就可滿足需求。
如上圖,所有模組的HttpServlet、Service與Source資料庫操作全部署在一起。 application.xml作簡單的配置即可:
<application port="5050"> <server protocol="HTTP" port="6060" root="root"> <services autoload="true" /> <servlets autoload="true"/> </server> </application>
2、多點部署
在生產環境需要避免單點問題,一個服務一般會部署多套。在此做個簡單的容災部署,最前端部署一個nginx作反向代理和負載均衡伺服器,後面部署兩套系統。
如上圖,兩個程式間的Serivce都是本地模式,兩者會通過SNCP服務保持資料同步,若DataSource開啟了資料快取也會自動同步。兩套的配置檔案相同,配置如下:
<application port="5050"> <resources> <group name="ALL"> <node addr="192.168.50.110" port="7070"/> <node addr="192.168.50.120" port="7070"/> </group> </resources> <!-- HTTP 監聽 Server --> <server protocol="HTTP" port="6060" root="root"> <!-- 前端配置了nginx,需要配置才能獲取客戶端真實的IP地址 --> <request> <remoteaddr value="request.headers.X-RemoteAddress"/> </request> <services autoload="true" groups="ALL"/> <servlets autoload="true" /> </server> <!-- SNCP 監聽 Server --> <server protocol="SNCP" port="7070"> <services autoload="true" groups="ALL"> <!-- 有WebSocketServlet的服務必須配置WebSocketNodeService,且Redkale同時會自動建立一個同名(ws_notify)的 CacheSource --> <service name="ws_notify" value="org.redkale.service.WebSocketNodeService"/> <!-- 存在DataSource必須配置DataSourceService --> <service name="demodb" value="org.redkale.service.DataSourceService"/> <!-- 存放使用者HTTP session資訊的CacheSource --> <service name="usersessions" value="org.redkale.service.CacheSourceService"> <property name="key-type" value="java.lang.String"/> <property name="value-type" value="java.lang.Integer"/> </service> </services> </server> </application>
3、分層部署
隨著業務的複雜度增加,接入層與業務層混在一起會越來越難部署和維護,因此需要進行分層部署。
如上圖,對HttpServlet與Service進行了分離。每個接入層的Service都是遠端模式,業務層只需提供SNCP供遠端呼叫。
接入層中每個程式的配置相同,配置如下:
<application port="5050"> <resources> <group name="ALL"> <node addr="192.168.50.110" port="7070"/> <node addr="192.168.50.120" port="7070"/> </group> </resources> <!-- HTTP 監聽 Server --> <server protocol="HTTP" port="6060" root="root"> <!-- 前端配置了nginx,需要配置才能獲取客戶端真實的IP地址 --> <request> <remoteaddr value="request.headers.X-RemoteAddress"/> </request> <services autoload="true" groups="ALL"> <!-- 有WebSocketServlet的服務必須配置WebSocketNodeService,且Redkale同時會自動建立一個同名(ws_notify)的 CacheSource --> <service name="ws_notify" value="org.redkale.service.WebSocketNodeService"/> </services> <servlets autoload="true" /> </server> </application>
業務層中每個程式的配置相同,配置如下:
<application port="5050"> <resources> <group name="ALL"> <node addr="192.168.50.110" port="7070"/> <node addr="192.168.50.120" port="7070"/> </group> </resources> <!-- SNCP 監聽 Server --> <server protocol="SNCP" port="7070"> <services autoload="true" groups="ALL"> <!-- 有WebSocketServlet的服務必須配置WebSocketNodeService,且Redkale同時會自動建立一個同名(ws_notify)的 CacheSource --> <service name="ws_notify" value="org.redkale.service.WebSocketNodeService"/> <!-- 存在DataSource必須配置DataSourceService --> <service name="demodb" value="org.redkale.service.DataSourceService"/> <!-- 存放使用者HTTP session資訊的CacheSource --> <service name="usersessions" value="org.redkale.service.CacheSourceService"> <property name="key-type" value="java.lang.String"/> <property name="value-type" value="java.lang.Integer"/> </service> </services> </server> </application>
4、微服務部署
當使用者量和發帖量增加到上百萬的時候,明顯地將所有模組的服務部署到一個程式裡是不行的。 因此需要將Service服務都獨立部署形成微服務架構。
如上圖,將Serivice都獨立部署並進行容災部署,當然如果有需要,Servlet之間、Source都可以各自分離獨立部署。不同型別的Service之間都是遠端模式呼叫。
接入層中每個程式的配置相同,配置如下:
<application port="5050"> <resources> <group name="USER_SERVICE"> <node addr="192.168.50.110" port="7070"/> <node addr="192.168.50.111" port="7070"/> </group> <group name="NOTIFY_SERVICE"> <node addr="192.168.50.120" port="7070"/> <node addr="192.168.50.121" port="7070"/> </group> <group name="FORUM_SERVICE"> <node addr="192.168.50.130" port="7070"/> <node addr="192.168.50.131" port="7070"/> </group> </resources> <!-- HTTP 監聽 Server --> <server protocol="HTTP" port="6060" root="root"> <!-- 前端配置了nginx,需要配置才能獲取客戶端真實的IP地址 --> <request> <remoteaddr value="request.headers.X-RemoteAddress"/> </request> <services autoload="true"> <service value="org.redkale.demo.UserService" groups="USER_SERVICE"/> <service value="org.redkale.demo.NotifyService" groups="NOTIFY_SERVICE"/> <service value="org.redkale.demo.ForumService" groups="FORUM_SERVICE"/> <!-- 有WebSocketServlet的服務必須配置WebSocketNodeService,且Redkale同時會自動建立一個同名(ws_notify)的 CacheSource --> <service name="ws_notify" value="org.redkale.service.WebSocketNodeService" groups="NOTIFY_SERVICE"/> </services> <servlets autoload="true" /> </server> </application>
使用者模組UserService服務群中各個程式的配置相同,配置如下:
<application port="5050"> <resources> <group name="USER_SERVICE"> <node addr="192.168.50.110" port="7070"/> <node addr="192.168.50.111" port="7070"/> </group> <group name="NOTIFY_SERVICE"> <node addr="192.168.50.120" port="7070"/> <node addr="192.168.50.121" port="7070"/> </group> <group name="FORUM_SERVICE"> <node addr="192.168.50.130" port="7070"/> <node addr="192.168.50.131" port="7070"/> </group> </resources> <!-- SNCP 監聽 Server --> <server protocol="SNCP" port="7070"> <services autoload="true"> <service value="org.redkale.demo.NotifyService" groups="NOTIFY_SERVICE"/> <service value="org.redkale.demo.ForumService" groups="FORUM_SERVICE"/> <!-- 存在DataSource必須配置DataSourceService --> <service name="demodb" value="org.redkale.service.DataSourceService" groups="USER_SERVICE"/> <!-- 存放使用者HTTP session資訊的CacheSource --> <service name="usersessions" value="org.redkale.service.CacheSourceService" groups="USER_SERVICE"> <property name="key-type" value="java.lang.String"/> <property name="value-type" value="java.lang.Integer"/> </service> </services> </server> </application>
通知模組NotifyService服務群中各個程式的配置相同,配置如下:
<application port="5050"> <resources> <group name="USER_SERVICE"> <node addr="192.168.50.110" port="7070"/> <node addr="192.168.50.111" port="7070"/> </group> <group name="NOTIFY_SERVICE"> <node addr="192.168.50.120" port="7070"/> <node addr="192.168.50.121" port="7070"/> </group> <group name="FORUM_SERVICE"> <node addr="192.168.50.130" port="7070"/> <node addr="192.168.50.131" port="7070"/> </group> </resources> <!-- SNCP 監聽 Server --> <server protocol="SNCP" port="7070"> <services autoload="true"> <service value="org.redkale.demo.UserService" groups="USER_SERVICE"/> <service value="org.redkale.demo.ForumService" groups="FORUM_SERVICE"/> <!-- 有WebSocketServlet的服務必須配置WebSocketNodeService,且Redkale同時會自動建立一個同名(ws_notify)的 CacheSource --> <service name="ws_notify" value="org.redkale.service.WebSocketNodeService" groups="NOTIFY_SERVICE"/> <!-- 存在DataSource必須配置DataSourceService --> <service name="demodb" value="org.redkale.service.DataSourceService" groups="NOTIFY_SERVICE"/> </services> </server> </application>
帖子模組ForumService服務群中各個程式的配置相同,配置如下:
<application port="5050"> <resources> <group name="USER_SERVICE"> <node addr="192.168.50.110" port="7070"/> <node addr="192.168.50.111" port="7070"/> </group> <group name="NOTIFY_SERVICE"> <node addr="192.168.50.120" port="7070"/> <node addr="192.168.50.121" port="7070"/> </group> <group name="FORUM_SERVICE"> <node addr="192.168.50.130" port="7070"/> <node addr="192.168.50.131" port="7070"/> </group> </resources> <!-- SNCP 監聽 Server --> <server protocol="SNCP" port="7070"> <services autoload="true"> <service value="org.redkale.demo.UserService" groups="USER_SERVICE"/> <service value="org.redkale.demo.NotifyService" groups="NOTIFY_SERVICE"/> <!-- 存在DataSource必須配置DataSourceService --> <service name="demodb" value="org.redkale.service.DataSourceService" groups="FORUM_SERVICE"/> </services> </server> </application>
5、API閘道器式部署
隨著使用者量到了上千萬時,一個UserService的服務程式是無法提供全部使用者服務。 因此可以考慮按使用者段進行分散式部署。將192.168.50.110、192.168.50.111上的UserService服務改成閘道器式的服務。下面是以 Service本地模式介紹中的UserService 為範例進行編寫:
@ResourceType({UserService.class}) public class UserServiceGateWay extends UserService { @Resource(name = "userservice_reg") private UserService regUserService; //只用於註冊的服務節點 @Resource(name = "userservice_mob") private UserService mobUserService; //只用於查詢手機號碼對應的userid的服務節點 @Resource(name = "userservice_node01") private UserService userService01; //userid小於2000000的使用者的服務節點 @Resource(name = "userservice_node02") private UserService userService02; //userid小於4000000的使用者的服務節點 @Resource(name = "userservice_node03") private UserService userService03; //userid小於6000000的使用者的服務節點 @Resource(name = "userservice_node04") private UserService userService04; //userid大於6000000的使用者的服務節點 private UserService getService(int userid) { if (userid <= 200_0000) return userService01; if (userid <= 400_0000) return userService02; if (userid <= 600_0000) return userService03; return userService04; } @Override public UserInfo findUserInfo(int userid) { return this.getService(userid).findUserInfo(userid); } @Override public RetResult<UserInfo> login(LoginBean bean) { //手機號碼用long儲存,0表示無手機號碼 int userid = mobUserService.findUserid(bean.getMobile()); if (userid < 1) return new RetResult<>(10001, "not found mobile " + bean.getMobile()); return this.getService(userid).login(bean); } @Override public void register(UserInfo user) { regUserService.register(user); //會生成userid this.getService(user.getUserid()).putUserInfo(user); } @Override public UserInfo updateUsername(int userid, String username) { return this.getService(userid).updateUsername(userid, username); } }
從程式碼看出,UserServiceGateWay繼承了UserService, 確保了UserService對外的服務介面不變,上面程式碼是使用者量在600-800萬之間的寫法,通過簡單的使用者ID分段,根據不同使用者ID調不同的服務節點。
如上圖,閘道器下的UserService部署分三類: userservice_reg只用於註冊使用者;userservice_mob提供查詢手機號碼與使用者ID間的關係的服務;userservice_node按使用者段提供已有使用者的服務。且每個UserService的例項在UserServiceGateWay都是遠端模式。每種型別可以部署多個節點(為了結構圖簡單,上圖每個型別只部署一個節點)。UserServiceGateWay(192.168.50.110、192.168.50.111)的配置如下:
<application port="5050"> <resources> <group name="USER_SERVICE_REG"> <node addr="192.168.70.110" port="7070"/> </group> <group name="USER_SERVICE_MOB"> <node addr="192.168.70.150" port="7070"/> </group> <group name="USER_SERVICE_NODE01"> <node addr="192.168.70.201" port="7070"/> </group> <group name="USER_SERVICE_NODE02"> <node addr="192.168.70.202" port="7070"/> </group> <group name="USER_SERVICE_NODE03"> <node addr="192.168.70.203" port="7070"/> </group> <group name="USER_SERVICE_NODE04"> <node addr="192.168.70.204" port="7070"/> </group> <group name="USER_SERVICE"> <node addr="192.168.50.110" port="7070"/> <node addr="192.168.50.111" port="7070"/> </group> </resources> <!-- SNCP 監聽 Server --> <server protocol="SNCP" port="7070"> <services autoload="true"> <!-- 配置UserService閘道器 --> <service name="" value="org.redkale.demo.UserServiceGateWay" groups="USER_SERVICE"/> <!-- 配置UserService分段節點 --> <service name="userservice_reg" value="org.redkale.demo.UserService" groups="USER_SERVICE_REG"/> <service name="userservice_mob" value="org.redkale.demo.UserService" groups="USER_SERVICE_MOB"/> <service name="userservice_node01" value="org.redkale.demo.UserService" groups="USER_SERVICE_NODE01"/> <service name="userservice_node02" value="org.redkale.demo.UserService" groups="USER_SERVICE_NODE02"/> <service name="userservice_node03" value="org.redkale.demo.UserService" groups="USER_SERVICE_NODE03"/> <service name="userservice_node04" value="org.redkale.demo.UserService" groups="USER_SERVICE_NODE03"/> </services> </server> </application>
由以上幾種部署方式的範例可以看出,Redkale提供了非常強大的架構,集中式到微服務架構不需要增加修改一行程式碼即可隨意切換,即使閘道器式部署也只是新增很少的程式碼就可切換,且不影響其他服務。真正可以做到敏捷開發,複雜的系統都可如小系統般快速地開發出來。
為了降低接入層與業務層程式碼的耦合, 可以將Service分介面與實現兩個類,接入層只載入介面包、業務層使用實現包。
appplication.xml 配置說明
<?xml version="1.0" encoding="UTF-8"?> <!-- 檔案說明: ${APP_HOME} 指當前程式的根目錄APP_HOME required: 被宣告required的屬性值不能為空 --> <!-- address: 本地的IP地址, 預設值為預設網路卡的ip,當不使用預設值需要指定值,如127.0.0.1 port: required 程式的管理Server的埠,用於關閉或者與監管系統進行資料互動 host: 程式的管理Server的地址; 預設為127.0.0.1。 lib: 加上額外的lib路徑,多個路徑用分號;隔開; 預設為空。 例如: ${APP_HOME}/lib/a.jar;${APP_HOME}/lib2/b.jar; --> <application port="6560" lib=""> <!-- 所有服務所需的資源 --> <resources> <!-- transport節點只能有一個,用於配置所有Transport的池引數,沒配置該節點將自動建立一個。 threads: 執行緒總數, 預設: <group>節點數*CPU核數*8 bufferCapacity: ByteBuffer的初始化大小, 預設: 8K; bufferPoolSize: ByteBuffer池的大小,預設: <group>節點數*CPU核數*8 --> <transport capacity="8192" bufferPoolSize="32" threads="32"/> <!-- 一個組包含多個NODE, 同一Service服務可以由多個程式提供,這些程式稱為一個GROUP,且同一GROUP內的程式必須在同一機房或區域網內 一個group節點對應一個 Transport 物件。 name: 服務組ID,長度不能超過11個位元組. 預設為空字串。 注意: name不能包含$符號。 protocol:值只能是UDP TCP, 預設TCP 注意: 一個node只能所屬一個group。只要存在protocol=SNCP的Server節點資訊, 就必須有group節點資訊。 --> <group name="" protocol="TCP"> <!-- 需要將本地node的addr與port列在此處。 同一個<node>節點值只能存在一個<group>節點內,即同一個addr+port只能屬於一個group。 addr: required IP地址 port: required 埠 clients: 連線池數, 預設: CPU核數*4 buffers: ByteBuffer物件池的大小, 預設: CPU核數*8 --> <node addr="127.0.0.1" port="7070"/> </group> <!-- 全域性的引數配置, 可以通過@Resource(name="property.xxxxxx") 進行注入, 被註解的欄位型別只能是String、primitive class 如果name是system.property.開頭的值將會在程式啟動時進行System.setProperty("yyyy", "YYYYYY")操作。 如果name是mimetype.property.開頭的值將會在程式啟動時進行MimeType.add("yyyy", "YYYYYY")操作。 load: 載入檔案,多個用;隔開。 預設置入的system.property.的有: System.setProperty("convert.json.tiny", "true"); System.setProperty("convert.bson.tiny", "true"); System.setProperty("convert.json.pool.size", "128"); System.setProperty("convert.bson.pool.size", "128"); System.setProperty("convert.json.writer.buffer.defsize", "4096"); System.setProperty("convert.bson.writer.buffer.defsize", "4096"); --> <properties load="config.properties"> <property name="system.property.yyyy" value="YYYYYY"/> <property name="xxxxxx" value="XXXXXXXX"/> <property name="xxxxxx" value="XXXXXXXX"/> <property name="xxxxxx" value="XXXXXXXX"/> </properties> </resources> <!-- protocol: required server所啟動的協議,有HTTP、SNCP, 目前只支援HTTP、SNCP。SNCP使用TCP實現; host: 服務所佔address , 預設: 0.0.0.0 port: required 服務所佔埠 root: 如果是web型別服務,則包含頁面 預設:{APP_HOME}/root lib: server額外的class目錄, 預設為空 charset: 文字編碼, 預設: UTF-8 backlog: 預設10K threads: 執行緒總數, 預設: CPU核數*16 maxbody: request.body最大值, 預設: 64K bufferCapacity: ByteBuffer的初始化大小, 預設: 8K; 如果是HTTP協議則預設: 16K + 8B (相容HTTP 2.0) bufferPoolSize: ByteBuffer池的大小,預設: CPU核數*512 responsePoolSize: Response池的大小,預設: CPU核數*256 readTimeoutSecond: 讀操作超時秒數, 預設0, 表示永久不超時 writeTimeoutSecond: 寫操作超時秒數, 預設0, 表示永久不超時 --> <server protocol="HTTP" host="127.0.0.1" port="6060" root="root" lib=""> <!-- 載入所有的Service服務; 在同一個程式中同一個name同一型別的Service將共用同一個例項 autoload="true" 預設值. 自動載入以下目錄(如果存在的話)下所有的Service類: server.lib; server.lib/*; server.classes; autoload="false" 需要顯著的指定Service類 includes: 當autoload="true", 拉取類名與includes中的正規表示式匹配的類, 多個正規表示式用分號;隔開 excludes: 當autoload="true", 排除類名與excludes中的正規表示式匹配的類, 多個正規表示式用分號;隔開 groups: 所屬組的節點,多個節點值用;隔開,如果配置檔案中存在多個SNCP協議的Server節點,需要顯式指定group屬性. 當 protocol == SNCP 時 group表示當前Server與哪些節點組關聯。 當 protocol != SNCP 時 group只能是空或者一個group的節點值,不能為多個節點值。 --> <services autoload="true" includes="" excludes=""> <!-- 顯著載入指定的Service的介面類 --> <service value="com.xxx.XXX1Service"/> <!-- name: 顯式指定name,覆蓋預設的空字串值。 注意: name不能包含$符號。 groups: 顯式指定groups,覆蓋<services>節點的groups預設值。 --> <service value="com.xxx.XXX2Service" name="" groups="xxx;yyy"/> <!-- 給Service增加配置屬性 --> <service value="com.xxx.XXX1Service"> <property name="xxxxxx" value="XXXXXXXX"/> <property name="xxxxxx" value="XXXXXXXX"/> </service> </services> <!-- 當Server為HTTP協議時, request節點才有效。 remoteaddr 節點: 替換請求方節點的IP地址, 通常請求方是由nginx等web靜態伺服器轉發過的則需要配置該節點。 且value值只能是以request.headers.開頭,表示從request.headers中獲取對應的header值。 例如下面例子獲取request.getRemoteAddr()值,如果header存在X-RemoteAddress值則返回X-RemoteAddress值,不存在返回getRemoteAddress()。 --> <request> <remoteaddr value="request.headers.X-RemoteAddress"/> </request> <!-- 當Server為HTTP協議時, response節點才有效。 defcookie 節點: 當response裡輸出的cookie沒有指定domain 和path時,使用該節點的預設值。 如果addheader、setheader 的value值以request.headers.開頭則表示從request.headers中獲取對應的header值 例如下面例子是在Response輸出header時新增兩個header(一個addHeader, 一個setHeader)。 --> <response> <defcookie domain="" path=""/> <addheader name="Access-Control-Allow-Origin" value="request.headers.Origin" /> <setheader name="Access-Control-Allow-Credentials" value="true"/> </response> <!-- 載入所有的Servlet服務; path: servlet的ContextPath字首 預設為空 autoload="true" 預設值. 自動載入以下目錄(如果存在的話)下所有的Servlet類: ${APP_HOME}/lib; ${APP_HOME}/root/lib/*; ${APP_HOME}/root/classes; autoload="false" 需要顯著的指定Service類 includes: 當autoload="true", 拉取類名與includes中的正規表示式匹配的類, 多個正規表示式用分號;隔開 excludes: 當autoload="true", 排除類名與excludes中的正規表示式匹配的類, 多個正規表示式用分號;隔開 --> <servlets path="/pipes" autoload="true" includes="" excludes=""> <!-- 當Server為HTTP協議時,ResourceServlet才有效. 預設存在一個有預設屬性的resource-servlet節點 webroot: web資源的根目錄, 預設取server節點中的root值 --> <resource-servlet webroot="root"> <!-- 資源快取的配置, 預設存在一個含預設屬性的caches節點 limit: 資源快取最大容量, 預設: 128M, 為0表示不快取, 單位可以是B、K、M、G,不區分大小寫 lengthmax: 可快取的檔案大小上限, 預設: 1M(超過1M的檔案不會被快取) --> <caches limit="128M" lengthmax="1M" /> <!-- 支援類似nginx中的rewrite, 目前只支援靜態資源對靜態資源的跳轉。 type: 匹配的型別, 目前只支援location(匹配requestURI), 預設: location match: 匹配的正規表示式 forward: 需跳轉後的資源連結 例如下面例子是將/xxx-yyy.html的頁面全部跳轉到/xxx.html --> <rewrite type="location" match="^/([^-]+)-[^-/.]+/.html(.*)" forward="/$1.html"/> </resource-servlet> <!-- 顯著載入指定的Servlet --> <servlet value="com.xxx.XXX1Servlet" /> <servlet value="com.xxx.XXX2Servlet" /> <servlet value="com.xxx.XXX3Servlet" > <property name="xxxxxx" value="XXXXXXXX"/> <property name="yyyyyy" value="YYYYYYYY"/> </servlet> </servlets> </server> <server protocol="SNCP" host="127.0.0.1" port="7070" root="root" lib=""> <!-- 引數完全同上 --> <services autoload="true" includes="" excludes="" /> </server> </application>
相關文章
- dotnet core微服務框架Jimu介紹微服務框架
- lms微服務框架主機介紹微服務框架
- silky微服務框架的服務治理介紹微服務框架
- silky微服務框架服務註冊中心介紹微服務框架
- 曉黑板 go-zero 微服務框架介紹Go微服務框架
- java語言的入門介紹Java
- 最熱門的13個Java微服務框架Java微服務框架
- 【微服務目錄】.NET Core 微服務介紹微服務
- rocketmq事務訊息入門介紹MQ
- 【Nacos】微服務配置中心介紹微服務
- Java多執行緒傻瓜入門介紹Java執行緒
- Java爬蟲入門(一)——專案介紹Java爬蟲
- Mybatis 入門介紹MyBatis
- Rocketmq 入門介紹MQ
- libevent入門介紹
- Django 入門介紹Django
- linux介紹(入門)Linux
- Nginx 入門介紹Nginx
- rollup入門介紹
- 微服務 Spring cloud 各元件介紹微服務SpringCloud元件
- SpringCloud包含的微服務介紹--EurekaSpringGCCloud微服務
- 更好的 java 重試框架 sisyphus 入門簡介Java框架
- Spring Shell入門介紹Spring
- Java微服務下的分散式事務介紹及其解決方案2Java微服務分散式
- 微軟微服務構建框架Dapr基礎入門教程微軟微服務框架
- 小白入門微服務(0) - 什麼是微服務微服務
- (18)go-micro微服務ELK介紹Go微服務
- go微服務框架go-micro深度學習(二) 入門例子Go微服務框架深度學習
- 關於微服務,這些你都瞭解嗎-微服務介紹微服務
- 『python入門:』 python的介紹Python
- WebSocket協議入門介紹Web協議
- 整合學習入門介紹
- Java常用的5大框架介紹!Java框架
- go微服務框架go-micro深度學習(一) 整體架構介紹Go微服務框架深度學習架構
- 關於微服務入門篇微服務
- 微服務入門權威指南微服務
- 入門全棧Java程式設計師——課程介紹全棧Java程式設計師
- 5款Java微服務開源框架Java微服務框架
- 前端微服務化解決方案1-介紹前端微服務