首页 文章 精选 留言 我的

精选列表

搜索[服务端],共10002篇文章
优秀的个人博客,低调大师

Mycat 作为代理服务端的小知识点

一 . 前言 Mycat 以一个 Server 的形式对外暴露服务 , 其主要配置类为 Server.xml , 这一篇主要针对一些小细节进行学习 , 主要包括 : Server.xml 的加载方式 Server 中的配置和作用 在连接请求中 Server 的流转 二 . Server.xml 的配置 2.1 Server.xml 配置详情 Server.xml 主要在 XMLSchemaLoader 中进行加载 , Server.xml 文件中主要分为以下几个部分 User 管理 <user name="user"> <property name="password">user</property> // 用户可访问的 schemas , 中间可通过逗号分隔 <property name="schemas">db001</property> <property name="readOnly">true</property> <property name="defaultSchema">db001</property> </user> 复制代码 配置管理 配置文件直接从源码中拉下来的 , 也是非常清楚的 , 有兴趣的可以拉源码看一下 <system> <property name="nonePasswordLogin">0</property> <!-- 0为需要密码登陆、1为不需要密码登陆 ,默认为0,设置为1则需要指定默认账户--> <property name="ignoreUnknownCommand">0</property><!-- 0遇上没有实现的报文(Unknown command:),就会报错、1为忽略该报文,返回ok报文。 在某些mysql客户端存在客户端已经登录的时候还会继续发送登录报文,mycat会报错,该设置可以绕过这个错误--> <property name="useHandshakeV10">1</property> <property name="removeGraveAccent">1</property> <property name="useSqlStat">0</property> <!-- 1为开启实时统计、0为关闭 --> <property name="useGlobleTableCheck">0</property> <!-- 1为开启全加班一致性检测、0为关闭 --> <property name="sqlExecuteTimeout">300</property> <!-- SQL 执行超时 单位:秒--> <property name="sequenceHandlerType">1</property> <!--<property name="sequnceHandlerPattern">(?:(\s*next\s+value\s+for\s*MYCATSEQ_(\w+))(,|)|\s)*)+</property> INSERT INTO `travelrecord` (`id`,user_id) VALUES ('next value for MYCATSEQ_GLOBAL',"xxx"); --> <!--必须带有MYCATSEQ_或者 mycatseq_进入序列匹配流程 注意MYCATSEQ_有空格的情况--> <property name="sequnceHandlerPattern">(?:(\s*next\s+value\s+for\s*MYCATSEQ_(\w+))(,|)|\s)*)+</property> <property name="subqueryRelationshipCheck">false</property> <!-- 子查询中存在关联查询的情况下,检查关联字段中是否有分片字段 .默认 false --> <property name="sequenceHanlderClass">io.mycat.route.sequence.handler.HttpIncrSequenceHandler</property> <!-- <property name="useCompression">1</property>--> <!--1为开启mysql压缩协议--> <!-- <property name="fakeMySQLVersion">5.6.20</property>--> <!--设置模拟的MySQL版本号--> <!-- <property name="processorBufferChunk">40960</property> --> <!-- <property name="processors">1</property> <property name="processorExecutor">32</property> --> <!--默认为type 0: DirectByteBufferPool | type 1 ByteBufferArena | type 2 NettyBufferPool --> <property name="processorBufferPoolType">0</property> <!--默认是65535 64K 用于sql解析时最大文本长度 --> <!--<property name="maxStringLiteralLength">65535</property>--> <!--<property name="sequenceHandlerType">0</property>--> <!--<property name="backSocketNoDelay">1</property>--> <!--<property name="frontSocketNoDelay">1</property>--> <!--<property name="processorExecutor">16</property>--> <!-- <property name="serverPort">8066</property> <property name="managerPort">9066</property> <property name="idleTimeout">300000</property> <property name="bindIp">0.0.0.0</property> <property name="dataNodeIdleCheckPeriod">300000</property> 5 * 60 * 1000L; //连接空闲检查 <property name="frontWriteQueueSize">4096</property> <property name="processors">32</property> --> <!--分布式事务开关,0为不过滤分布式事务,1为过滤分布式事务(如果分布式事务内只涉及全局表,则不过滤),2为不过滤分布式事务,但是记录分布式事务日志--> <property name="handleDistributedTransactions">0</property> <!-- off heap for merge/order/group/limit 1开启 0关闭 --> <property name="useOffHeapForMerge">0</property> <!-- 单位为m --> <property name="memoryPageSize">64k</property> <!-- 单位为k --> <property name="spillsFileBufferSize">1k</property> <property name="useStreamOutput">0</property> <!-- 单位为m --> <property name="systemReserveMemorySize">384m</property> <!--是否采用zookeeper协调切换 --> <property name="useZKSwitch">false</property> <!-- XA Recovery Log日志路径 --> <!--<property name="XARecoveryLogBaseDir">./</property>--> <!-- XA Recovery Log日志名称 --> <!--<property name="XARecoveryLogBaseName">tmlog</property>--> <!--如果为 true的话 严格遵守隔离级别,不会在仅仅只有select语句的时候在事务中切换连接--> <property name="strictTxIsolation">false</property> <!--如果为0的话,涉及多个DataNode的catlet任务不会跨线程执行--> <property name="parallExecute">0</property> </system> 复制代码 防火墙配置 <firewall> <whitehost> <host host="1*7.0.0.*" user="root"/> </whitehost> <blacklist check="false"> </blacklist> </firewall> 复制代码 2.2 Server.xml 细节解析 Server.xml 内部有几大标签 , 主要为 user , system 和 firewall // user : 用于定义登录的 Mycat 的用户和权限 , 最终映射为 UserConfig 除了上面展示的 , 其还提供了如下特殊属性 : - benchmark : 负载均衡策略 , 0 为不限制连接数 - privilegesConfig : 表级别的增删改查设置 // System 标签 : 系统配置标签 , 最终映射为 SystemConfig 对象 , 除了上面展示 , 其主要还有如下配置 - charset : 配置字符集 , 务必和数据库一致 - defaultSqlParser : 指定默认的解析器 - processors : 系统可用线程数 (默认Runtime.getRuntime().availableProcessors()) - processorBufferChunk : 每次分配 Socket Direct Buffer , 此处会影响获取字节的大小 - processorBufferPool : BufferPool 的计算比例 - processorBufferLocalPercent : ThreadLocalPool 分配 Pool 的比例大小 , 默认 100 - sequnceHandlerType : Mycat 全局序列的类型 - private long processorCheckPeriod : 清理 NIOProcessor 空闲间隔 - private long dataNodeIdleCheckPeriod : 后端连接清理间隔 - private long dataNodeHeartbeatPeriod : 对后端读写发起心跳间隔 - private int useOffHeapForMerge : 是否启用Off Heap for Merge 1-启用,0-不启用 - private int usingAIO = 0 : 是否开启 AIO - private int packetHeaderSize = 4 : MySQL 协议报文长度 - private int maxPacketSize = 16 * 1024 * 1024 : 可用携带的数据最大大小 - private String memoryPageSize : 页大小,对应MemoryBlock的大小,单位为M - private long idleTimeout : 连接的空闲时间的超时长度 - private int txIsolation : 初始阿虎啊前端连接事务的隔离级别 , 对应 1-4 复制代码 三 . Server.xml 的加载方式 Server.xml 是在 ConfigInitializer 进行的加载 ,最终加载位 Map , 进而传递到 MycatServer 中 //读取server.xml XMLConfigLoader configLoader = new XMLConfigLoader(schemaLoader); // 对应 schema.xml -> dataHost private final Map<String, DataHostConfig> dataHosts; // 对应 schema.xml -> dataNode private final Map<String, DataNodeConfig> dataNodes; // 对应 schema.xml规则 private final Map<String, SchemaConfig> schemas; // 对应 System 全局配置 private final SystemConfig system; // 对应 User 特定 Config private final Map<String, UserConfig> users; // 对应防火墙配置 private final FirewallConfig firewall; // 对应分片配置 private final ClusterConfig cluster; 复制代码 四. 配置的使用场景 4.1 节点一 : Server 连接 当通过工具连接时 , 会首先进行 init DB 操作 ,此时会获取 DB 信息获取连接 C- FrontendConnection # initDB public void initDB(byte[] data) { // S1 : 通过 MySQLMessage 对象获取 data 数据 // init 请求参数 : \u0006\u0000\u0000\u0000\u0002db001 -> db001 // S2 : 检查 DB 有效性 db == null || !privileges.schemaExists(db) // S3 : 校验当前用户是否存在 privileges.userExists(user, host) // S4 : 获取 Schemas Set<String> schemas = privileges.getUserSchemas(user); if (schemas == null || schemas.size() == 0 || schemas.contains(db)) { this.schema = db; // OkPacket.OK : 07 00 00 02 00 00 00 02 00 00 00 write(writeToBuffer(OkPacket.OK, allocate())); } else { String s = "Access denied for user '" + user + "' to database '" + db + "'"; writeErrMessage(ErrorCode.ER_DBACCESS_DENIED_ERROR, s); } } 复制代码 补充一 : OkPacket.OK : 700010002000 是什么意思 ? MySQL OK 包返回结构 一个 OK 数据包从服务器发送到客户机,表示命令成功完成 , 在 MySQL 5.7.5中,OK packes 也被用来表示 EOF,而 EOF 数据包已被弃用。 在 packes 中会包含如下数据 : 包头 , 受影响的行 , 最后一次插入的 ID , Status Flag 的状态 等等 , 后面有机会 , 找个案例详细的看看 补充二 : privileges 对象 可以看到 , 上述代码中频繁出现 FrontendPrivileges , 该对象的作用是什么 ? FrontendPrivileges 是一个权限提供者接口 , 他提供了几种常见的方法例如 : schemaExists : 检查schema是否存在 userExists : 检查用户是否存在,并且可以使用host实行隔离策略 checkFirewallWhiteHostPolicy : 检查防火墙策略 ....等等 可以理解为 , FrontendPrivileges 就是对 server.xml 数据的逻辑处理 , 其主要实现类为 MycatPrivileges . 其内部逻辑也比较简单 , 主要是对 MycatConfig 的处理 , 例如 : // 检查schema是否存在 public boolean schemaExists(String schema) { MycatConfig conf = MycatServer.getInstance().getConfig(); return conf.getSchemas().containsKey(schema); } // 非常好的实践 , 直接返回实例对象 public static final MycatServer getInstance() { // private static final MycatServer INSTANCE = new MycatServer(); // 而该静态对象在构造器中就已经完成了相关config 的初始化 return INSTANCE; } 复制代码 可以看到 , 内部配置基本上包含了常用的 Config 4.2 节点二 : 查询时配置 配置会在各个环节生效 , 下面来看一下几个常见的场景 : 超时时间的常见使用场景 // 定时检查任务 , 处理回收资源 : C- MycatServer # processorCheck : C- NIOProcessor # backendCheck private void backendCheck() { // S1 : 获取超时时间 long sqlTimeout = MycatServer.getInstance().getConfig().getSystem().getSqlExecuteTimeout() * 1000L; // S2 :对所有的连接进行迭代 Iterator<Entry<Long, BackendConnection>> it = backends.entrySet().iterator(); // S3 : 首先删除空连接 , 然后SQL执行超时的连接关闭 if (c.isBorrowed() && c.getLastTime() < TimeUtil.currentTimeMillis() - sqlTimeout) { //..... } } // PS : 还有多个使用场景 , 这里就不一一看了 复制代码 从这个案例上面 , 就可以明显的看到 , 配置的主要使用还是靠从 MycatServer 中获取配置进行处理 , 而 MycatServer 就是整个流程的核心对象之一 , 下一篇来详细看看 五 . Server 的数据接收 在 Mycat NIO 处理请求的时候 , 可以看到一个 byte[] 持续流转其中 , 那么这个 Byte 中包含了那些数据呢 ? // 在 FrontendConnection # initDB 中 , 我们可以看到 data 的具体数据 , 以一个连接为例 : - \u0006\u0000\u0000\u0000\u0002 : 前缀 , 判断具体的类型 - db001 : 具体的 Server Schema // 补充 : 通过前四位类型判断 C- FrontendCommandHandler # handle public void handle(byte[] data) { if (source.getLoadDataInfileHandler() != null && source.getLoadDataInfileHandler().isStartLoadData()) { MySQLMessage mm = new MySQLMessage(data); int packetLength = mm.readUB3(); if (packetLength + 4 == data.length) { source.loadDataInfileData(data); } return; } // 可以看到 switch (data[4]) { // public static final byte COM_INIT_DB = 2; case MySQLPacket.COM_INIT_DB: commands.doInitDB(); source.initDB(data); break; // public static final byte COM_QUERY = 3; case MySQLPacket.COM_QUERY: commands.doQuery(); source.query(data); break; case MySQLPacket.COM_PING: commands.doPing(); source.ping(); break; case MySQLPacket.COM_QUIT: commands.doQuit(); source.close("quit cmd"); break; //..... 省略部分类型 default: commands.doOther(); MycatConfig config = MycatServer.getInstance().getConfig(); if (config.getSystem().getIgnoreUnknownCommand() == 1) { LOGGER.warn("Unknown command:{}", data[4]); source.ping(); } else { LOGGER.error("Unknown command:{}", new String(data)); source.writeErrMessage(ErrorCode.ER_UNKNOWN_COM_ERROR, "Unknown command"); } } } 复制代码 一般一个查询会分成2个部分 : 初始化连接 执行当前的操作 , 以 Query 为例 这里可以看到 , Byte[0] - Byte[4] 还是标志位 , 后面会传入具体的 SQL . 不论是 initDB 还是 Query , 都会进行一个关键步骤 : MySQLMessage mm = new MySQLMessage(data); // 解析标志位 mm.position(5); String db = mm.readString(); // 当标注位解析完成后 , 最终会调用对应的 Handler 完成后续的逻辑 - queryHandler.query(sql); 复制代码 总结 对入口进行了简单的学习 , 参考了文档 , 也做了一定的补充 , 后续可以慢慢的深入整个体系了 最后 如果你觉得此文对你有一丁点帮助,点个赞。或者可以加入我的开发交流群:1025263163相互学习,我们会有专业的技术答疑解惑 如果你觉得这篇文章对你有点用的话,麻烦请给我们的开源项目点点star:http://github.crmeb.net/u/defu不胜感激! PHP学习手册:https://doc.crmeb.com 技术交流论坛:https://q.crmeb.com

