Simple RPC - 06 从零开始设计一个服务端(上)_注册中心的实现
文章目录
- Pre
- 核心内容
- 服务端结构概述
- 注册中心的实现
- 1. 注册中心的架构
- 2. 面向接口编程的设计
- 3. 注册中心的接口设计
- 4. SPI机制的应用
- 小结
Pre
Simple RPC - 01 框架原理及总体架构初探
Simple RPC - 02 通用高性能序列化和反序列化设计与实现
Simple RPC - 03 借助Netty实现异步网络通信
Simple RPC - 04 从零开始设计一个客户端(上)
Simple RPC - 05 从零开始设计一个客户端(下)_ 依赖倒置和SPI
核心内容
- 服务端结构概述:注册中心和RPC服务的结构及作用。
- 注册中心实现:通过单机版的注册中心实现共享元数据,分析其接口设计和SPI机制。
- RPC服务实现:理解服务端处理RPC请求的核心逻辑,包括如何注册服务和处理请求。
- 请求分发机制:深入了解RequestInvocation和RpcRequestHandler类中的请求分发机制。
- 代码分析与总结:通过代码实例进一步理解设计思想,并总结整体架构和设计原则。
服务端结构概述
在RPC框架中,服务端可以分为两个主要部分:注册中心和RPC服务。
- 注册中心:负责管理服务元数据,并提供服务发现的功能。
- RPC服务:负责处理客户端发来的RPC请求,并调用相应的业务服务。
简单来说:注册中心的作用是帮助客户端来寻址,找到对应 RPC 服务的物理地址;RPC 服务用于接收客户端桩的请求,调用业务服务的方法,并返回结果。
注册中心的实现
1. 注册中心的架构
通常,一个完整的注册中心包括客户端和服务端两部分:
-
客户端:向调用方提供 API,负责与注册中心服务端的通信。
-
服务端:实际管理和记录每个 RPC 服务的注册信息,并将这些信息存储在元数据中。当客户端需要查找服务时,服务端会返回对应的服务地址。
在本例中,出于简化考虑,我们实现了一个单机版的注册中心。这个注册中心只有客户端部分,多个客户端通过读写同一个本地元数据文件实现服务信息的共享。
该注册中心只能在单机环境下运行,不支持跨服务器调用。
2. 面向接口编程的设计
尽管当前实现是单机版的注册中心,但通过“面向接口编程”的设计模式,我们可以在不修改已有代码的情况下,通过 SPI 插件机制,扩展出一个支持跨服务器调用的注册中心(例如,基于 HTTP 协议的实现)。
3. 注册中心的接口设计
在 RPC 框架的接入点接口 RpcAccessPoint
中,增加了一个用于获取注册中心实例的方法:
public interface RpcAccessPoint extends Closeable {/*** 获取注册中心的引用* @param nameServiceUri 注册中心 URI* @return 注册中心引用*/NameService getNameService(URI nameServiceUri);
}
- 该方法接受一个注册中心的 URI 作为参数,并返回一个
NameService
接口的实例。这个NameService
接口表示注册中心的客户端,可以用来和注册中心服务端通信。
NameService
接口中定义了与注册中心通信的核心方法:
public interface NameService {/*** 返回所有支持的协议*/Collection<String> supportedSchemes();/*** 连接注册中心* @param nameServiceUri 注册中心地址*/void connect(URI nameServiceUri);
}
- supportedSchemes 方法返回注册中心支持的协议(例如
file
或http
)。 - connect 方法根据 URI 建立与注册中心的连接。
完整代码如下
/*** 注册中心接口定义* 该接口用于服务的注册和发现,支持多种通信协议** @author artisan*/
public interface NameService {/*** 获取所有支持的协议** @return 支持的协议集合*/Collection<String> supportedSchemes();/*** 连接注册中心** @param nameServiceUri 注册中心的URI地址*/void connect(URI nameServiceUri);/*** 注册服务** @param serviceName 服务名称* @param uri 服务的URI地址* @throws IOException 如果连接或注册失败,则抛出此异常*/void registerService(String serviceName, URI uri) throws IOException;/*** 查询服务地址** @param serviceName 服务名称* @return 服务的URI地址* @throws IOException 如果查找失败,则抛出此异常*/URI lookupService(String serviceName) throws IOException;
}
4. SPI机制的应用
通过 SPI 机制,RpcAccessPoint
可以根据 URI 中指定的协议,动态加载不同的 NameService
实现类。例如,在单机版注册中心中,NameService
的实现类是 LocalFileNameService
,其具体功能是读写本地文件,存储和查找服务信息。
public class LocalFileNameService implements NameService {@Overridepublic Collection<String> supportedSchemes() {return Collections.singleton("file");}@Overridepublic void connect(URI nameServiceUri) {// 连接到本地文件,初始化文件读写工具}// 其他方法实现...
}
通过这种方式,新的注册中心实现可以通过 SPI 动态添加到系统中。例如,要实现一个基于 HTTP 的注册中心,只需开发一个新的 NameService
实现类,并将其添加到系统的 CLASSPATH 中即可。
LocalFileNameService
代码如下
/*** LocalFileNameService 类实现了 NameService 接口,提供了一种基于文件系统来管理服务名称和URI的实现方式* 它使用 "file" 协议来操作本地文件,并将服务信息存储在文件中* @author artisan*/
public class LocalFileNameService implements NameService {private static final Logger logger = LoggerFactory.getLogger(LocalFileNameService.class);/*** 支持的协议集合,本实现仅支持 "file" 协议*/private static final Collection<String> schemes = Collections.singleton("file");/*** 用于存储服务信息的文件对象*/private File file;/*** 返回此服务支持的协议集合** @return 支持的协议集合*/@Overridepublic Collection<String> supportedSchemes() {return schemes;}/*** 连接到指定的名称服务URI,如果支持该URI的协议,则将URI解析为本地文件* 此方法首先检查给定的URI是否使用受支持的协议如果协议受支持,则将URI转换为本地文件路径* 如果不支持该协议,则抛出运行时异常** @param nameServiceUri 名称服务的URI,用于连接和解析* @throws RuntimeException 如果URI的协议不受支持,则抛出此异常*/@Overridepublic void connect(URI nameServiceUri) {// 检查URI的协议是否在支持的协议列表中if (schemes.contains(nameServiceUri.getScheme())) {// 如果协议受支持,则将URI转换为本地文件路径file = new File(nameServiceUri);} else {// 如果协议不受支持,则抛出异常throw new RuntimeException("Unsupported scheme!");}}/*** 注册服务,将服务名称和服务URI写入到文件中* 此方法是同步的,以确保并发访问时的数据一致性** @param serviceName 服务名称* @param uri 服务的URI* * @throws IOException 如果发生I/O错误*/@Overridepublic synchronized void registerService(String serviceName, URI uri) throws IOException {// 记录服务注册的日志信息logger.info("Register service: {}, uri: {}.", serviceName, uri);// 使用RandomAccessFile和FileChannel来读写文件,并确保资源在使用后能够正确关闭try (RandomAccessFile raf = new RandomAccessFile(file, "rw");FileChannel fileChannel = raf.getChannel()) {// 获取文件锁,以确保并发访问时的数据一致性FileLock lock = fileChannel.lock();try {// 获取文件长度,用于后续判断文件是否为空int fileLength = (int) raf.length();Metadata metadata;byte[] bytes;// 如果文件长度大于0,说明文件非空,读取并解析文件内容if (fileLength > 0) {bytes = new byte[(int) raf.length()];ByteBuffer buffer = ByteBuffer.wrap(bytes);// 循环读取文件内容到ByteBuffer中while (buffer.hasRemaining()) {fileChannel.read(buffer);}// 解析字节码为Metadata对象metadata = SerializeSupport.parse(bytes);} else {// 如果文件为空,创建一个新的Metadata对象metadata = new Metadata();}// 根据服务名获取或创建一个空的URI列表List<URI> uris = metadata.computeIfAbsent(serviceName, k -> new ArrayList<>());// 如果列表中不存在该URI,则添加进去if (!uris.contains(uri)) {uris.add(uri);}// 记录更新后的Metadata信息logger.info(metadata.toString());// 将Metadata对象序列化为字节码bytes = SerializeSupport.serialize(metadata);// 清空文件,为写入新的字节码做准备fileChannel.truncate(bytes.length);// 将文件指针移到文件开头,准备写入fileChannel.position(0L);// 将字节码写入文件fileChannel.write(ByteBuffer.wrap(bytes));// 强制将写入操作刷入磁盘fileChannel.force(true);} finally {// 释放文件锁lock.release();}}}/*** 根据服务名称查找服务的URI* 如果文件中存在对应的服务URI,则随机返回一个** @param serviceName 服务名称* @return 服务的URI,如果找不到则返回null* @throws IOException 如果发生I/O错误*/@Overridepublic URI lookupService(String serviceName) throws IOException {Metadata metadata;// 使用try-with-resources语句确保文件资源正确关闭try (RandomAccessFile raf = new RandomAccessFile(file, "rw");FileChannel fileChannel = raf.getChannel()) {// 获取文件锁以确保数据的一致性FileLock lock = fileChannel.lock();try {// 读取文件内容到字节数组byte[] bytes = new byte[(int) raf.length()];ByteBuffer buffer = ByteBuffer.wrap(bytes);// 循环读取直到文件末尾while (buffer.hasRemaining()) {fileChannel.read(buffer);}// 如果文件非空,则反序列化为Metadata对象,否则创建新的空Metadata对象metadata = bytes.length == 0 ? new Metadata() : SerializeSupport.parse(bytes);// 记录日志logger.info(metadata.toString());} finally {// 释放文件锁lock.release();}}// 从Metadata中获取服务的所有URIList<URI> uris = metadata.get(serviceName);// 如果没有找到对应的URI列表,返回nullif (null == uris || uris.isEmpty()) {return null;} else {// 随机选择一个URI返回return uris.get(ThreadLocalRandom.current().nextInt(uris.size()));}}
}
小结
- 面向接口编程:设计时面向接口编程,使得系统具有良好的扩展性,可以通过增加 SPI 插件方式扩展新的功能。
- 单机版注册中心:当前实现的是一个单机版的注册中心,通过本地文件共享元数据,不支持跨服务器调用。
- SPI机制:通过 SPI 机制,可以动态加载不同的
NameService
实现,支持多种协议的注册中心。
这种设计模式确保了系统的灵活性和可扩展性,为后续的功能扩展提供了便利。
相关文章:
![](https://i-blog.csdnimg.cn/direct/78488bc8a8d64c3e8c2b14f3ec6cec17.jpeg#pic_center)
Simple RPC - 06 从零开始设计一个服务端(上)_注册中心的实现
文章目录 Pre核心内容服务端结构概述注册中心的实现1. 注册中心的架构2. 面向接口编程的设计3. 注册中心的接口设计4. SPI机制的应用 小结 Pre Simple RPC - 01 框架原理及总体架构初探 Simple RPC - 02 通用高性能序列化和反序列化设计与实现 Simple RPC - 03 借助Netty实现…...
![](https://www.ngui.cc/images/no-images.jpg)
【深度学习】基于Transformers的大模型推理框架
本文旨在介绍基于transformers的decoder-only语言模型的推理框架。与开源推理框架不同的是: 本框架没有利用额外的开源推理仓库,仅基于huggingface,transformers,pytorch等原生工具进行推理,适合新手学习大模型推理流…...
![](https://i-blog.csdnimg.cn/direct/d7585aa78dc04f0e8c70d27db5031cf0.png)
电脑监控怎样看回放视频?一键解锁电脑监控回放,守护安全不留死角!高效员工电脑监控,回放视频随时查!
你是否曾好奇那些键盘敲击背后的秘密?电脑监控不仅是守护企业安全的隐形盾牌,更是揭秘高效与合规的魔法镜!一键解锁安企神监控回放,就像打开时间宝盒,让过去的工作瞬间跃然眼前。无论是精彩瞬间还是潜在风险࿰…...
![](https://i-blog.csdnimg.cn/direct/dff65b4d04c24307bd2d823a70f9c3b7.png#pic_center)
【一起学Rust | 框架篇 | Tauri2.0框架】tauri中rust和前端的相互调用(rust调用前端)
文章目录 前言1. rust中调用前端2. 如何向前端发送事件3. 前端监听事件4. 执行js代码 前言 近期Tauri 2.0 rc版本发布,2.0版本迎来第一个稳定版本,同时官方文档也进行了更新。Tauri是一个使用Rust构建的框架,可以让你使用前端技术来构建桌面…...
![](https://i-blog.csdnimg.cn/direct/2c8fe034e25144db876a5f1a5665a38a.png)
deque容器
deque容器的基本概念 deque 是 C 标准库中的双端队列(double-ended queue)容器,提供了在两端进行插入和删除操作的功能。 deque与vector区别: vector对于头部的插入删除效率低,数据量越大效率越低。deque相对而言&am…...
![](https://www.ngui.cc/images/no-images.jpg)
Redis远程字典服务器(9)—— 类型补充
类型查询传送门:Understand Redis data types | Docs 一,stream类型 官方文档对于这个类型的解释是:streams是一个数据结构,它表现得像一个 “append-only log”,就是只能往后面添加,底层是字符串&#x…...
![](https://i-blog.csdnimg.cn/direct/93c47cde17c54e1fb852a196eba263a5.png)
VMware虚拟机nat无法联通主机
VMware在nat模式下主机无法ping通虚拟机 原因: 虚拟机和对应的网卡不在一个网段 虚拟机开启了防火墙 解决方法: 首先判断虚拟机的网络ip是否和网卡在一个网段上 判断虚拟机使用的网卡 nat模式在VMware虚拟机中一般只有一个对应的网卡 如图笔者的nat网卡为VM…...
![](https://i-blog.csdnimg.cn/direct/0f9f4736f3904b6ab021b25011fe96be.png)
「字符串」详解AC自动机并实现对应的功能 / 手撕数据结构(C++)
目录 前置知识 概述 核心概念:fail指针 作用 构建 图示 Code 成员变量 创建销毁 添加词库 文本扫描 复杂度 Code 前置知识 在此前,你应该首先了解trie树(字典树)的概念: 「字符串」详解Trie࿰…...
![](https://i-blog.csdnimg.cn/direct/add618b7faec4e3387468eb64d0eb673.png)
freecad遭遇网络不同无法安装插件Addon Manager: Unexpected 0 response from server
16:31:18 Addon Manager: Unexpected 0 response from server 16:31:18 Failed to connect to GitHub. Check your connection and proxy settings. 打开freecad的插件管理器时候,有些地方,比如我在家里就不行,在公司就ok。 于是找到了解…...
![](https://www.ngui.cc/images/no-images.jpg)
Ruby模板引擎:构建动态视图的艺术
标题:Ruby模板引擎:构建动态视图的艺术 在Ruby on Rails的世界里,模板引擎是构建动态网页的基石。它们允许开发者将服务器端的逻辑嵌入到HTML中,实现数据的动态展示。本文将深入探讨Ruby中几种常用的模板引擎,包括ERB…...
![](https://i-blog.csdnimg.cn/direct/37029b3f7062447f93db6b577755634a.png)
HarmonyOS NEXT星河版零基础入门(3)
目录 1. 系统弹出框 2.interface转成class类 3.vp/fp 4. 写一个正方形 设置它的宽度 但不设定高度 不论屏幕怎么变实现他的宽高比 5.State 6.图片和资源 7.淘宝镜像 7.1windows 脚本禁用(操作策略 允许npm包的命令可执行) 8. es6&ArkTS中…...
![](https://www.ngui.cc/images/no-images.jpg)
第二十讲 python中的异常结构-try except-else-finally
目录 1.try... except 结构 2. try... 多个except结构 3. try...except...else结构 4. try...except...finally结构 5. return语句和异常处理问题 5.1 异常处理前的 return 5.2异常处理后的 return 5.3 finally 块中的 return 6.常见的异常 1.try... except 结构 try except 是…...
![](https://i-blog.csdnimg.cn/direct/e823c97958164b32a3d53944d0a5e602.png)
springer 投稿系统中返修注意点
初次提交 初次提交时, manuscript 提交的是 pdf 文件 返修后提交 在经过返修之后需要提交的是注意一下几点: 此时提交的Blined manuscript ,虽然名字没变,但不能再提交pdf 文件, 而需要提交的是可编辑的源文件 .te…...
![](https://www.ngui.cc/images/no-images.jpg)
CSS:display和visiblity
隐藏元素- display:none和visibility:hidden display 属性设置一个元素应如何显示,visibility 属性指定一个元素应可见还是隐藏。 隐藏一个元素可以通过吧display属性设置为“none”,或者把visibility属性设置为“hidden”。但是这两种会产生不同的结果…...
![](https://i-blog.csdnimg.cn/direct/5fda22f45dcb433488d60e260fe66350.png)
43.x86游戏实战-XXX寻找吸怪坐标
免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 本次游戏没法给 内容参考于:微尘网络安全 工具下载: 链接:https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd6tw3 提…...
![](https://www.ngui.cc/images/no-images.jpg)
Redis地理位置相关应用
下面是一个结合 MySQL 数据库和 Redis 的地理位置服务示例,包含表结构、PHP 代码和 Redis 操作,用于处理基于地理位置的数据存储和查询。 1. 创建 MySQL 数据库表 首先,创建一个用于存储位置信息的 MySQL 表,如下所示࿱…...
![](https://i-blog.csdnimg.cn/direct/f69ed7f1ba5e4405861207252c3d5dac.png)
优化WAN流量:如何通过调整系统设置降低企业网络成本
一、症状与问题背景 当电脑显示空闲状态时,如果满足以下条件,第二拨号链接可能会意外激活: 您正在使用基于 Microsoft Windows 的计算机,该计算机连接到远程网络并且是 Active Directory 域服务 (AD DS) 域的成员。 您通过二级…...
![](https://www.ngui.cc/images/no-images.jpg)
Java-HttpHeaders请求头或响应头
HttpHeaders 是 Spring Framework 中的一个类,用于封装 HTTP 头部信息。它提供了一种方便的 方式来设置 HTTP 请求头和处理 HTTP 响应头。下面分别介绍如何使用 HttpHeaders 来设置请求 头和处理响应头。 设置请求头 在发送 HTTP 请求时,可以通过 HttpHeaders 设置各种请…...
![](https://www.ngui.cc/images/no-images.jpg)
Elasticsearch高阶查询
Elasticsearch高阶查询 文章目录 Elasticsearch高阶查询相关性和相关性算分相关性 (Relevance)什么是TF-IDFBM25explain关键字Boosting如何通过Boost控制想要的文档排在前面? 布尔查询(bool Query)查询语法语法格式 单字符串多字段查询三种场…...
![](https://i-blog.csdnimg.cn/direct/2ba18cfeacee46bd8459f25ed03539fc.png)
【流媒体】RTMPDump—RTMP_Connect函数(握手、网络连接)
目录 1. RTMP_Connect函数1.1 网络层连接(RTMP_Connect0)1.2 RTMP连接(RTMP_Connect1)1.2.1 握手(HandShake)1.2.2 RTMP的NetConnection(SendConnectPacket) 2.小结 RTMP协议相关&am…...
![](https://www.ngui.cc/images/no-images.jpg)
通过https方式访问内网IP
单位要做个用浏览器扫二维码的功能。我先在本地测试一直不成功,后来放到服务器上运行成功了。比较了一下,服务器上是https,但是本地没有证书。我问了一下信安的同事,要求二维码必须在本地扫描,不能上公网。所以只好在本…...
![](https://www.ngui.cc/images/no-images.jpg)
flutter 键盘弹出 都会重新Build
原因是调用MediaQuery.of(context)后,点击TextField组件时会导致调用build方法。 解决方法:在Scaffold组件的body嵌套Builder组件,然后设置一个BuildContext变量,将Builder组件中的context传递给BuildContext变量,然后…...
![](https://www.ngui.cc/images/no-images.jpg)
RedisDistributedLock 分布式锁
设计一个简单的 RedisDistributedLock 类,实现单例模式,并包含基本的锁定机制。这个类将使用 Redis 来管理锁,确保在分布式系统中资源的同步访问 import redis.clients.jedis.Jedis;public class RedisDistributedLock {private static Redi…...
![](https://i-blog.csdnimg.cn/direct/549cb3b0c7fe4c85a3d06a004dc4a8eb.png)
Java之包装类
Java中的包装类(Wrapper Classes)是基本数据类型的对象包装类。Java为每个基本数据类型(如int、char等)提供了对应的包装类,使得基本类型可以被当作对象来处理。这些包装类位于java.lang包中。 包装类的用途 对象化&a…...
![](https://i-blog.csdnimg.cn/direct/9cf11cf3c4f84335ae7db200a78dda89.png)
Linux - 权限
文章目录 一、用户二、文件 一、用户 1、Linux下有两种用户:超级用户(root)、普通用户。 超级用户:可以再linux系统下做任何事情,不受限制 。 普通用户:在linux下做有限的事情。 超级用户的命令提示符是“…...
![](https://i-blog.csdnimg.cn/direct/0fe5db714ccf411fa740872d9619a2c7.png)
免费图形化nginx管理工具nginxWebUI
nginxWebUI是一款图形化管理nginx配置得工具, 可以使用网页来快速配置nginx的各项功能, 包括http协议转发, tcp协议转发, 反向代理, 负载均衡, 静态html服务器, ssl证书自动申请、续签、配置等, 配置好后可一建生成nginx.conf文件, 同时可控制nginx使用此文件进行启动与重载, 完…...
![](https://www.ngui.cc/images/no-images.jpg)
编程上的挫折不可怕,可怕的是你畏惧了
如何克服编程学习中的挫折感 编程学习之路上,挫折感就像一道道难以逾越的高墙,让许多人望而却步。然而,真正的编程高手都曾在这条路上跌倒过、迷茫过,却最终找到了突破的方法。那么,我是如何在Bug的迷宫中找到出口的&…...
![](https://www.ngui.cc/images/no-images.jpg)
docker逃逸手法
docker逃逸手法 基本docker操作docker 命令dockerfilesDocker Compose漏洞利用容器漏洞 基本docker操作 docker 命令 # docker拉取 docker pull # 指定版本拉取 docker pull ubuntu:22.04# 显示镜像可执行的操作 docker image # 列出存储在本地系统上的所有图像 docker image…...
![](https://i-blog.csdnimg.cn/direct/d3f10a2ad4e8428ca5b0051f327d7a2e.png)
3 pytest Fixture
3 pytest Fixture 3.1 通过 conftest.py 共享 fixture3.2 使用 fixture 执行配置及销毁逻辑3.3 使用 --setup-show 回溯 fixture 的执行过程3.4 使用 fixture 传递测试数据3.5 使用多个 fixture3.6 指定 fixture 作用范围3.7 使用 usefixtures 指定 fixture3.8 为常用 fixture …...
![](https://i-blog.csdnimg.cn/direct/1970990be04948acbf674f7de0737f90.png)
pinctl 和 gpio子系统驱动
一.设备树中添加pinctl节点模板 1.创建对应的节点 同一个外设的 PIN 都放到一个节点里面,打开 imx6ull-14x14-evk.dts,在 iomuxc 节点 中的“imx6ul-evk”子节点下添加 “pinctrl_test” 节点。添加完成以后如下所示: pinctrl_test:test_g…...
flash网站素材下载/永久免费用的在线客服系统
内核:3.3 平台:rlx 涉及的主要文件有 include/linux/clk.h drivers/clk/clkdev.c drivers/clk/clk.c arch/rlx/bsp/clock.c 1、 clk通用接口 内核定义了一套标准的接口(include/linux/clk.h),用于所有的平台之上。每个时钟源对象使用…...
![](/images/no-images.jpg)
艺术设计教学资源网站建设标准/世界球队最新排名
一、处理JSON 1、将JavaScript数据转换为JSON对象(序列化) JSON.stringify(Object)2、将JSON数据转换为JavaScript对象(逆序列化) JSON.parse(stringJSON)二、Buffer模块缓冲数据(使用两位16进制表示一字节) 1、创建缓冲区 Buffer.from(array): returns …...
![](https://img-blog.csdnimg.cn/e09f30ed07ff493f97ea55adf212def6.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6LWk6bG856eR5oqA,size_20,color_FFFFFF,t_70,g_se,x_16)
wordpress wiki/深圳知名seo公司
一、硬件材料 1*Arduino NANO开发板 1*模块MQ-2烟雾气敏传感器模块 1*传感器模块 L9110风扇模块 1*加湿器USB喷雾模块 二、硬件接线图...
做公司网站麻烦吗/潍坊网站建设解决方案
在看到了mongoTemplate的操作之后,觉得这种东西是很符合我们程序员世界的操作的,但是看到mysql的jdbc之后,瞬间一百万个小泥马从头飘过,所以就想自己实现一个mysql版本的upsert功能,有set与increase,decrease。实现操作…...
![](https://img-blog.csdnimg.cn/img_convert/e8d178f76d871751a85eead500f20dce.gif)
商务网站建设实验书/怎样交换友情链接
作者:蓝笔头链接:https://www.jianshu.com/p/f3e64e70eb1b1. 排序1.1 数组排序(java.util.Arrays)1.1.1 基本数据类型排序对整个数组排序public static void sort(int[] a);对部分数组 [fromIndex, toIndex) 排序public static vo…...
![](https://img-blog.csdnimg.cn/20210129094144592.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMzMyNTcw,size_16,color_FFFFFF,t_70)
网站服务器cpu占用多少要升级/做网站优化哪家公司好
目录 Java对象内存分配流程 1. 流程介绍 2. 什么是逃逸分析 1.为什么要分配在栈上? 2.什么情况下会分配在栈上? 3.什么是逃逸分析 3.什么是大对象 4.什么是TLAB Java对象内存分配流程 1. 流程介绍 1.执行new指令 2.进行逃逸分析,判…...