做唯品客网站的感想/河北seo网络推广
Netty系列整体栏目
内容 | 链接地址 |
---|---|
【一】深入理解网络通信基本原理和tcp/ip协议 | https://zhenghuisheng.blog.csdn.net/article/details/136359640 |
【二】深入理解Socket本质和BIO | https://zhenghuisheng.blog.csdn.net/article/details/136549478 |
【三】深入理解NIO的基本原理和底层实现 | https://zhenghuisheng.blog.csdn.net/article/details/138451491 |
深入理解NIO的基本原理和底层实现
- 一,深入理解NIO的底层原理
- 1,Reactor反应堆模式
- 1.1,通过餐厅描述Bio
- 1.2,通过餐厅引入nio
- 2,NIO三大核心组件
- 3,NIO通信原理
- 4,通过NIO实现简单网络编程
一,深入理解NIO的底层原理
在上一篇中,讲解了bio的底层原理和具体实现,虽然bio在一定场景下也可以进行通信,但是随着互联网越来越多业务的场景,bio会存在阻塞的弊端被暴露无疑,在并发量稍微大点的地方,通过bio实现的网络编程会显得略显吃力。于是在jdk1.4之后,引入了一个新东西 NIO ,由于bio原名叫做 Blocking IO阻塞io,因此新网络编程的取名nio,有着 NoBlocking IO即不阻塞io,当然也有的地方取名为new io。
在讲解nio之前,依旧和以前的学习一样,不能脱离官网进行学习:netty官网地址 ,用户指南可以参考4.1版本
1,Reactor反应堆模式
网络编程从bio废弃到再到nio的崛起,跟nio的底层实现有着很大的联系,其最主要的设计思想就是这个 reactor 反应堆模式,总结这个reactor模式主要有三点:注册感兴趣的事件,扫描是否有感兴趣的事件发生,在事件发生之后做出相应的处理
在讲解这个反应堆模式之前,先通过一个生活中的案例来讲述这个事情,以我们去线下餐厅点餐为例,首先用户扫码点餐,然后点餐系统返回一个排队的号码,再服务员喊到号码的时候去取餐,就以这个案例来说明一下什么是反应堆模式。
1.1,通过餐厅描述Bio
首先在上面的这个点餐的案例中,bio的实现如下,就有点类似于用户直接和厨师直接进行交流,告诉厨师要什么菜,当没有用户点餐时,那么厨师就会一直等待用户来点餐,直到有用户点餐为止,如果一直没有用户点餐,那么厨师就会一直处于阻塞状态进行等待,这里就对应了bio服务端,没有客户端请求时会长期处于一个阻塞状态;
如果已经有了一个用户点餐,那么厨师会先炒这个用户的菜,当有其他用户来点餐时,那么其他用户会处于阻塞状态,只有等帮第一个用户炒完菜之后,厨师才能和第二个用户进行交流,第二个用户才能把自己需要什么菜告诉厨师,在如果在上一个用户的菜还没炒玩之前,那么下一个用户则会处于一个阻塞等待状态。因此这样效率肯定是非常低下的,那么毫无疑问,bio的这种方式注定是要被淘汰的。(这里服务端默认为在一个cpu里面,就是说一个cpu中只有一个线程去处理请求,上面案例对应的就是服务端对应的就是一个厨师,厨师就是老板,其他顾客就是对应的服务端)
1.2,通过餐厅引入nio
由于一个厨师对应多个用户效率会十分的低下,而且如果用户量稍微大一点,那么每个用户就不用去干其他的事情,就一直排队阻塞在那里,因此严重的影响整个系统的吞吐量以及严重的影响用户的体验感。随着客户的增加,或者午餐这段高峰期,为了解决用户长时间等待问题,那么就可以做一个点餐系统,用户只需扫码点餐即可,当用户点餐完成之后,可以去做用户自己想做的事情,如出去逛逛等,此时系统会给用户一个点餐号,此时就解决了用户长时间排队阻塞的问题。厨师这边也不需要每次只处理一个请求,如多个用户点同一个菜,那么厨师可以一次性炒多份菜,这样也提高了厨师这边的效率。当厨师将菜炒好之后,只需要服务员通过念号或者通过公众号通知订餐的用户即可。
反应堆模式就是,不能一直等着客户端去等待服务端的响应,而是通过某个中间层,客户端先向中间层注册一个事件,当服务端有空做出响应的时候再通过定时任务去扫描这个中间层,当中间层发现有注册的事件之后,再去通知客户端,这样就可以减少客户端的等待时间。换句话就是说,通过请求响应的模式来说,客户端向服务端发送一个请求之后,如果服务端长时间没有响应,那么客户端可以结束此次请求,服务端来不及响应,但是服务端得记录这个请求的记录,当服务端有空的时候,再去扫描这个记录,再去响应这个请求,再通过通知异步的去响应对应的请求。
2,NIO三大核心组件
在nio编程中,里面有三大核心组件,分别是 Selector、Channel、Buffer 三大组件。
在上面讲解了通过餐厅系统去了解nio的内部实现,在这三大组件中,扮演的角色分别如下:
- 由于在网络编程中,基本是基于tcp协议去实现客户端和服务端之间的通信,因此通过socket将tcp协议封装,而这里的channel,是对这个socket进行了再次的封装。也就是说,只需要创建这个channel实例就可以完成双端之间的通信,因此点餐系统里面的用户和厨师之间的交流就是通过这个channel去实现的,那么channel扮演的角色就是完成客户和厨师之间的最终交流
- Selector就是一个选择器,通过这个餐厅系统,可以发现引入了一个新的点餐系统,用于注册客户的订单以及在订单完成之后给予响应,就是通知下单的客户,因此这个Selector选择器扮演的角色就是这个点餐系统,也是这个反应堆模式的核心,用于注册客户端事件,扫描这些注册的事件,并对这些事件做出具体的响应
- 而这个Buffer,就是nio和bio之间的重大区别,因为这个Buffer就是一个Nio的一个重要的特性,用于面向缓冲流进行编程,这个Buffer指的是应用层之间的buffer,就是已经建立好连接之后,在服务端内部的一个缓冲区,如在这个餐厅系统中,在准备食材的时候也是需要大量时间的,如果先点餐的用户需要准备的食材要久一些,那么厨师可以优先炒后面用户下的单,那么这个Buffer就起到重要的作用了。由于这个bio是串行执行,那么就不存在这个Buffer的说法,但是在这个nio里面,通过这个Buffer让整个系统更加的灵活,即使先建立的请求,也可以后响应,从而提高整个系统的吞吐量。还有比如说可以重复的读取数据,来不及处理的优先放在这个buffer缓冲区,某个buffer缓冲区如果字节数没达到要求可以先去处理其他的缓冲区等,主要是让整个系统更加的灵活多变,从而提高整个系统的吞吐量和响应。同时也是与BIO最大的差异化之一
3,NIO通信原理
通过上面的餐厅事例和讲解NIO内部的三大组件,接下来通过一个发送和接收数据的事例讲解NIO底层到底是如何进行网络通信和数据传输的。
- 首先客户端先向服务端发送一个请求,然后服务端在接收到这个请求之后,服务端首先会通过这个Selector先向本地注册一个连接事件,然后再扫描Channel事件列表,查看是否有感兴趣的Channel事件
- 在Channel中找到这个对连接感兴趣的事件之后,随后通知这个感兴趣的事件,创建一个ServerSocketChannel对象,用于服务端和客户端通过三次握手建立可靠的连接
- 完成建立连接之后,又会去Selector中扫描是否有对读数据感兴趣的事件,如果找到有服务端对读数据感兴趣的事件,又会通知对这个事件感兴趣的具体事件,用于实例化SocketChannel对象,这里的SocketChannel就是建立好连接的Socket对象,用于真正的去读取数据以及发送数据
- socket读取的数据并不是发送给服务端的应用程序,而是将数据先存入到Buffer中,让应用程序去读取buffer里面的数据,从而提高整个架构的吞吐量和效率
- 最后将要响应的数据也存到Buffer中,然后通过感兴趣的写事件,将数据返回给对应的客户端即可
4,通过NIO实现简单网络编程
上面讲解了大量的理论,接下来通过具体的编码,来讲述NIO的底层到底是怎么实现的。首先创建一个服务端的线程,用于接收客户端的请求以及内部做出的响应,接下来创建一个 NioServerTask 的任务类,并且实现一个 Runnable 方法,在该方法中去创建 selector,ServerSocketChannel,SockerChannel、Buffer等对象
package com.zhs.netty.nio.nio;import com.zhs.netty.nio.Const;
import lombok.extern.slf4j.Slf4j;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;/*** 服务端线程具体代码实现*/
@Slf4j
public class NioServerTask implements Runnable{private volatile boolean started;private ServerSocketChannel serverSocketChannel;private Selector selector;/*** 构造方法* @param port 指定要监听的端口号*/public NioServerTask(int port) {try {//创建一个选择器selector = Selector.open();//创建ServerSocketChannel的实例serverSocketChannel = ServerSocketChannel.open();//通道实例设置为非阻塞模式serverSocketChannel.configureBlocking(false);//绑定端口serverSocketChannel.socket().bind(new InetSocketAddress(port));//注册事件到selector之上,监听客户端连接serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);started = true;log.info("服务器已启动,端口号:" + port);} catch (IOException e) {e.printStackTrace();}}@Overridepublic void run() {while(started){try {//selector每隔1s被唤醒一次selector.select(1000);//获取全部已经注册的本地事件Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();while(iterator.hasNext()){SelectionKey key = iterator.next();//将处理过的本地注册事件给删除iterator.remove();handleInput(key);}} catch (IOException e) {e.printStackTrace();}}}//处理具体的事件private void handleInput(SelectionKey key) throws IOException {if(key.isValid()){//处理新接入的客户端的请求if(key.isAcceptable()){//获取channels全部事件中对此感兴趣的事件ServerSocketChannel ssc = (ServerSocketChannel) key.channel();//获取到感兴趣的事件之后,创建一个socket实例,用于发送和读取数据SocketChannel sc = ssc.accept();//设置为非阻塞sc.configureBlocking(false);//注册一个感兴趣的读事件sc.register(selector,SelectionKey.OP_READ);}//处理对端的发送的数据if(key.isReadable()){SocketChannel sc = (SocketChannel) key.channel();//创建ByteBuffer,开辟一个缓冲区ByteBuffer buffer = ByteBuffer.allocate(1024);int readBytes = sc.read(buffer);if(readBytes>0){//缓冲区中存在指针,记录有效位置buffer.flip();//根本有效位置的指针处创建字节数组byte[] bytes = new byte[buffer.remaining()];//将缓冲区可读字节数组复制到新建的数组中buffer.get(bytes);String message = new String(bytes,"UTF-8");log.info("服务器收到消息:" + message);String result = Const.response(message);doWrite(sc,result);}else if(readBytes<0){//将channels集合的数据取消key.cancel();sc.close();}}}}/*发送应答消息*/private void doWrite(SocketChannel sc,String response) throws IOException {byte[] bytes = response.getBytes();ByteBuffer buffer = ByteBuffer.allocate(bytes.length);buffer.put(bytes);buffer.flip();sc.write(buffer);}
}
从上面的代码中可以发现,在服务端中只关注了读的事件,并没有关注写的事件。并且在这个Buffer中,存在一个指针,用于记录buffer的有效位置,这样在读数据时,只需要读取到有效的数据即可。
服务端代码写好之后,接下来编写客户端的代码,代码和客户端基本一样,但是由于客户端不需要提供服务,因此在客户端这边是不需要 ServerSocketChannel 这个组件的。其他的 SocketChannel,Selector,Buffer 还是需要的
package com.zhs.netty.nio.nio;import lombok.extern.slf4j.Slf4j;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;/*** @author zhenghuisheng* nio客户端请求*/
@Slf4j
public class NioClientTask implements Runnable{private String host;private int port;private volatile boolean started;private Selector selector;private SocketChannel socketChannel;public NioClientTask(String ip, int port) {this.host = ip;this.port = port;try {//创建选择器的实例selector = Selector.open();//创建ServerSocketChannel的实例socketChannel = SocketChannel.open();//设置通道为非阻塞模式socketChannel.configureBlocking(false);started = true;} catch (IOException e) {e.printStackTrace();}}@Overridepublic void run() {try{doConnect();}catch(IOException e){e.printStackTrace();System.exit(1);}//循环遍历selectorwhile(started){try{//无论是否有读写事件发生,selector每隔1s被唤醒一次selector.select(1000);//获取全部已经注册的本地事件Set<SelectionKey> keys = selector.selectedKeys();//转换为迭代器Iterator<SelectionKey> it = keys.iterator();SelectionKey key = null;while(it.hasNext()){key = it.next();it.remove();try{handleInput(key);}catch(Exception e){if(key != null){key.cancel();if(key.channel() != null){key.channel().close();}}}}}catch(Exception e){e.printStackTrace();System.exit(1);}}//selector关闭后会自动释放里面管理的资源if(selector != null)try{selector.close();}catch (Exception e) {e.printStackTrace();}}//具体的事件处理方法private void handleInput(SelectionKey key) throws IOException{if(key.isValid()){//获得关心当前事件的channelSocketChannel sc = (SocketChannel) key.channel();//连接事件if(key.isConnectable()){if(sc.finishConnect()){socketChannel.register(selector,SelectionKey.OP_READ);}else System.exit(1);}//有数据可读事件if(key.isReadable()){//创建ByteBuffer,并开辟一个1M的缓冲区ByteBuffer buffer = ByteBuffer.allocate(1024);//读取请求码流,返回读取到的字节数int readBytes = sc.read(buffer);//读取到字节,对字节进行编解码if(readBytes>0){//将缓冲区当前的limit设置为position,position=0,// 用于后续对缓冲区的读取操作buffer.flip();//根据缓冲区可读字节数创建字节数组byte[] bytes = new byte[buffer.remaining()];//将缓冲区可读字节数组复制到新建的数组中buffer.get(bytes);String result = new String(bytes,"UTF-8");log.info("客户端收到消息:" + result);}//链路已经关闭,释放资源else if(readBytes<0){key.cancel();sc.close();}}}}private void doWrite(SocketChannel channel,String request)throws IOException {//将消息编码为字节数组byte[] bytes = request.getBytes();//根据数组容量创建ByteBufferByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);//将字节数组复制到缓冲区writeBuffer.put(bytes);//flip操作writeBuffer.flip();//发送缓冲区的字节数组channel.write(writeBuffer);}private void doConnect() throws IOException{//非阻塞的连接,这里需要注意,因为客户端和服务端都是无阻塞的,因此可能在三次握手建立连接之前,//这段注册读的代码就已经走完了,因此在else中增加一个注册连接的代码if(socketChannel.connect(new InetSocketAddress(host,port))){socketChannel.register(selector,SelectionKey.OP_READ);}else{socketChannel.register(selector,SelectionKey.OP_CONNECT);}}//写数据对外暴露的APIpublic void sendMsg(String msg) throws Exception{doWrite(socketChannel, msg);}
}
接下来进行一个数据的测试,先创建一个服务端的Main方法,然后启动这个Main方法,并且设置端口号为8881
public class NioServer {private static NioServerTask nioServerTask;public static void main(String[] args){nioServerTask = new NioServerTask(8881);new Thread(nioServerTask,"NioServer").start();}
}
再创建一个客户端的Main方法,ip设置成本地,端口号设置成服务端设置的端口号
/*** @author zhenghuisheng*/
public class NioClient {private static NioClientTask nioClientTask;public static void main(String[] args) throws Exception {nioClientTask = new NioClientTask("127.0.0.1",8881);new Thread(nioClientTask,"nioClient").start();//控制台输入Scanner scanner = new Scanner(System.in);String message = scanner.next();while(!StringUtils.isEmpty(message)){nioClientTask.sendMsg(message);}}
}
客户端发送消息:
132432
21:58:41.118 [nioClient] INFO com.zhs.netty.nio.nio.NioClientTask - 客户端收到消息:Hello,132432,Now is Sat May 04 21:58:41 CST 2024
服务端接收到的消息:
21:58:30.767 [main] INFO com.zhs.netty.nio.nio.NioServerTask - 服务器已启动,端口号:8881
21:58:41.114 [NioServer] INFO com.zhs.netty.nio.nio.NioServerTask - 服务器收到消息:132432
到此为止,通过NIO的方式将服务端发送消息和客户端接收消息的代码实现
相关文章:

【netty系列-03】深入理解NIO的基本原理和底层实现(详解)
Netty系列整体栏目 内容链接地址【一】深入理解网络通信基本原理和tcp/ip协议https://zhenghuisheng.blog.csdn.net/article/details/136359640【二】深入理解Socket本质和BIOhttps://zhenghuisheng.blog.csdn.net/article/details/136549478【三】深入理解NIO的基本原理和底层…...

大数据Scala教程从入门到精通第二篇:Scala入门
一:Scala入门 1:为什么学习Scala Spark新一代内存级大数据计算框架,是大数据的重要内容 Spark就是使用Scala编写的。因此为了更好的学习Spark,需要掌握Scala这门语言 Spark的兴起,带动Scala语言的发展! 2:Scala的发展…...

Spring Data JPA数据批量插入、批量更新真的用对了吗
Spring Data JPA系列 1、SpringBoot集成JPA及基本使用 2、Spring Data JPA Criteria查询、部分字段查询 3、Spring Data JPA数据批量插入、批量更新真的用对了吗 4、Spring Data JPA的一对一、LazyInitializationException异常、一对多、多对多操作 前言 在前两篇文章已经…...

数据结构-线性表-应用题-2.2-12
1)算法的基本设计思想:依次扫描数组的每一个元素,将第一个遇到的整数num保存到c中,count记为1,若遇到的下一个整数还是等于num,count,否则count--,当计数减到0时,将遇到的下一个整数保存到c中,计…...

目录页码右对齐快速解决
选择目录–段落–制表符,按图中设置即可...

分红76.39亿,分红率再创新高,成长活力无限的伊利带来丰厚回报
伊利47万股东,又等来了一个好消息。 4月29日,伊利股份发布2023年报,实现营业总收入1261.79亿元,归母净利润104.29亿元,双创历史新高,实现连续31年稳健增长。 在递交亮眼成绩单的同时,乳业巨头伊…...

关于行进线路。
https://map.tianditu.gov.cn/ 作者:Chockhugh 链接:https://www.zhihu.com/question/20545559/answer/494685117 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 以50km,几乎全是…...

Unity 编辑器工具 - 资源引用查找器
目录 1.功能概述 2.完整代码 3. 实现原理 4. 使用预览 5.新增优化版本 在Unity项目开发过程中,管理和维护资源之间的引用关系是至关重要的。当然我们项目也是需要这个功能 毕竟项目大了之后查找资源引用还是交给 资源引用查找器 比较好。 1.功能概述 资源引用…...

MySQL中的批量更新实战
MySQL中的批量更新实战 表结构 mysql> desc dept; --------------------------------------------------------- | Field | Type | Null | Key | Default | Extra | --------------------------------------------------------- | deptno | int(11) …...

为软件教学文档增加实践能力
为了更方便软件教学,我们在凌鲨(OpenLinkSaas)上增加了公共资源引用的功能。 目前可以被引用的公共资源: 微应用常用软件公共知识库Docker模板 引用公共资源 引用微应用 目前微应用包含了主流数据库,终端等工具,可以方便的进行各种相关实…...

39-2 Web应用防火墙 - WAF数据库层绕过
如果你本地没有安装mysql就先安装一下:4-2 MySQL 的下载与安装_mysql5.7.9.1下载-CSDN博客 一、数据库层绕过简介 绕过数据库层通常用于规避Web应用防火墙(WAF)的SQL注入防护规则。攻击者需要利用数据库特性,寻找规避常规安全策略的方法。这里涉及到不同数据库的特性、SQ…...

薪酬激励策略:留住企业核心人才的关键
在竞争激烈的商业环境中,企业为了保持竞争力和市场地位,必须高度重视人才的管理和发展。企业的核心人才是推动企业发展的关键因素,因此,如何有效地激励和留住这些核心人才,成为企业持续发展的关键之一。薪酬激励策略作…...

【bbs02补】注册功能form组件-前端-后端-总结、登录功能(前端、后端、生成验证码)
1 注册功能 1.1 注册功能form组件 1.2 注册功能前端 1.3 注册功能后端 1.4 forms组件和前后端总结 2 登录功能 2.1 登录前端 2.2 生成验证码 1 注册功能 1.1 注册功能form组件 # 注册页面-用户名-密码-确认密码-邮箱-手机号-头像# form组件 可以帮助我们1 快速生成前端页面2 数…...

MindSponge分子动力学模拟——定义一个分子系统
技术背景 在前面两篇文章中,我们分别介绍了分子动力学模拟软件MindSponge的软件架构和安装与使用。这里我们进入到实用化阶段,假定大家都已经在本地部署好了基于MindSpore的MindSponge的编程环境,开始用MindSponge去做一些真正的分子模拟的工…...

unity想让方法带一个默认参数怎么写
在C#中,包括Unity使用的C#版本,你可以为方法参数提供默认值。这允许你在调用方法时省略某些参数,并使用这些参数的默认值。以下是如何为一个方法参数设置默认值的示例: using UnityEngine; public class MyClass : MonoBehaviou…...

从零开始的软件测试学习之旅(六)测试网络基础知识
测试网络基础知识 HTTP和HTMLURLDNS客户端和服务器请求方法和状态码面试高频Fiddler抓包工具教学弱网 HTTP和HTML 概念 html: HyperText Markup Language 超文本标记语言 http: HyperText Transfer Protocol 超文本传输协议 超文本: 图片, 音频, 视频 关系:http 可以对 html 的…...

NSS题目练习
[SWPUCTF 2021 新生赛]gift_F12 通过题目提示可以知道flag应该可以在源代码中找到 查看源代码,直接用 ctrlf 搜索flag即可 [SWPUCTF 2021 新生赛]jicao 题目打开后能看到一串php代码,要求是用post传参传入idwllmNB以及用get传参传入json[x]"wllm&q…...

Springboot+vue项目零食销售商城
摘要 随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,零食销售商城当然也不能排除在外。零食销售商城是以实际运用为开发背景,运用软件工程原理和开发方法ÿ…...

cesium 雷达遮罩(电弧球效果)
cesium 雷达遮罩(电弧球效果) 以下为源码直接复制可用 1、实现思路 通过修改“material”材质来实现轨迹球效果 2、代码示例 2.1 index.html <!DOCTYPE html> <html lang="en"><head><!...

W801学习笔记二十三:语文和英语学习应用的代码汇总
前面几章,代码经过重构,可能有点乱。这里给个最终版本,以供参考。 1、应用基类: IScean.h enum SceanResult{SceanResult_EXIT 1, SceanResult_Done 2 };class IScean {public:IScean();virtual ~IScean();// 纯虚函数virtu…...

安卓LayoutParams浅析
目录 前言一、使用 LayoutParams 设置宽高二、不设置 LayoutParams2.1 TextView 的 LayoutParams2.2 LinearLayout 的 LayoutParams 三、getLayoutParams 的使用四、setLayoutParams 的作用五、使用 setWidth/setHeight 设置宽高 前言 先来看一个简单的布局,先用 x…...

UltralSO制作启动盘时报错:磁盘/映像容量太小解决办法
UltralSO制作启动盘时报错:磁盘/映像容量太小解决办法 发现网上随便下载的UltralSO制作启动盘时报错:磁盘/映像容量太小,导致制作启动盘出错 解决方案: 去这个地址下载:https://cn.ultraiso.net/xiazai.html 下载正版…...

2024-05-09四月初二周四
2024-05-09四月初二周四 06:40-23:00 深兰Ai第五期 Part1:课时258:00:00:00 12:30-13:00 午饭烧水: 13:30-23:00 机器学习 19:00-20:00 晚饭: 20:00-23:00 coding 2.5 特征降维 unending 23:00-06:30 烧水资料下载...

【微服务】springcloud整合dubbo3使用nacos作为注册中心
目录 一、前言 二、springboot版本升级带来的问题 2.1 springboot为什么需要升级版本...

php中常用的数据类型汇总
在 PHP 中,常用的数据类型主要有以下几种: 标量类型(Scalar Types) integer(整型):用于存储整数,可以是正数或负数。float(浮点型/双精度型):用于…...

【源码阅读】Golang中的go-sql-driver库源码探究
文章目录 前言一、go-sql-driver/mysql1、驱动注册:sql.Register2、驱动实现:MysqlDriver3、RegisterDialContext 二、总结 前言 在上篇文章中我们知道,database/sql只是提供了驱动相关的接口,并没有相关的具体实现,具…...

2024-05-08 postgres-火山模型-执行-记录
摘要: 2024-05-08 postgres-火山模型-执行-记录 上下文: 2024-05-08 postgres-调试及分析-记录-CSDN博客 火山模型: 数据流是在查询树上,自上而下进行拉取,由上而下的调用。树本身就表明了数据的流动。每次执行一个元组,也就类似于迭代器的…...

QT5带UI的常用控件
目录 新建工程,Qmainwindow带UI UI设计器 常用控件区 Buttons 按钮 containers 容器 控件属性区域 对象监视区 布局工具区 信号与槽区 简单例子1 放置一个按钮控件,改文本为发送,该按键为Button1; 按钮关联信号和…...

识货小程序逆向
声明 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!wx a15018601872,x30184483x…...

【OceanBase 系列】—— OceanBase v4.3 特性解读:查询性能提升之利器列存储引擎
原文链接:OceanBase 社区 对于分析类查询,列存可以极大地提升查询性能,也是 OceanBase 做好 HTAP 和 OLAP 的一项不可缺少的特性。本文介绍 OceanBase 列存的实现特色。 OceanBase从诞生起就一直坚持LSM-Tree架构,不断打磨功能支…...