优秀的个人博客,低调大师

Logstash 7.13.3 发布,开源服务端数据处理流程

Logstash 是开源的服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到你最喜欢的“存储库”中。目前,Logstash7.13.3已正式发布,该版本更新内容如下: Plugins Cef Codec - 6.2.2 修复了启用 ECS 模式并解析CEF 字段fileHash时可能发生的无效字段引用。 添加了编号deviceCustom*和deviceCustom*Label字段的扩展映射,以便现在所有字段都包含数字 1 到 15。#89 Multiline Codec- 3.0.11 修复:避免在编解码器关闭时长线程休眠#67 Xml Filter - 4.1.2 [DOC] 更新文档以更正 parse_options 配置选项的名称#75 Beats Input- 6.1.5 更改了 jar 依赖项以反映较新的版本#425 修复:减少连接重置时的错误记录#424 更新说明:https://www.elastic.co/guide/en/logstash/7.13/logstash-7-13-3.html

优秀的个人博客,低调大师

Logstash 7.11.2 发布,开源服务端数据处理流程

Logstash 是开源的服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到你最喜欢的“存储库”中。目前,Logstash7.11.2已正式发布,该版本更新内容如下: Notable issues fixed 解决了一个可能导致自动重新加载的问题。开发团队将not terminated状态替换为两个更有描述性的状态:running和loading。此修复程序可以防止正在加载的管道被描述为running。#12444 Plugins Elasticsearch Filter - 3.9.3 [DOC] 更新链接以使用 shared attributes#144 [DOC] 修复了重组后的 Logstash-to-cloud 文档的链接#142 [DOC] 记录 secured clusters 所需的权限#140 Geoip Filter - 6.0.5 修复数据库下载任务。将项目升级到 Java 11#175 启用 MaxMind GeoIP2-Domain 数据库的使#162 Metrics Filter - 4.0.7 修复文档中的错字 Beats Input - 6.0.14 Feat:log + unwrap generic SSL context 异常#405 [DOC] 更新链接以使用 shared attributes Elasticsearch Input - 4.9.1 [DOC] 使用 shared attributes替换了 hard-coded links#143 [DOC] 向 docinfo_fields 示例添加了缺少的引号#145 Http Input - 3.3.7 Feat:改进的error handling/logging/unwraping#133 Syslog Input - 3.4.5 增加了对侦听 IPv6 地址的支持 Tcp Input - 6.0.7 修复:减少连接重置时的错误记录(to info level)#168 重构:只给 Socket classes打一次补丁(第一次输入时) 重构:使用适当的 log4j logger(在 Java 中,以避免在解包 LogStash::Logging::Logger 时出现意外) Kafka Integration - 10.7.1 修复:自 Logstash 5.0起弃用了 SHUTDOWN event的用法#71 Cloudwatch Output - 3.0.9 修复:自 Logstash 5.0起弃用了 SHUTDOWN event的用法#18 Elasticsearch Output - 10.8.4 修复了 retried request 会丢弃“update”参数的问题#800 避免在连接到 Elasticsearch 版本7.x时,避免隐性地将 deprecated type 设置为_doc#994 [DOC] 更新链接以使用 shared attributes#985 Lumberjack Output - 3.1.8 修复:自 Logstash 5.0 起弃用了 SHUTDOWN event的用法 #31 S3 Output - 4.3.3 [DOC] 更新链接以使用 shared attributes#230 更新说明:https://www.elastic.co/guide/en/logstash/7.11/logstash-7-11-2.html#logstash-7-11-2

