目录
1. 介绍
2. 实践
2.1. 启动消费者
2.2. 启动生产者
1. 介绍 RocketMQ是一个开源的分布式消息传递系统,最初由阿里巴巴集团开发并于2012年开源。它旨在解决高可靠性、高吞吐量、低延迟和可伸缩性等大规模分布式系统下的消息通信需求。
RocketMQ的设计目标是提供一种灵活、可靠、高性能的消息传递解决方案,适用于各种场景,包括在线消息通信、日志处理、流式处理、事件驱动架构等。
下面是对RocketMQ的主要特点和关键功能的简要介绍:
分布式架构:RocketMQ采用了分布式架构,支持水平扩展和高可用性。它的架构包括多个消息生产者、多个消息消费者和多个消息服务器(Broker)。消息生产者将消息发送到Broker,消息消费者从Broker订阅并消费消息。
高可靠性和容错性:RocketMQ通过复制和故障转移机制,提供高可靠性和容错性。它支持主从同步复制和异步复制方式,确保消息不会丢失,并且在Broker故障时能够自动切换到备用Broker。
高吞吐量和低延迟:RocketMQ通过优化存储、网络和消息传递等方面的性能,实现高吞吐量和低延迟。它支持批量发送和批量消费消息,有效地减少网络开销和提高消息处理效率。
灵活的消息模型:RocketMQ支持多种消息模型,包括点对点(P2P)和发布-订阅(Pub-Sub)模型。在P2P模型中,消息生产者直接发送消息给特定的消费者;在Pub-Sub模型中,消息生产者发布消息到特定的主题(Topic),消息消费者订阅感兴趣的主题并接收相应的消息。
丰富的消息过滤和顺序消息支持:RocketMQ提供灵活的消息过滤功能,可以根据消息的属性、标签或SQL表达式进行过滤。此外,它还支持顺序消息,确保相同主题的消息按照发送顺序被消费。
可伸缩性和扩展性:RocketMQ具有良好的可伸缩性和扩展性,可以根据需求增加或减少Broker、生产者和消费者的数量,以适应不断增长的消息流量。
丰富的生态系统和社区支持:RocketMQ拥有活跃的开源社区,提供了丰富的文档、示例和工具。此外,它还与其他开源项目(如Apache Storm、Apache Flume、Apache Flink等)集成,为用户提供更多选择和灵活性。
总之,RocketMQ是一个功能强大的分布式消息传递系统,具有高可靠性、高吞吐量、低延迟和可伸缩性等特点。它适用于构建大规模分布式系统中的消息通信基础设施,为开发者提供了一种可靠、高效的消息传递解决方案。
2. 实践 注意:以下配置需从阿里云 RocketMQ 获取
HTTP_ENDPOINT = "xxx"
ACCESS_KEY = "xxx"
SECRET_KEY = "xxx"
TOPIC = "xxx"
GROUP_ID = "xxx"
INSTANCE_ID = "xxx"
2.1. 启动消费者 """ The code was copied from this link https://help.aliyun.com/zh/apsaramq-for-rocketmq/cloud-message-queue-rocketmq-4-x-series/developer-reference/send-and-subscribe-to-transactional-messages-2?spm=a2c4g.11186623.0.0.4b6f8707cKp9eN """ from mq_http_sdk.mq_exception import MQExceptionBase from mq_http_sdk.mq_consumer import * from mq_http_sdk.
一、创建keystore签名文件 1、在菜单栏中,依次点击 Build - Generate Signed Bundle/Apk...(生成签名)
2、选择 APK 选项,点击按钮 Next 到下一步
3、新建key store秘钥文件,点击按钮 Next 到下一步
4、按如下提示填写信息,点击按钮 Next 到下一步
5、签名生成完成,勾选记住密码,方便下次打包
6、勾选签名效验方式,选择要打包的环境,点击按钮 Next 开始打包
7、见到如下提示,说明打包成功
二、获取签名文件的配置信息 终端执行如下命令:
keytool -list -v -keystore 你的keystore文件的绝对路径
输入 keystore 的密码后,就可以在终端上看到 keystore 签名文件的配置信息了,如下图所示
三、项目中配置签名信息 1、在菜单栏中,依次点击 File - Project Structure
2、依次点击 Module - app - Signing Configs - +,然后添加刚才生成的正式签名
3、点击Apply ,再点击ok,完成添加配置
4、点击按钮 ok 后,Android Studio 会自动在app模块的build.gradle中添加签名信息,如下图所示
5、签名配置成功后,把签名文件和环境关联,参照1流程,在Build Types里面进行设置
四、验证签名是否成功 方法一(keytool,只支持V1签名校验) 进入JDK/bin, 输入命令 keytool -printcert -jarfile xxx.apk (显示签名证书信息) 参数: -printcert 打印证书内容 -jarfile <filename> 已签名的jar文件 或apk文件 方法二(apksigner,支持V1和V2签名校验) 进入Android SDK/build-tools/SDK版本, 输入命令 apksigner verify -v --print-certs xxx.
目录
一、前言
二、 深度理解vector 的二维数组(重点!)
三、vector 二维数组的空间理解(重点!)
✨问题分析
✨如何合理定制vector的内存空间
四、vector 二维数组的初始化
五、vector 二维数组的 添加与删除
✨添加一行
✨添加一列
✨删除一行
✨删除一列
六、常考面试题
七、共勉
一、前言 最近在刷 Leetcode 的时候,发现 vector 的二维数组操作 都还没弄明白吗,但是STL的强大是众所周知滴,早晚都是要解决滴,因此专门写下这篇文章,以供自己复习和各位老铁使用,快速的回忆vector的用法,让你找回自信,不用再竞赛的时候颜面尽失。
vector 的一维操作可以看看之前这篇文章哦:vector 详解
二、 深度理解vector 的二维数组(重点!) 在解决大部分算法问题的时候,通常都会遇到二维数组 vector<vector<int>> table, 但是不知道怎么对其进行初始化(初始化时指定二维容器的大小),于是通过查阅了很多资料,将其总结如下:
vector<vector<int>> table(size1, vector<int>(size2, 0)); 代码说明:声明一个名为 table 的容器,其元素为 vector的容器。简单来说类似一个int型的二维数组。
这样,就得到了一个如下图所示的二维容器。 具体代码的内容,可以这样理解:
图中,我将外围容器table的初始化参数分成了两部分 A、B A: table外围容器的大小B: table外围容器的内容,即 size1个vector型的元素。B1:内部容器的大小B2:内部容器的内容 观察规律,可以得出如下的初始化格式:容器(大小,内容)
三、vector 二维数组的空间理解(重点!) 我们都知道,在 C语言 中,创建一维数组或者更高维度的数组时,都是需要提前给他分配大小的。
而在 C++的 vector 容器 中我们并不需要那么做,我们可以直接push进去后,根据下标访问它,如:
✨问题分析 vector<int> a; a.push_back(1); cout << a[0]; 由此处诞生出了两个问题:
项目编译工具:Gradle 8.2开发工具: Idea开发语言: 建议java17以上ui组件:openjfx (org.openjfx.javafxplugin)打包工具: jpackage (org.beryx.jlink)如果打包出现错误,可以安装wix(3.1以上) + dotnetfx(3.5以上) 试试看 一、如何解决打包问题 java 14以后,有了jpackage工具,能够很方便的打包成exe,msi,dmg等包了。
如果有java环境的机器,可以使用launch4j进行打包(可以指定支持的运行时java环境版本min~max, 参考 https://github.com/charlydang/RestartApplicationButton), 可参考maven插件https://github.com/orphan-oss/launch4j-maven-plugin,这种方式打的包体积很小,但是需要运行的系统安装了对应的jvm环境才好。jpackage更适合没有java环境的机器,可以运行在任何一台机器上。
试了Maven项目的javafx-maven-plugin插件,发现没法打包成可安装的包exe或者msi。
最终选择了gradle管理项目(打包插件:badass-jlink-plugin),如果有idea最新版的话,新建JavaFx、gradle的项目默认用的就是这个插件。不过要稍微改下配置。具体参数配置可以查看github: https://github.com/beryx/badass-jlink-plugin, readme里有介绍几个例子。我是参考这个例子https://github.com/beryx-gist/badass-jlink-example-log4j2-javafx进行的配置。也可以看看这个项目,挺不错的(地址 https://github.com/gleidsonmt/DashboardFx)。
plugins { id 'java' id 'application' id 'org.javamodularity.moduleplugin' version '1.8.12' id 'org.openjfx.javafxplugin' version '0.0.13' id 'org.beryx.jlink' version '2.25.0' } group 'com.example' version '1.0' repositories { mavenCentral() } ext { junitVersion = '5.9.1' } sourceCompatibility = '17' targetCompatibility = '17' dependencies { implementation('org.apache.logging.log4j:log4j-core:2.11.1') testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}") } tasks.withType(JavaCompile) { options.
在代码中有如下代码结构:
//... public class MainActivity extends AppCompatActivity implements View.OnClickListener { //... @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_add: //添加数据 break; case R.id.btn_query: //查询数据 break; case R.id.btn_update: //修改数据 break; case R.id.btn_delete: //删除数据 break; } } //... } 出现如下报错:
Constant expression required 解决方法:
在根目录下的 gradle.properties 中添加 android.nonFinalResIds=false 就可以了
一、深入理解递归 二、递归vs迭代 三、深入理解搜索、回溯和剪枝 四、汉诺塔问题 . - 力扣(LeetCode)
class Solution { public: //笔试题,不讲武德,C=A void move(int n,vector<int>& A, vector<int>& B, vector<int>& C)//实现从a经过b这个辅助盘子移到c { //设置函数出口 if(n==1) //此时不能再分割子问题了 直接给C即可 { C.push_back(A.back()); A.pop_back(); return; } //先把a的前n-1个通过c移到b move(n-1,A,C,B); //然后将A的最后一个盘子移到C上 C.push_back(A.back()); A.pop_back(); //然后将b上的n-1个盘子通过A移到c move(n-1,B,A,C); } void hanota(vector<int>& A, vector<int>& B, vector<int>& C) { int n=A.size(); return move(n,A,B,C); } }; 五、合并两个有序链表 . - 力扣(LeetCode)
class Solution { public: ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { if(list1==nullptr) return list2; else if(list2==nullptr) return list1; else if(list1->val<list2->val) {list1->next=mergeTwoLists(list1->next,list2);return list1;} else {list2->next=mergeTwoLists(list2->next,list1);return list2;} } }; 六、反转链表 .
Live2D虚拟人物应用(前端vue3) 1.所需技术
Vue3+ts
Live2D官方SDK
pixi.js@6.x pixi-live2d-display 两个库
2.Live2D官方SDK
下载地址:https://www.live2d.com/en/sdk/about/ (需翻墙)
前端SDK需对应web选项
下载文件:
下载解压后将CubismSdkForWeb-4/Core/live2dcubismcore.min.js此文件复制到public文件夹中
并在index.html中引用
3.引用两个库
4.准备好live2d资源 一般设计师会给到一个文件夹,里面包含了一堆json,里面的.model3.json是live2d模型的入口文件。把这个文件夹放到项目的public目录,因为打包后它会出现在dist/下,到时候需要能够引用到。(ps:实在迷茫的小伙伴可以去B站买一个live2D有一分钱的)
5.代码层面
在template标签中定义canvas标签
Script标签中引用vue方法和相应文件,定义变量
获取live2d模型调用PIXI.js在页面进行渲染
关于PIXI.js的方法可以参考相关博客:
https://www.cnblogs.com/huangqian/p/17626223.html
5. live2D模型动作表情
这里我只做了按钮形式的表情切换和动作执行
表情方法
model.expression 方法用于切换虚拟人物表情执行文件 type参数名称与Expressions数组对象中每个对象Name属性对应(其实就是事件执行切换对应json文件)
动作方法
model.motion方法用于切换虚拟人物动作执行文件
这里要注意model.motion方法参数 第一个参数:
第二个参数就是数组对象的索引
6.启动项目
npm启动你的vue3项目就可以看到成果了
20240408_095201
拓展应用 live2D模型实际应用场景不单单只有网页看板娘实际上还可以用作直播中的虚拟形象通过steam特定软件导入live2D面部捕捉软件实现二次元虚拟直播
教学视频干货在这,但前提是你要准备好你的模型文件
【vup教程】5分钟学会!面捕VTS!推流OBS!(拓展ios)_哔哩哔哩_bilibili
更多基于live2D的桌面移动端可以去B站或者CSDN上找相应的视频或博客
本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 郭霖 即可关注,每个工作日都有文章更新。
今天这篇文章给大家介绍一下Android 14系统中的一个新特性,对部分照片和视频进行访问授权,也可以称之为选择性照片和视频访问授权。
这是Android系统在隐私和安全性方面的又一次调整升级,目的是为了能够更好地保护用户隐私。
但是这个新特性对于开发者而言,真的是让我们苦上加苦,因此我会边吐槽边来讲解这个最新的特性。
Android本地读写权限变更史 Android开发者很苦。
我会全面介绍一下Android系统从诞生至今,在本地读写权限方面的完整变更史,然后大家应该能对Android开发者的苦感同身受。
本地读写权限指的是App拥有对手机外置公共存储空间(SD卡)读取和写入的能力。
Android 1.0 远古时代的Android系统对于权限方面是非常宽松的。
当然这个时代的Android手机我自己都没有用过,那个时候据说对于本地读写功能是没有任何限制的,任何一个App都可以随意读写整个手机的公共存储空间。
Android 1.6 很明显,如此宽松的权限设计是有问题的,于是Android 1.6系统引入了WRITE_EXTERNAL_STORAGE权限。
如果你想要向手机的公共存储空间写入数据,那么就得在你的应用程序的AndroidManifest.xml文件中声明这个权限才行。
Android 4.4 Android 1.6系统只是对写入公共存储空间有了限制,读取公共存储空间的文件仍然是不受限制的。
那么从Android 4.4开始,Google引入了READ_EXTERNAL_STORAGE权限。如果想要读取公共存储空间的文件,就需要在AndroidManifest.xml文件中声明这个权限才行。
Android 6.0 之前的Android系统,如果你想要使用某个权限,只需要在AndroidManifest.xml文件中声明一下就行。
这个声明起到什么作用呢?它会在App安装的时候告知用户,这个App总共申请了哪些权限,如果继续安装的话即视为用户同意了所有这些权限的申请。
这个规则属实有点霸王条款,因为用户无法部分同意该App申请的权限。
于是在Android 6.0系统中,Google引入了运行时权限功能,某些危险程度高的权限不能再像之前那样在AndroidManifest.xml文件中声明一下就行了,而是要在App运行的过程中弹出权限申请框,只有用户同意了授权,才能使用其权限对应的功能。
READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE都被划入了运行时权限的范畴。
关于运行时权限的更多内容,可以参考《第一行代码 Android 第3版》第8章。
Android 10 运行时权限机制引入之后,Android系统的隐私和安全性达到了一个新的高度,因此也让本地读写权限在相当长的一段时间里保持了比较稳定的用法。
不过从Android 10系统开始,Google不满足于现状,又开始大刀阔斧地改革了,并且后面的改动频率让人瞠舌。
Android 10引入了Scoped Storage机制,App被禁止使用绝对路径访问公共存储空间。这样,用户设备上的隐私信息可以得到更好的保护。
而诸如手机照片、视频、音频之类的公共型资源,如果App想要访问的话,可以需要借助MediaStore API来完成。
App通过MediaStore API写入照片、视频、音频等公共型资源,是不需要申请任何权限的。而App通过MediaStore API读取照片、视频、音频等公共型资源,仍需要申请READ_EXTERNAL_STORAGE权限才行。
由于Scoped Storage机制变动过大,Google怕大量App来不及适配,因此提供了一个requestLegacyExternalStorage属性。将这个属性设置为true,那么App仍然可以使用绝对路径访问公共存储空间。
关于Android 10更多的行为变更,可以参考 Android 10适配要点,作用域存储 这篇文章。
Android 11 给了一年的缓冲期,Google认为绝大部分应用应该都已经完成了Scoped Storage的适配,因此从Android 11开始requestLegacyExternalStorage属性将不再起作用。
另外,考虑到有些文件浏览器类型的App的确需要使用绝对路径访问公共存储空间,Android 11又添加了一个MANAGE_EXTERNAL_STORAGE权限,但仅限特定确实有需求的App申请,随便申请的话可能会被Google Play商店下架。
关于Android 11更多的行为变更,可以参考 Android 11新特性,Scoped Storage又有了新花样 这篇文章。
在 Python 中,pip 是一个包管理工具,用于安装和管理 Python 包。设置成国内源可以加快包的下载速度,常用的国内源包括阿里云源和清华大学源。下面是设置 pip 源为阿里云源和清华大学源的方法:
命令行方式 设置 pip 源为阿里云源: 首先,打开命令行窗口。
输入以下命令设置 pip 源为阿里云源:
pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ 这样就成功将 pip 源设置为阿里云源了。 设置 pip 源为清华大学源: 打开命令行窗口。
输入以下命令设置 pip 源为清华大学源:
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple 这样就成功将 pip 源设置为清华大学源了。 现在,你可以通过这两种方式来将 pip 源设置成国内源,以加快包的下载速度。
完整示例: 下面是一个示例 Python 脚本,演示了如何使用 requests 包从指定 URL 获取内容:
import requests url = 'https://www.example.com' response = requests.get(url) if response.status_code == 200: print('成功获取网页内容:') print(response.text) else: print('获取网页内容失败。') 你可以运行这段代码来获取指定网页的内容。请确保安装了 requests 包,如果没有安装,可以使用以下命令进行安装:
当使用C#中的ComboBox控件时,你可以通过以下详细方法使用它:
在窗体上放置 ComboBox 控件:
在 Visual Studio 的窗体设计器中,从工具箱中拖动并放置一个 ComboBox 控件到你的窗体上。
设置 ComboBox 的属性:
Items:用于设置或获取 ComboBox 中的选项集合。你可以通过添加项到集合中来动态添加选项。Text:用于设置或获取当前选中项的文本。SelectedIndex:用于设置或获取当前选中项的索引。索引从 0 开始,-1 表示没有选中项。DropDownStyle:用于设置下拉列表的样式。常用的值有: DropDown:显示下拉列表,用户可以从中选择。DropDownList:只显示下拉列表,用户无法手动输入。 处理 ComboBox 的事件:
SelectedIndexChanged:当 ComboBox 的选中项发生改变时触发的事件。你可以通过订阅该事件,在选中项改变时执行特定的操作。 下面是一个示例,演示如何使用 ComboBox 控件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
0代表producer往集群发送数据不需要等到集群的返回,不确保消息发送成功。安全性最低但是效率最高。1代表producer往集群发送数据只要leader应答就可以发送下一条,只确保leader发送成功。all代表producer往集群发送数据需要所有的follower都完成从leader的同步才会发送下一条,确保leader发送成功和所有的副本都完成备份。安全性最高,但是效率最低。 最后要注意的是,如果往不存在的topic写数据,能不能写入成功呢?kafka会自动创建topic,分区和副本的数量根据默认配置都是1。
此外,对于某些业务场景,设置max.in.flight.requests.per.connection=1会严重降低吞吐量,如果放弃使用这种同步重试机制,则可以考虑在消费端增加失败标记的记录,然后用定时任务轮询去重试这些失败的消息并做好监控报警。
Kafka的多副本机制 Kafka为分区(Partition)引入多副本(Replica)机制,分区(Partition)中的多个副本中有一个leader,其余称为leader的follower。我们的消息发送到leader副本,然后follower副本才能从leader副本中拉取消息进行同步。
Kafka的follower从leader同步数据的流程 初始同步请求:当一个新的follower加入集群或者现有的follower与leader失去连接后重新连接时,follower会向leader发送一个初始同步请求(Initial Fetch Request),请求获取最新的数据。获取偏移量信息:leader响应这个请求,发送给follower最新的日志文件(log file)名称和偏移量(offset)。这告诉follower从哪个位置开始拉取数据。数据拉取:根据从leader获取的偏移量信息,follower开始从leader拉取数据。这些数据通常是leader日志文件中的一部分或全部内容。写入本地副本:follower在接收到数据后,会将这些数据写入自己的本地副本中。这确保了即使leader发生故障,follower也有完整的数据副本。提交偏移量:一旦数据写入完成,follower会向leader发送一个确认消息,告知已经成功写入的偏移量。这个确认是Kafka复制协议的一部分,确保leader知道哪些数据已经被follower成功接收和写入。持续同步:在初始同步之后,follower会持续地监听leader的日志变化。每当leader有新的数据写入时,follower都会按照上述流程拉取并写入这些数据。故障恢复和选举:如果leader发生故障,Kafka集群中的其他节点(通常是follower)会通过ZooKeeper进行选举,选出一个新的leader。选举成功后,新的leader会继续接受生产者的写入请求,并同步数据到其他的follower。日志截断:在某些情况下,如删除旧的topic分区或执行日志压缩时,leader可能会截断其日志文件。当这种情况发生时,leader会通知所有的follower进行相同的截断操作,以确保所有副本的一致性。 整个同步流程是异步的,并且设计得足够高效,以便在Kafka集群中处理大量的数据和高并发的读写操作。此外,Kafka还通过一系列的优化手段(如批量拉取、压缩传输等)来减少同步过程中的网络开销和延迟。
Kafka的follower为什么不能用于消息消费 对于消息的消费,Kafka采用的是生产者-消费者模式。在这个模式中,生产者将消息写入Kafka的leader分区,而消费者则从leader分区拉取消息进行消费。Kafka通过移交偏移量来控制消费者从哪个位置开始消费消息,从而使得消费者可以按照一定的顺序消费消息。Kafka的设计是基于分布式的,所有的读写操作都是在leader分区进行的,follower分区则主要负责从leader同步数据。从而保证分布式环境中数据的一致性和可靠性。 Kafka的多分区(partition)以及多副本(Replica)机制的作用 Kafka 通过给特定 Topic 指定多个 Partition, 而各个 Partition 可以分布在不同的 Broker 上, 这样便能提供比较好的并发能力(负载均衡)。Partition 可以指定对应的 Replica 数, 这也极大地提高了消息存储的安全性, 提高了容灾能力,不过也相应的增加了所需要的存储空间。 Kafka和Zookeeper的关系 Zookeeper主要为Kafka提供元数据的管理的功能。
Broker注册:在 Zookeeper 上会有一个专门用来进行 Broker 服务器列表记录的节点。每个 Broker 在启动时,都会到 Zookeeper 上进行注册,即到 /brokers/ids 下创建属于自己的节点。每个 Broker 就会将自己的 IP 地址和端口等信息记录到该节点中去Topick注册:在 Kafka 中,同一个Topic 的消息会被分成多个分区并将其分布在多个 Broker 上,这些分区信息及与 Broker 的对应关系也都是由 Zookeeper 在维护。比如我创建了一个名字为 my-topic 的主题并且它有两个分区,对应到 zookeeper 中会创建这些文件夹:/brokers/topics/my-topic/Partitions/0、/brokers/topics/my-topic/Partitions/1。负载均衡:对于同一个 Topic 的不同 Partition,Kafka 会尽力将这些 Partition 分布到不同的 Broker 服务器上。当生产者产生消息后也会尽量投递到不同 Broker 的 Partition 里面。当 Consumer 消费的时候,Zookeeper 可以根据当前的 Partition 数量以及 Consumer 数量来实现动态负载均衡。 在Kafka2.
因为我们的版本选择的纯净版,所以需要在 Spark 环境文件中指定已经安装的 Hadoop 路径。
cd $SPARK_HOME/conf
mv spark-env.sh.template spark-env.sh
vim spark-env.sh
在该文件末尾添加,指定 Hadoop 路径:
export SPARK_DIST_CLASSPATH=$(hadoop classpath)
添加完成之后,保存并退出。
其中 $(hadoop classpath) 的作用是获取 Hadoop 类路径的值 (需要提前配置 Hadoop 的环境变量,否则获取不到) ,我们可以直接打印看看它存储的内容:
在 Hive 配置 Spark 参数 进入 Hive 的 conf 目录中,创建 Spark 配置文件,指定相关参数。
cd $HIVE_HOME/conf
vim spark-default.conf
添加如下配置内容:
指定提交到 yarn 运行 spark.master yarn
开启日志并存储到 HDFS 上 spark.eventLog.enabled true
spark.eventLog.dir hdfs://hadoop120:8020/spark-logDir
指定每个执行器的内存 spark.executor.memory 1g
指定每个调度器的内存 spark.driver.memory 1g
配置文件创建完成后,在 HDFS 上创建 Spark 的日志存储目录。
假设我们上下游的速度不匹配,上游发送速率为 2,下游接收速率为 1,可以看到图上在 ResultSubPartition 中累积了两条消息,10 和 11, backlog 就为 2,这时就会将发送的数据 <8,9> 和 backlog = 2 一同发送给下游。下游收到了之后就会去计算是否有 2 个 Buffer 去接收,可以看到 InputChannel 中已经不足了这时就会从 Local BufferPool 和 Network BufferPool 申请,好在这个时候 Buffer 还是可以申请到的。
过了一段时间后由于上游的发送速率要大于下游的接受速率,下游的 TaskManager 的 Buffer 已经到达了申请上限,这时候下游就会向上游返回 Credit = 0,ResultSubPartition 接收到之后就不会向 Netty 去传输数据,上游 TaskManager 的 Buffer 也很快耗尽,达到反压的效果,这样在 ResultSubPartition 层就能感知到反压,不用通过 Socket 和 Netty 一层层地向上反馈,降低了反压生效的延迟。同时也不会将 Socket 去阻塞,解决了由于一个 Task 反压导致 TaskManager 和 TaskManager 之间的 Socket 阻塞的问题。
总结:
网络流控是为了在上下游速度不匹配的情况下,防止下游出现过载。 2. 网络流控有静态限速和动态反压两种手段
3. Flink 1.5 之前是基于 TCP 流控 + bounded buffer 实现反压
3.AI绘画生产小说/游戏/宣传物等配图
下边是我通过AI做副业的部分收入,主要是通过AI绘画做设计图赚钱,利用AI技术生成的设计图片不仅高效质量又高,还有做AI电商背景图上传到平台等。(以下仅代表个人收益)
大概统计了一下这半个月的收入,如下表
二、AI****的第二层价值是「个人增值」 实用价值
1.比如你的工作是设计师, 你现在通过学会AI技术,用AI赋能现有的工作,去加快效率以及实现独特的AI效果,把自己变成AI设计师
2.比如你的工作是程序员 你可以通过AI技术去辅助写代码,把自己变成AI程序员。蓝色部分的代码就是AI工具Copilot根据前面的代码而生成的
3.比如你的工作是摄影师 你可以通过AI技术,去实现原本现实拍摄需要大成本才能做到的AI写真,把自己打造成AI摄影师
4.比如你是一个淘宝女装店老板 如果自己的服装店对模特照片要求不是很高,也可以利用AI生成模特来降低成本
除此之外,还有AI建筑设计、AI修图等等等等,这些都是AI个人增值里的实用价值,给你在现有的技能上赋能提效。
三、AI****的第三层价值是「兴趣爱好」 我自己是最喜欢这个价值的,包括我们很多小伙伴之所以能聚在一起,也是因为大家本身就对AI感兴趣,而不是说非得功利性地去看待AI。
可能大家都想学习AI绘画技术,也想通过这项技能真正赚到钱,但是不知道该如何开始学习,因为网上的资料太多太杂乱了,如果不能系统的学习就相当于是白学,因为自身做副业需要,我这边整理了全套的AIGC资料包,大家有需要可以文末获取,希望能够真正帮助到大家。
关于AI绘画技术储备 学好 AI绘画 不论是就业还是做副业赚钱都不错,但要学会 AI绘画 还是要有一个学习规划。最后大家分享一份全套的 AI绘画 学习资料,给那些想学习 AI绘画 的小伙伴们一点帮助!
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Python开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注Python)
学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!
一、Python所有方向的学习路线 Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
二、学习软件 工欲善其事必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。
三、全套PDF电子书 书籍的好处就在于权威和体系健全,刚开始学习的时候你可以只看视频或者听某个人讲课,但等你学完之后,你觉得你掌握了,这时候建议还是得去看一下书籍,看权威技术书籍也是每个程序员必经之路。
四、入门学习视频 我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。
五、实战案例 光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
六、面试资料 我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
bca3abe69e09bc1a.png)
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-FnTpPtBG-1712516541313)]
在Python中,我们经常需要连接和操作数据库。pymysql是一个流行的Python模块,专门用于与MySQL数据库进行交互。本文将介绍pymysql模块的基本使用方法,以及它在实际开发中的一些应用场景。
一、pymysql 模块介绍 pymysql是一个用于Python编程的第三方模块,用于连接和操作MySQL数据库。它提供了一个简单而强大的接口,使开发者能够轻松地在Python程序中执行各种数据库操作,如查询、插入、更新和删除数据等。
pymysql模块由Python实现,它遵循Python Database API规范(PEP 249),这使得它与其他数据库API兼容,并使得在不同的数据库之间切换变得更加容易。
pymysql在Python开发者社区非常受欢迎,因为它易于使用、功能强大并且具有良好的性能。它提供了许多高级特性,如事务管理、连接池、数据类型转换等,使得开发数据库驱动的应用程序变得更加便捷和高效。
总之,pymysql模块是一个重要的工具,可帮助Python开发者轻松地与MySQL数据库进行交互和操作。
二、使用步骤 1.安装pymysql模块 在使用pymysql模块之前,首先需要将其安装到Python环境中。可以通过在命令行中运行以下命令来安装pymysql模块:
pip install pymysql 如遇【‘pip’ 不是内部或外部命令,也不是可运行的程序或批处理文件。】可查看本人另一篇文章来解决!
【三步解决】‘pip‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。
2.连接数据库及常用操作 代码如下(示例):
# 导入pymysql模块 import pymysql # 建立数据库连接 conn = pymysql.connect( host='localhost', # 主机名(或IP地址) port=3306, # 端口号,默认为3306 user='root', # 用户名 password='password', # 密码 charset='utf8mb4' # 设置字符编码 ) # 获取mysql服务信息(测试连接,会输出MySQL版本号) print(conn.get_server_info()) # 创建游标对象 cursor = conn.cursor() # 选择数据库 conn.select_db("mytable") # 执行查询操作 cursor.execute('SELECT \* FROM mytable') # 获取查询结果,返回元组 result : tuple = cursor.
一、KeyStore描述 在 Android 开发中,KeyStore 是一个用于存储密钥和证书的安全容器。它提供了一种安全的方式来存储敏感信息,如密钥对、数字证书等,以防止它们被未授权的应用或攻击者访问。
KeyStore 通常用于加密数据、数字签名、TLS/SSL 连接等场景。
Android 开发中使用 KeyStore 的常见场景:
存储密钥对:可以使用 KeyStore 来生成和存储公钥和私钥的密钥对。这些密钥对通常用于数据加密、数字签名等操作。
存储数字证书:可以使用 KeyStore 来存储数字证书,用于验证身份、建立安全连接等场景。
安全存储密码:可以使用 KeyStore 来安全地存储密码、凭证、API 密钥等敏感信息,以防止它们被未授权的应用或攻击者访问。
TLS/SSL 连接:可以使用 KeyStore 来管理客户端证书和受信任的 CA 证书,用于安全通信、建立 TLS/SSL 连接等操作。
双因素身份验证:可以使用 KeyStore 来存储和管理双因素身份验证所需的密钥和证书,用于提高身份验证的安全性。
在 Android 中,KeyStore 是通过 java.security.KeyStore 类来实现的。可以使用该类来创建、加载、存储和检索密钥和证书。Android 提供了特定于 Android 平台的 KeyStore 实现,称为 AndroidKeyStore,它提供了更高级的安全功能,如硬件支持、密钥链随机生成等。
二、KeyStore使用 // 密钥库类型 private const val PP_KEYSTORE_TYPE = "AndroidKeyStore" // 密钥库别名 private const val PP_KEYSTORE_ALIAS = "pp_keystore_alias" // 加密算法标准算法名称 private const val PP_TRANSFORMATION = "
目录
前言
HTML(构建)
CSS(设计)
JavaScript(互动)
总结
相关书籍推荐
前言 前端(Frontend)指的是与用户直接交互的部分,也称为客户端。在网站或者应用程序中,前端通常包括用户界面(UI)、用户体验(UX)以及与用户直接交互的各种功能。前端开发主要涉及使用HTML、CSS和JavaScript等技术来构建网站或应用程序的用户界面和交互逻辑。今天我们来初步认识一下这三件套。
HTML(构建) HTML(HyperText Markup Language)是一种用于创建网页结构的标记语言。它由一系列的元素(elements)组成,这些元素用标签(tags)来描述其在网页中的含义和结构。HTML被广泛用于构建网页,并且是Web开发中的基础。通过HTML,开发者可以定义文本、图像、链接、表格、表单等在网页中的布局和内容。HTML使用一种层次结构来组织网页内容,这种结构由标签对(tag pair)组成,其中包括起始标签(opening tag)、结束标签(closing tag)和标签内容。例如,<p>标签用于表示段落,<img>标签用于插入图像,<a>标签用于创建链接等。HTML不负责网页的样式和交互行为,这些功能通常由CSS(Cascading Style Sheets)和JavaScript来实现。HTML与CSS和JavaScript一起构成了Web开发的基础技术,用于创建具有吸引力、交互性和可访问性的网页。 CSS(设计) CSS(Cascading Style Sheets,层叠样式表)是一种用于控制网页样式和布局的样式表语言。它可以与HTML结合使用,通过定义样式规则来指定网页元素的外观和排版方式。CSS的主要作用是将内容与其呈现方式分离,使得网页的样式和结构可以独立进行管理和修改,从而提高网页的可维护性和可重用性。CSS使用一种规则(rule)的结构来定义样式,每个规则由选择器(selector)和声明块(declaration block)组成。选择器用于选择要应用样式的HTML元素,而声明块包含了一组属性-值对,用于描述所选元素的样式。例如,以下是一个简单的CSS规则,这个规则将会选中所有的段落(<p>元素),并将它们的文本颜色设置为蓝色,字体大小设置为16像素。 p { color: blue; font-size: 16px; } CSS可以用于控制元素的尺寸、颜色、字体、间距、边框等各种样式属性,以及实现响应式布局、动画效果等。它是Web开发中的重要技术之一,与HTML和JavaScript一起构成了现代Web页面的核心技术。 JavaScript(互动) JavaScript是一种高级的、解释型的编程语言,用于在网页上实现交互式的动态效果和功能。它通常被用于在网页上操作DOM(Document Object Model,文档对象模型)、处理用户输入、进行数据验证、执行动画效果、与服务器进行通信等。JavaScript最初由Netscape公司(现在的Mozilla基金会)的布兰登·艾奇(Brendan Eich)在1995年创建,并最初被用于在网页中实现简单的交互效果。如今,JavaScript已经发展成为一种强大的、全球通用的编程语言,它被广泛应用于Web开发、移动应用开发、桌面应用程序开发等领域。JavaScript具有以下特点: 动态性: JavaScript可以在网页加载完毕后动态地修改网页内容、样式和结构,使得网页具有更丰富的交互性。事件驱动: JavaScript可以通过监听用户的操作事件(如点击、键盘输入等)来触发相应的响应动作,从而实现交互效果。跨平台: JavaScript可以在几乎所有的现代浏览器中运行,并且可以被用于开发跨平台的Web应用程序。灵活性: JavaScript支持面向对象编程(OOP)、函数式编程(FP)等多种编程范式,使得开发者能够根据需要选择合适的编程风格。 JavaScript与HTML和CSS一起构成了现代Web开发中的三大核心技术,它们共同构建了丰富、交互性强的Web页面和应用程序。 总结 在前端中,HTML,CSS,JavaScript相互配合,来构建前端页面,其中
HTML用于对页面进行构建CSS用于对页面进行设计JavaScript用于实现和用户之间的互动逻辑 熟练运用三件套,是进行前端设计的重要基础。
相关书籍推荐 HTML+CSSHead First HTML与CSS(第二版)CSS精通CSS 高级Web标准解决方案(第三版)JavaScriptJavaScript权威指南(第七版) 新手上路,水平有限,如有错误,还望海涵并指出!
与君共勉!
我们存储到ES中数据大致分为以下两种:
全文本,例如文章内容、通知内容精确值,如实体Id 在对这两类值进行查询的时候,精确值类型会比较它们的二进制,其结果只有相等或者不想等。而对全文本类型进行等值比较是不太实现的,一般我们只会比较两个文本是否相似。根据上一讲的内容我们知道,要比较两个文本类型是否相似,使用相关性评分来评估的。而要得到相关性评分,我们就需要对全文本进行分词处理,然后得到统计数据才能进行评估
在es中,负责处理文本分词的是分词器,本文我们就来学习ES中分词器的组成和部分分词器的特性。
分词(Analysis)与分词器 分词是将全文本转换为一系列单词的过程,这些单词称为term或者token,而这个过程称为分词。
分词是通过**分词器(Analyzer)来实现的,**比如用于中文分词的IK分词器等。当然你也可以实现自己的分词器,例如可以简单将全文本以空格来实现分词。ES内置来一些常用的分词器,如果不能满足你的需求,你可以安装第三方的分词器或者定制化你自己的分词器。
**除了在写入的时候对数据进行分词,在对全文本进行查询的时候也需要使用相同的分词器对检索内存进行分析。例如,**查询Java Book的时候会分为java 和book两个单词,如下如所示:
分词器的组成 分词器主要由 3 部分组成。
Character Filter:注意对原文本进行格式处理,比如去除html标签Tokenizer:按照指定规则对文本进行切分,比如按空格来切分单词,同时页负责标记出每个单词的顺序、位置以及单词在原文本中开始和结束的偏移量Token Filter:对切分后的单词进行处理,如转换为小写、删除停顿词、增加同义词、词干化等 如下图就是分词器工作的流程,需要进行分词的文本依次通过Character Filter、Tokenizer、Token Filter,最后得出切分后的词项:
ES内置的分词器 为了方便用户使用,Es为用户提供了多个内置的分词器,常见的有以下8种。
Standard Analyzer:这个是默认的分词器,使用Unicode文本分割算法,将文本按单词切分并且转换为小写Simple Analyzer:按照非字母切分并且进行小写处理Stop Analyzer:与 Simple Analyzer 类似,但增加了停用词过滤(如 a、an、and、are、as、at、be、but 等)。Whitespace Analyzer:使用空格对文本进行切分,并不进行小写转换Pattern n Analyzer;使用正则表达式切分,默认使用 \W+ (非字符分隔)。支持小写转换和停用词删除。Keyword Analyzer:不进行分词Language Analyzer:提供了多种常见语言的分词器。如 Irish、Italian、Latvian 等。Customer Analyzer:自定义分词器 下面我们通过讲解Standard Analyzer来进一步熟悉分词器的工作流程,但在这之前我要先介绍一个Es提供的API:_analyze。
_analyze Api是一个非常有用的工具,它可以帮助我们查看分词器是如何工作的。_analyze API 提供了 3 种方式来查看分词器是如何工作的。
使用 _analyze API 时可以直接指定 Analyzer 来进行测试,示例如下: GET _analyze { "analyzer": "standard", "text": "Your cluster could be accessible to anyone." } # 结果 { "
在Web开发中,我们经常遇到前后端数据类型不匹配的问题,特别是当后端使用大数据类型如Long时,前端由于JavaScript的数字精度限制,可能导致精度丢失。本文将深入探讨这个问题,并提供两种有效的解决方法。
一、问题背景 在后端开发中,为了确保数据的完整性和精度,我们可能会选择使用Long类型来存储某些数据,如订单ID、用户ID等。然而,当这些数据通过API传输到前端时,由于JavaScript中Number类型的精度限制(最大安全整数为2^53-1),如果Long类型的值超过了这个范围,就可能导致精度丢失。
二、解决方法 针对这个问题,我们可以采取以下几种解决方法:
方法一:使用@JsonSerialize注解将Long类型转换为String类型 在Java后端中,我们可以使用Jackson库的注解功能,将Long类型的字段在序列化为JSON时转换为String类型。这样,前端接收到的数据就是字符串形式,避免了精度丢失的问题。
示例代码如下:
import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import lombok.Data; @Data public class PayOrderVo { // 使用ToStringSerializer将Long类型的id字段转换为String类型 @JsonSerialize(using = ToStringSerializer.class) private Long id; // 其他字段... } 通过这种方式,我们可以确保后端返回的JSON中,Long类型的字段都以字符串的形式存在,前端可以直接将其作为字符串处理,无需担心精度问题。
方法二:使用@JsonFormat注解将Long类型格式化为String 除了使用ToStringSerializer,Jackson还提供了@JsonFormat注解,它允许我们指定字段的序列化格式。当我们将shape属性设置为JsonFormat.Shape.STRING时,Long类型的字段也会被格式化为字符串。
示例代码如下:
import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; @Data public class PayOrderVo { // 使用@JsonFormat注解将Long类型的id字段格式化为String @JsonFormat(shape = JsonFormat.Shape.STRING) private Long id; // 其他字段... } 这种方法同样可以确保Long类型的字段在序列化为JSON时以字符串形式出现,避免前端精度丢失的问题。
前两种通过注解的方式确实可以有效地解决Long类型数据在前后端传输中的精度丢失问题。然而,当项目中存在多个类,且这些类中的多个字段都需要将Long类型转换为String类型返回给前端时,逐一为每个字段添加注解不仅繁琐,还可能导致代码冗余和难以维护。为了更优雅、高效地解决这一问题,我们可以考虑使用全局配置的方式,一次性解决所有Long类型字段的序列化问题。这样,我们不仅能提高开发效率,还能确保代码的一致性和可维护性。接下来,我们将详细探讨如何通过全局配置来实现这一目标。
方法三:全局配置Jackson将Long类型序列化为String 除了对单个字段进行注解配置外,我们还可以进行全局配置,使得所有Long类型的字段在序列化时都自动转换为String类型。这样可以减少在每个字段上添加注解的重复工作。
示例代码如下:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.
说白了,Google、Baidu 赖以生存的搜索引擎,抖音、头条引以为傲的推荐系统,广点通等平台主流的“印钞机器”广告引擎,这背后的算法逻辑,数据分析科学和机器学习原理,才是最值得工程师深入研究的风口。
但是,这些和大厂核心业务挂钩的主流系统,通常都非常复杂。
淘宝、抖音、美团头条推荐系统的基础架构
就拿字节跳动的推荐系统来说,架构层面包含数据排序层、融合过滤层、召回层、数据存储层、计算平台层、数据源等。这其中,不仅涉及多种算法逻辑,还关系到数据处理相关作业,用开发工程师的思维进行理解,确实会比较困难。
况且,各个大厂都有自家的技术沉淀,所构建的系统和实现逻辑也截然不同,比如:
同样是搜索引擎,Google 和 Baidu 的实现方式有什么区别?
今日头条、抖音,和淘宝、天猫的推荐系统,差异在哪?
作为一名开发工程师,需要掌握哪些必备算法知识?
其实,有关推荐系统、广告系统和搜索系统的探讨,都是这两年才开始热起来的。这类较新的复杂系统,恕我直言,仅仅靠网上的学习资料很难真正理解。有句话叫万事开头难,如果你也想提升这一块的技术能力,与其冒着树立错误认知的风险,还不如找个靠谱的大咖带领学习。
市面上分析算法的人很多,真比较起课程深度与质量,那我还是推荐这门神秘超一线大厂1500道的2021LeetCode算法刷题pdf笔记
==================================================================
昨晚逛GitHub,无意中看到一位大佬的算法刷题笔记,感觉发现了宝藏!有些小伙伴可能已经发现了,但咱这里还是忍不住安利一波,怕有些小伙伴没有看到。
关于算法刷题的困惑和疑问也经常听朋友们提及。这份笔记里面共包含作者刷力扣算法题后整理的上千道题,每道题均附有详细题解过程。有了这个笔记的总结,对校招和社招的算法刷题帮助之大不言而喻,果断收藏安利。
累计**1500+**道…拿来即刷!word很大,你忍一下,我就不一一截图了,诸君自行下载哈。
可以看到,每道题的原题,题目大意,解题思路,以及代码实现都非常详细。
关于算法刷题的困惑和疑问也经常听朋友们提及。这份笔记里面共包含作者刷LeetCode算法题后整理的数百道题,每道题均附有详细题解过程。很多人表示刷数据结构和算法题效率不高,甚是痛苦。有了这个笔记的总结,对校招和社招的算法刷题帮助之大不言而喻,果断收藏了。
非常值得一刷的LeetCode
LeetCode刷题目录
============
思维导图
====
最易懂的贪心算法
========
玩转双指针
=====
居合斩!二分查找
========
千奇百怪的排序算法
=========
一切皆可搜索
======
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
最后 针对以上面试题,小编已经把面试题+答案整理好了
面试专题 除了以上面试题+答案,小编同时还整理了微服务相关的实战文档也可以分享给大家学习
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门即可获取!
12502531539)]
[外链图片转存中…(img-8sBS0mnb-1712502531539)]
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门即可获取!