专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

基于Mina的配置中心(二)

基于Mina的配置中心(二)

首先来看看配置中心数据库的设计。

表结构:

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代码生成器,生成一下代码。
生成后的效果:
89_1.png

首先要把 Message 这个类移动到Base模块中,因为客户端发送消息,也需要使用这个类。
最后效果:
89_2.png

MinaServerProperty

因为使用了SpringBoot,接下来我们使用配置类的方式来整合Mina

因为有很多配置属性,我不想用户全都写到application.properties中,而且如果用户在application.properties中写配置属性的时候,能出现提示就更好了。

所以首先要创建一个类: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.json

注意:要使用Maven的编译命令,或者打包命令才会在target或者jar包中创建/META-INF/spring-configuration-metadata.json这个文件,还有这里不要用lombok,老老实实的写gettersetter,不然是没有提示的。

{
  "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里的提示就是这些东西。

89_3.png

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(); } } 

当然配置类不会这么简单,我们现在能配的东西不多。现在有很多东西没有写,等写好之后再把配置补上。

自定义协议

在客户端与服务端的通讯中,在底层其实是二进制数据,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的配置类,敬请期待。

对啦,欢迎大家关注我的公众号,共同学习,一起进步。加油

89_4.png

本文使用 tech.souyunku.com 排版

文章永久链接:https://tech.souyunku.com/33748

未经允许不得转载:搜云库技术团队 » 基于Mina的配置中心(二)

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们