优秀的个人博客,低调大师

Logstash 7.9.1 发布,开源服务端数据处理流程

Logstash 是开源的服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到你最喜欢的“存储库”中。目前,Logstash 7.9.1已正式发布,该版本更新内容如下: Notable issues fixed 修复 Monitoring和 Central Management 的 Docker 镜像配置中的问题。 Pipeline execution修复了 flushing和shutdown 一致的 Fingerprinting 将 JRuby 更新到 9.2.13.0 Plugins Avro Codec - 3.2.4 [DOC] 添加有关部分反序列化的说明#35 Fingerprint Filter - 3.2.2 修复了在 Hash/Map objects 上缺乏一致的 fingerprints 的问题 Kv Filter - 4.4.1 修复了包含反斜杠的field_split_pattern无法正确匹配的问题#87 ...... 完整更新内容查看:https://www.elastic.co/guide/en/logstash/7.9/logstash-7-9-1.html

优秀的个人博客,低调大师

Logstash 7.8.1 发布,开源服务端数据处理流程

Logstash 是开源的服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到你最喜欢的“存储库”中。目前,Logstash 7.8.1已正式发布,该版本更新内容如下: 性能改进和bug修复 修复了pipeline compilation期间的性能回归问题 修复了多个 pipeline shutdown和 reloadingedit 的问题 Beats/TCP /HTTPInput Plugins 的依赖性变化 Plugins Xml Filter - 4.1.1 修复:处理事件时引发的异常不再使 pipeline崩溃#73 Beats Input - 6.0.11 更新了 jackson databind 和 Netty 依赖关系。此外,此版本还删除了对tcnative和boringssl的依赖,改用 JVM 提供的密码器。如果未安装 JCE 无限强度管辖区策略,这可能导致可用的密码更少。(从 u161 开始的 JDK 版本都默认安装了这个策略。)#393 添加了错误处理以检测 ssl 证书或密钥文件是否无法读取#394 Elasticsearch Input - 4.6.2 添加了 scroll clearing 和更好的 scroll expiration处理方法#128 [DOC]删除了过时的兼容性声明#124 ...... 更多内容可查看发布说明:https://www.elastic.co/guide/en/logstash/7.8/logstash-7-8-1.html#_multiple_fixes_to_pipeline_shutdown_and_reloading 上传新附件

