基於Mina的配置中心(二)

基於Mina的配置中心(二)

首先來看看配置中心數據庫的設計。java

表結構:

CREATE TABLE `message` (
 `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '消息體id',  `project_name` varchar(200) DEFAULT NULL COMMENT '項目名稱',  `env_value` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'local' COMMENT '環境,dev平常,gray灰度,online線上,local本地',  `property_value` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT 'preperties 中的value',  `config_value` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '配置中心配置的須要注入的值',  `remote_address` varchar(100) DEFAULT NULL COMMENT '客戶端 session key',  `creator` bigint(20) DEFAULT NULL COMMENT '建立人',  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立時間',  `modifier` bigint(20) DEFAULT NULL COMMENT '修改人',  `gmt_modify` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改時間',  `config_version` int(11) NOT NULL DEFAULT '1' COMMENT '樂觀鎖,版本',  `is_deleted` int(1) NOT NULL DEFAULT '0' COMMENT '邏輯刪除,0未刪除,1已刪除',  PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='消息體'; 複製代碼
  1. project_name:項目名稱,不一樣的項目可能有名字相同的配置,因此用來區分。
  2. env_value:當前環境,我以爲既然是配置中心,就應該接管全部配置,不須要用戶再寫三個 application.properties文件來區分。這個極大的簡化了多環境項目。
  3. property_value:這個東西其實就是 application.properties裏面配置的值,舉個栗子🌰,好比你在 application.properties寫了一個這個配置 mina.config.name=data1,那麼 data1就是 property_value
  4. config_value:就是你真正要配置的值,就是用來替換 data1的值。
  5. remote_address:這個是客戶端的地址,主要是當服務端更改了配置項,來主動向客戶端推送的。是的,這個配置中心既有推的模式,也有拉的模式。

而後用咱們很是熟悉的Mybatis-Plus代碼生成器,生成一下代碼。
生成後的效果:
git

首先要把 Message 這個類移動到Base模塊中,由於客戶端發送消息,也須要使用這個類。
最後效果:
github

MinaServerProperty

由於使用了SpringBoot,接下來咱們使用配置類的方式來整合Minaweb

由於有不少配置屬性,我不想用戶全都寫到application.properties中,並且若是用戶在application.properties中寫配置屬性的時候,能出現提示就更好了。spring

因此首先要建立一個類:MinaServerProperty數據庫

package com.lww.mina.config;
 import org.springframework.boot.context.properties.ConfigurationProperties;  /**  * @author lww  * @date 2020-07-05 16:13  */ @ConfigurationProperties(prefix = "mina.server") public class MinaServerProperty {   /**  * 服務器監聽端口,默認 9123  */  private Integer port = 9123;   /**  * 服務器ip地址,默認 127.0.0.1  */  private String address = "127.0.0.1";   /**  * 緩衝區大小,默認2048  */  private Integer readBufferSize = 2048;   /**  * 空閒時間,單位秒 默認 5 秒沒操做就進入空閒狀態  */  private Integer idelTimeOut = 5;   /**  * 初始化線程池大小,默認10  */  private Integer corePoolSize = 10;   /**  * 最大線程數,默認20  */  private Integer maximumPoolSize = 20;   /**  * 初始化用戶名  */  private String username;   /**  * 初始化密碼  */  private String password;   public String getUsername() {  return username;  }   public void setUsername(String username) {  this.username = username;  }   public String getPassword() {  return password;  }   public void setPassword(String password) {  this.password = password;  }   public Integer getPort() {  return port;  }   public void setPort(Integer port) {  this.port = port;  }   public String getAddress() {  return address;  }   public void setAddress(String address) {  this.address = address;  }   public Integer getReadBufferSize() {  return readBufferSize;  }   public void setReadBufferSize(Integer readBufferSize) {  this.readBufferSize = readBufferSize;  }   public Integer getIdelTimeOut() {  return idelTimeOut;  }   public void setIdelTimeOut(Integer idelTimeOut) {  this.idelTimeOut = idelTimeOut;  }   public Integer getCorePoolSize() {  return corePoolSize;  }   public void setCorePoolSize(Integer corePoolSize) {  this.corePoolSize = corePoolSize;  }   public Integer getMaximumPoolSize() {  return maximumPoolSize;  }   public void setMaximumPoolSize(Integer maximumPoolSize) {  this.maximumPoolSize = maximumPoolSize;  } } 複製代碼

@ConfigurationProperties

這個註解配合@EnableConfigurationProperties這個一塊兒使用,能夠在項目裏生成以下的文件:
/META-INF/spring-configuration-metadata.jsonapache

注意:要使用Maven的編譯命令,或者打包命令纔會在target或者jar包中建立/META-INF/spring-configuration-metadata.json這個文件,還有這裏不要用lombok,老老實實的寫gettersetter,否則是沒有提示的。json

{
 "groups": [  {  "name": "mina.server",  "type": "com.lww.mina.config.MinaServerProperty",  "sourceType": "com.lww.mina.config.MinaServerProperty"  }  ],  "properties": [  {  "name": "mina.server.address",  "type": "java.lang.String",  "description": "服務器ip地址,默認 127.0.0.1",  "sourceType": "com.lww.mina.config.MinaServerProperty",  "defaultValue": "127.0.0.1"  },  {  "name": "mina.server.core-pool-size",  "type": "java.lang.Integer",  "description": "初始化線程池大小,默認10",  "sourceType": "com.lww.mina.config.MinaServerProperty",  "defaultValue": 10  },  {  "name": "mina.server.idel-time-out",  "type": "java.lang.Integer",  "description": "空閒時間,單位秒 默認 5 秒沒操做就進入空閒狀態",  "sourceType": "com.lww.mina.config.MinaServerProperty",  "defaultValue": 5  },  {  "name": "mina.server.maximum-pool-size",  "type": "java.lang.Integer",  "description": "最大線程數,默認20",  "sourceType": "com.lww.mina.config.MinaServerProperty",  "defaultValue": 20  },  {  "name": "mina.server.password",  "type": "java.lang.String",  "description": "初始化密碼",  "sourceType": "com.lww.mina.config.MinaServerProperty"  },  {  "name": "mina.server.port",  "type": "java.lang.Integer",  "description": "服務器監聽端口,默認 9123",  "sourceType": "com.lww.mina.config.MinaServerProperty",  "defaultValue": 9123  },  {  "name": "mina.server.read-buffer-size",  "type": "java.lang.Integer",  "description": "緩衝區大小,默認2048",  "sourceType": "com.lww.mina.config.MinaServerProperty",  "defaultValue": 2048  },  {  "name": "mina.server.username",  "type": "java.lang.String",  "description": "初始化用戶名",  "sourceType": "com.lww.mina.config.MinaServerProperty"  }  ],  "hints": [] } 複製代碼

當用戶在application.properties裏配置屬性時,會有提示:服務器

  1. application.properties里名稱是 mina.server前綴加上屬性的名稱,若是是駝峯命名的,則用 -分隔開,如 mina.server.read-buffer-size
  2. 屬性的默認值就是,咱們聲明時建立的值。
  3. 描述就是 javadoc,在 application.properties裏的提示就是這些東西。

MinaServerConfig

package com.lww.mina.config;
 import javax.annotation.Resource; import org.apache.mina.filter.executor.ExecutorFilter; import org.apache.mina.filter.logging.LoggingFilter; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;  /**  * @author lww  * @date 2020-07-05 16:13  */ @Configuration @EnableConfigurationProperties(MinaServerProperty.class) public class MinaServerConfig {   @Resource  private MinaServerProperty config;   /**  * 配置mina的多線程過濾器  */  @Bean  public ExecutorFilter executorFilter() {  //設置初始化線程數,最大線程數  return new ExecutorFilter(config.getCorePoolSize(), config.getMaximumPoolSize());  }   /**  * 配置mina的日誌過濾器  */  @Bean  public LoggingFilter loggingFilter() {  return new LoggingFilter();  } } 複製代碼

固然配置類不會這麼簡單,咱們如今能配的東西很少。如今有不少東西沒有寫,等寫好以後再把配置補上。session

自定義協議

在客戶端與服務端的通信中,在底層實際上是二進制數據,Mina提供了TextLineCodecFactory,根據換行符的編碼器,雖然通常場景夠用,可是仍是不知足咱們的需求,爲了更好的解決半包和粘包,咱們須要自定義協議。

  • 半包:客戶端發送的數據,在服務器端讀取到的實際上是二進制數據,服務器不知道讀取多少是完整的。因此讀取到的多是不完整的數據包。
  • 粘包:同上,客戶端一次發送了好幾個數據包,服務器一次讀取了兩個或多個包的數據。

解決半包粘包的方式有不少種,咱們採用添加消息頭的方式,消息頭中包含消息的長度,還有類型。

package com.lww.mina.protocol;
 import lombok.Data; import org.apache.commons.lang3.StringUtils;  /**  * @author lww  * @date 2020-07-05 17:47  */ @Data public class MessagePack {   /**  * 數據總長度  */  private int len;   /**  * 模塊代碼  */  private int module;   /**  * 包體 Message json格式  */  private String body;   /**  * 包頭長度  */  public static final int PACK_HEAD_LEN = 8;   /**  * 最大長度  */  public static final int MAX_LEN = 9999;   public MessagePack(int module, String body) {  this.module = module;  this.body = body;  // 總長度  this.len = PACK_HEAD_LEN + (StringUtils.isBlank(body) ? 0 : body.getBytes().length);  } } 複製代碼

一個 int 類型佔4個字節,因此長度加上模塊就佔8個byte,包頭長度就是8。而Message則轉爲Json存儲在body中。

總結

第二章先寫到這裏,咱們自定義了消息協議和Mina的配置類,用戶在application.properties中配置時,會有提示。

項目源碼

第三章會建立自定義的編碼解碼器,還有心跳檢測,在第三章咱們基本能夠完成Mina的配置類,敬請期待。

對啦,歡迎你們關注個人公衆號,共同窗習,一塊兒進步。加油🤣

本文使用 mdnice 排版

相關文章
相關標籤/搜索