优秀的个人博客,低调大师

Logstash 7.8.0 发布,开源服务端数据处理流程

Logstash 是开源的服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到你最喜欢的“存储库”中。目前,Logstash 7.8.0已正式发布,该版本更新内容如下: 新功能和改进 Expanded JDK ecosystem 改进了测试脚本基础结构,以接受主机中存在的特定 Java 开发工具包(JDK)。更改包括将 JDK 主目录的路径导出到名为 BUILD_JAVA_HOME 的环境变量中,并由 shell 程序脚本使用它来启动测试和集成脚本。这项工作和其他 JDK14 修复程序为 Logstash 在不久的将来支持 AdoptOpenJDK 11 和 14 铺平了道路。#11786,#11839,#11935 Expanded JDK platform supportedit Logstash 可在许多不同的操作平台和 Java 开发工具包(JDK)的各种版本上运行,7.8.0 中扩展了此覆盖范围。Logstash 引入了对在 CentOS/RHEL 8.x 和 Ubuntu 20.04 上运行的支持。并为 Zulu 11、AdoptOpenJDK 11 和 Oracle/OpenJDK/AdoptOpenJDK 14 添加了新的 JDK 支持。 Elasticsearch API key support 对 API 密钥的支持已在 6.7.0 中添加到 Elasticsearch 中。通过 7.8.0,Logstash 在 Elasticsearch 输出插件中引入了对 Elasticsearch API 密钥的支持#934。 从 LDAP 到 SAML 等,Elasticsearch 中的身份验证可以通过不同的方式进行。用户/密码身份验证对于离散用户访问 Elasticsearch 有意义。对于机器对机器的通信,API 密钥访问更为常见。 Elasticsearch 输入和过滤器插件中对 API 密钥的支持以及监视和管理功能将在以后的版本中添加。 Proxy support for monitoring and centralized management 有许多用户在分段网络中部署 Logstash 和 Elastic Stack,在分段网络中,一个组件可能无法直接与另一组件或 Internet 保持联系。Logstash 插件(例如elasticsearch、http 和 SNS 输出)支持代理服务器的配置。7.8.0 版将代理支持引入监视和中央管理#11799。 性能改进和重要问题已修复 性能:共享一个 single secret store #10794 性能:改善 event.clone 内存使用率#11794 Refactor:避免在 single even中发生 array#11732 Debugging:在启动时 print RUBY_DESCRIPTION,以方便调试#11852 修复:避免从 Java 使用 gsub(frame dependent)#11874 ...... 更多详细信息可查看发布说明。 下载地址:https://elastic.co/downloads/logstash

优秀的个人博客,低调大师

基于 Hunt Framework 3.2.0 快速构建服务端项目教程

Hunt Framework 是使用 D语言开发的全栈 Web 框架,类似于 Laravel / SpringBoot / Django 等,可以让 D 语言开发者快速的创建项目,内置超多业务规范一是方便开发者开箱即可用,二是方便管理者对项目代码更容易 review。 本示例代码基于目前最新的 Hunt Framework 最新版本 3.2.0 进行编写,接下来让我们感受一下使用 DLang 开发的快感:) 1. 创建一个普通的模板页面渲染项目 1.1 基于骨架项目创建空项目 首先使用 git 命令把骨架项目克隆到本地。 git clone https://github.com/huntlabs/hunt-skeleton.git myproject cd myproject 1.2 修改项目 http 监听地址和 监听端口 http 相关配置项在 config/application.conf 中可以找到如下内容,我们监听的 ip 是 127.0.0.1 端口是 8080: http.address = 127.0.0.1 http.port = 8080 1.3 控制器 我们可以看到 source/app/controller/IndexController.d 的源码,这个就是一个普通的控制器,代码如下: module app.controller.IndexController; import hunt.framework; class IndexController : Controller { mixin MakeController; @Action string index() { return view.render("index"); } } 我们可以看到 index 控制器还有一个 index 的方法,这个方法被使用 @Action 标记为了可访问的页面,而这个页面又使用 view 视图渲染了 index.html 模板(这里模板的扩展名因安全问题被省略)。 这里的视图会渲染 resources/views/default/index.html 模板文件。 1.4 路由配置 在配置文件目录可以找到 config/routes 这个默认的路由配置表,骨架项目有一条记录如下: GET / index.index 这条语义是使用 GET 方法访问 / 这个 path 会映射到 index 控制器的 index 方法。 1.5 编译运行项目 整个项目使用 dub 包管理器管理,一个命令即可编译运行: dub run -v 这时候根据你自己配置的 ip 和 端口访问即可: http://127.0.0.1:8080 至此你的 D 语言项目就跑起来了,是不是很酷?😎那下面章节来点数据库操作。 2 创建一个增删改查的 API 项目 在创建增删改查 API 之前我们需要做一些准备工作,一是创建好数据库的表结构,二是开启框架的路由组支持,让用户可以通过 example.com/api/ 或 api.example.com 的形式可以访问到。 2.1 首先我们开启路由组 在 config/application.conf 找到配置项 route.groups 修改为: route.groups = api:path:api 那我这里解释一下 api:path:api 的含义,{路由组的KEY}:{访问路由组的方式}:{路由组的自定义值},那通过上面这个设置后我们的 api 访问地址前缀就应该是: http://127.0.0.1:8080/api/ 如果我们设置为 route.groups = api:domain:api.example.com 那我们访问 api 地址的前缀就是: http://api.example.com/ 2.2 我们的表结构设计 可以自己执行这个 SQL 创建表,我们数据库使用的是 MySQL 5.7.x 做的 example。 SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for my_user -- ---------------------------- DROP TABLE IF EXISTS `my_users`; CREATE TABLE `my_users` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `username` varchar(255) DEFAULT NULL, `password` varchar(255) DEFAULT NULL, `email` varchar(255) DEFAULT NULL, `created` bigint(11) DEFAULT NULL, `updated` bigint(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; SET FOREIGN_KEY_CHECKS = 1; 2.3 修改数据库相关配置文件 数据库配置项文件在 config/application.conf 进行修改,找到如下配置按照你自己本地数据库环境进行设置: # Database database.driver = mysql database.host = 127.0.0.1 database.port = 3306 database.database = myproject database.username = root database.password = 123456 database.charset = utf8 database.prefix = my_ database.enabled = true 2.4 创建数据库模型 Hunt Framework 也是内置 Model 模型,我们创建模型类 app/model/User.d: module app.model.User; import hunt.entity; @Table("users") class User : Model { mixin MakeModel; @AutoIncrement @PrimaryKey ulong id; string username; string password; string email; uint created; uint updated; } 要注意的是使用 @PrimaryKey 标记 id 为主键,并且使用 @AutoIncrement 标记为自增,@Table("users") 是让你自己填写自己表的真实名字,我们表的真实名是 my_users,因为所有表前缀已经在 config/application.conf 中的配置项 database.prefix = my_ 配置过,所以这里的值我们只需要写 users 即可。 2.5 创建 Repository 对象 这个对象只要继承 EntityRepository 即可,里边已经包含了很多丰富的操作方法,app/repository/UserRepository.d: module app.repository.UserRepository; import hunt.framework; import app.model.User; class UserRepostiroy : EntityRepository!(User, ulong) { } 这里我们自定义 UserRepository 继承的 EntityRepository 是 hunt-entity 这个 ORM 库自带的类,我们使用模板传值的方式将我们自定义的 Model 类 User 和主键类型 ulong 传递过去了,这个编译时会帮我们处理很多事情,我们只要记住如何写就好了。 2.6 创建表单验证的类 作为 API 就很难缺少 POST 表单的接收和验证,Hunt Framework 内置表单验证机制,我们需要自己实现一个表单验证的对象 app/form/UserForm.d: module app.form.UserForm; import hunt.framework; class UserForm : Form { mixin MakeForm; @Length(4, 30, "用户名长度必须在 {{min}} 到 {{max}} 位之间。") string username; @Length(8, 32, "密码长度必须在 {{min}} 到 {{max}} 位之间。") string password; @NotEmpty("Email地址不允许为空。") string email; } 2.7 创建 API 对应的控制器 因为我们 API 使用的是独立的路由组,所以我们创建控制器的时候需要在 app/controller/ 目录下再创建一个子目录 api 来保存对应的控制器类文件,所以我们这个类文件命名为 app/controller/api/UserController.d: module app.controller.api.UserController; import hunt.framework; import app.repository.UserRepostiroy; import app.model.User; import app.message.ResultMessage; import app.form.UserForm; class UserController : Controller { mixin MakeController; @Action Response add(UserForm form) { // ResultMessage 是要返回的 json 消息体 auto resultMessage = new ResultMessage; // 使用 valid() 方法获取一个校验结果对象 auto valid = form.valid(); if (!valid.isValid()) { // 给个错误码 resultMessage.code = 10001; // valid.messages() 方法可以获取所有错误信息,我们这里只简单的获取一个错误进行返回 foreach (message; valid.messages()) { resultMessage.message = message; break; } } else { auto repository = new UserRepository; auto user = new User; user.username = form.username; user.password = form.password; user.email = form.email; // 把模型数据保存到数据库 repository.save(user); // 因没有错误就不需要设置错误码,提示添加成功即可 import std.format : format; resultMessage.message = format!"用户( %d )添加成功!"(user.id); } // 返回结果对象会自动由 JsonResponse 序列化为 json 返回给客户端 return new JsonResponse(resultMessage); } } 这里是 ReusltMessage 的代码: app/message/ReusultMessage.d module app.message.ResultMessage; class ResultMessage { uint code = 0; string message; } 2.8 API 路由配置文件 每个路由组有自己的路由配置表,api 的路由配置表是 config/api.routes,这个规则是不是很简单?我们看看添加用户接口的路由配置项: POST /user/add user.add 是不是很简单?这里因为是 api.routes 所以控制器会在 app/controller/api/ 目录下找对应的 user 控制器和 add 方法。 2.9 测试添加用户接口 这里我们使用 Firefox 插件进行接口请求,我们按照表单的要求添加 3 个字段,分别为 username、password、email,我们也按照 UserForm 中的验证规则去填写,当我们提交表单的时候可以看到如下界面: 这里提示 用户( 9 )添加成功!,这里的数字 9 其实是我们在将用户数据写入库中以后返回的主键 ID。 那我们为了测试表单校验的作用,我们把密码从 8 位改为 6 位,因为我们在 UserForm 中规则设定的是 8~32 位之间,再次提交表单如下结果: 这里说明我们的表单校验已经起了作用:) 3 总结 最总完成的项目目录结构如下: MYRPOJECT/ ├── config │ ├── api.routes │ ├── application.conf │ └── routes ├── data │ └── mysql.sql ├── dub.sdl ├── resources │ ├── translations │ │ ├── en-us │ │ │ └── message.ini │ │ └── zh-cn │ │ └── message.ini │ └── views │ └── default │ ├── footer.html │ ├── header.html │ └── index.html ├── source │ ├── app │ │ ├── controller │ │ │ ├── IndexController.d │ │ │ └── api │ │ │ └── UserController.d │ │ ├── form │ │ │ └── UserForm.d │ │ ├── message │ │ │ └── ResultMessage.d │ │ ├── model │ │ │ └── User.d │ │ └── repository │ │ └── UserRepository.d │ └── main.d └── wwwroot └── favicon.ico 整个项目看下来也算是清晰明了,在框架的使用方式上有着熟悉的味道,Hunt Framework 有着像 Laravel 那么快的开发效率,也有像 SpringBoot 那样规范的数据库操作方式,也具有像 golang 一样有原生语言编译后方便的部署方式。 相关资源地址 HuntLabs 官方网站: https://www.huntlabs.net Hunt Framework 代码库: https://github.com/huntlabs/hunt-framework 完整示例代码: https://gitee.com/zoujiaqing/example-myuser

优秀的个人博客,低调大师

Logstash 7.7.0 发布,开源服务端数据处理流程

Logstash 是开源的服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到你最喜欢的“存储库”中。目前,Logstash 7.7.0已正式发布,该版本更新内容如下: 新功能和改进 Improving Logging 继过去几个版本中改进了日志记录功能之后,日志消息已得到扩展,可以更准确地显示有关插件的信息。这些更改使用户可以更好地标识带有插件或管道的日志消息。#11078、#11593、#11567 更改包括: 已添加plugin.name到所有日志条目。 已添加plugin.id和pipeline.id到 docker 镜像。 改进 Java(Pipeline)Execution Engine Logstash 7.7 中提供的改进使用户可以更好地控制 singleworker pipelines 的事件顺序。 从历史上看,当 single worker 执行 pipeline 时,将保留输入插件和输出插件之间的 Logstash 事件顺序。从未正式记录过此行为,但这是许多用户所依赖的功能。 引入 Java Execution 引擎时,它破坏了单个工作程序的订单保留。现在,通过引入pipeline.ordered设置已解决此问题。#11552,#11710 该pipeline.ordered设置允许三种模式: auto (default)-如果只有一个 pipeline worker ,则自动启用订购。 true-强制排序,同时如果有多个工作程序,则阻止启动logstash。 false-无法保证 ordering。 Notable issues fixed Fixed:添加sudo到 GPG-KEY 的 rpm import中#11684 Fixed:使用轻量级正则表达式匹配(不取决于框架)#11653 Fixed:monitoringAPI无法正确解析包括环境变量扩展在内的 ID 的问题#11592 Fixed:更改 Javadoc 以符合 JDK13的更新要求#11642 ...... 更多详细信息可查看发布说明。 下载地址:https://elastic.co/downloads/logstash

优秀的个人博客,低调大师

Logstash 7.6.1 发布,开源服务端数据处理流程

Logstash 是开源的服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到你最喜欢的“存储库”中。目前,Logstash 7.6.1已正式发布,该版本更新内容如下: Logstash 7.6.1 发行说明 [DOC]返工 ls netflow 模块弃用通知#11600 [DOC]阐明 7.6 的内部收集器弃用状态#11607 [DOC]修复了用于监控的设置名称#11597 [DOC]添加 Apple 公证信息#11588 Plugins Dns Filter 将 Timeout::timeout block替换为Resolv::DNS::timeouts=#62 增加了对 ruby version > 2.0的限制,有效地使 Logstash 6.x+成为必需#62 Memcached Filter 修复了未设置 ttl 的问题#13 Split Filter 修复了@target 优化将阻止 event.remove(@field)被调用的问题 #40 Beats Input 修复了不必要为每个连接创建 SslContext 的问题#383 修复了充气机关闭时未被调用 end 的问题#383 由于 IdleStateHandler 中的问题,将 Netty 降级为 4.1.34#380 ...... 更多详细信息可查看发行说明:https://www.elastic.co/guide/en/logstash/7.6/logstash-7-6-1.html#_plugins

优秀的个人博客,低调大师

Logstash 7.5.2 发布,开源服务端数据处理流程

Logstash 是开源的服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到你最喜欢的“存储库”中。目前,Logstash 7.5.2已正式发布,该版本更新内容如下: Logstash 7.5.1 发行说明 修复:Java Execution -通过将类缓存从 ComputeStepSyntaxElement 移到 CompiledPipeline,提高 Logstash 启动时间 #11490 修复:Java Execution -通过仅在所有 WorkerLoops 都完全初始化后才启动,避免在过滤器和输出编译未完成时启动输入#11492 修复:通过使 get_thread_id 为“nil safe”来避免nil本机线程出现问题#11458 更新 JrJackson 和Jackson依赖项#11478 Pluginsedit Beats Input 更新了 Netty 依赖性,并删除了对不安全的 CBC 密码的支持 #376 更新了 Jackson 依赖 #375 File Input 修复: exclude 处理中的回归。 模式与文件名而不是完整路径匹配。#237 发布说明 下载地址

优秀的个人博客,低调大师

Logstash 7.5.1 发布,开源服务端数据处理流程

Logstash 是开源的服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到你最喜欢的“存储库”中。目前,Logstash 7.5.1已正式发布,该版本更新内容如下: Logstash 7.5.1 发行说明 通过包含相关 DLQ 的路径来提高报告完整 DLQ 时日志消息的实用性#11280 修复:消除了管道引用通过脱机插件包安装的基于Java的插件时管道启动时可能发生的崩溃#11340 修复:常见的 remove_field 插件选项现在可以在@metadata字段上正常工作#11342 修复:不要将 ThreadContext 泄漏到系统中#11356 修复:消除了 7.2.0 中引入的回归#11401 修复:使用空的 kibana 零件处理cloud-id#11435 patch release的 bump依赖#11438 Plugins Dns Filter 添加了有关 nameserver 选项的文档,该文档依赖于 /etc/resolv.conf 来配置解析器 Elasticsearch Filter 放松对 Elasticsearch gem 的限制#120 Grok Filter 在多匹配方案中改进了 grok 过滤器性能。#153 Jdbc_static Filter 解决了使用 Java 11 进行驱动程序验证的问题#51 ...... 更多详细信息可查看发行说明 下载地址:https://www.elastic.co/cn/downloads/logstash

优秀的个人博客,低调大师

Logstash 7.5.0 发布,开源服务端数据处理流程

Logstash 是开源的服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到你最喜欢的“存储库”中。目前,Logstash 7.5.0已正式发布,该版本更新内容如下: Logstash 7.5.0发行说明 为多个管道提供所有设置#11076 在 Pipelines.yml 文件中支持替换#11081 每个管道提供日志附加程序#11108 在 OpenSSL 套接字规范中使用 2048 位密钥#11115 添加管道配置的来源#11123 从 log4j2.properties中删除 10k 字符截断#11206 如果 Java 运行时小于 11,则从系统属性中删除#11225修复#11221 [DOC] 将 metricbeat 添加为监视选项#11190 Plugins Kafka Integration Kafka 集成插件的初始版本(将以前分开的 Kafka 插件和共享的依赖项组合到单个代码库中) Rabbitmq Integration RabbitMQ 集成插件的初始版本(将以前分开的 RabbitMQ 插件和共享的依赖项组合到单个代码库中) Elasticsearch Output 修复了文档中的措辞和更正的选项#881#883 弃用:添加了有关将 Logstash 的默认发行版与 OSS 版本的 ES 连接的警告#875 添加了用于连接到 ES 8.x 的模板#871 添加了对 ES 8.x 的 sniffing 支持#878 详细信息:https://www.elastic.co/guide/en/logstash/7.5/logstash-7-5-0.html 下载地址:https://www.elastic.co/cn/downloads/logstash

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册