Es客户端学习

news2024/11/16 15:46:49

版本:opensearch-rest-high-level-client-2.3.0.jar,httpcore-nio-4.4.11.jar,httpasyncclient-4.1.4.jar

问题背景

初始化es索引逻辑是监听大数据团队消息,然后异步写入es(org.opensearch.client.RestHighLevelClient#bulkAsync),qps很低就将服务cpu接近打满,通过排查问题原因是消息消费很快,es写入有瓶颈,由于是异步写入,那么请求都积压在服务导致服务内存不足频繁GC,进而导致cpu飙高,那么es客户端是如何初始化的?异步线程池是什么类型队列为什么不会积压阻塞?那么带着问题去学习事半功倍

ES客户端初始化流程

RestHighLevelClient.drawio.png

  1. 创建异步Http客户端
    1. customizeRequestConfig回调
    2. customizeHttpClient回调
  2. 创建IOReactor:ConnectingIOReactor
  3. 创建连接管理器
  4. 创建http异步客户端:InternalHttpAsyncClient

创建IOReactor

默认实现类:DefaultConnectingIOReactor

  1. requestQueue:SessionRequest队列,即:客户端与服务器建立会话连接请求队列(SessionRequest interface represents a request to establish a new connection (or session) to a remote host)
  2. threadFactory:dispatcher线程池,兜底命名规则:I/O dispatcher
  3. dispatchers:dispatcher处理器(BaseIOReactor)
    1. eventDispatch(IOEventDispatch):IOEvent分发调度器,动作:connected/inputReady/outputReady/timeout/disconnected
    2. exceptionHandler:IO异常处理器,当收到异常时决定是否继续执行I/O reactor,异常类型:IOException/RuntimeException
  4. workers:worker线程,BaseIOReactor与IOEventDispatch桥接线程。自旋等待处理select数据
    1. this.selector.select
    2. 如果是SHUT_DOWN状态,终止自旋
    3. 如果是SHUTTING_DOWN状态,closeSessions,closeNewChannels
    4. processEvents:处理事件,BaseIOReactor仅处理读写事件,acceptable,connectable事件不处理,客户端也不需要处理·.·
    5. validate:Validate active channels
    6. processClosedSessions:处理已关闭会话
    7. 如果是ACTIVE状态:org.apache.http.impl.nio.reactor.AbstractIOReactor#processNewChannels:处理新channel如果存在的话,即如果存在新channel将当前selector注册至channel(类型:SelectionKey.OP_READ,监听channel事件),并将注册的SelectionKey封装为IOSessionImpl添加至org.apache.http.impl.nio.reactor.AbstractIOReactor#sessions,将IOSessionImpl附加(attach)至刚刚注册的SelectionKey
    8. 如果是ACTIVE状态,并且sessions为空,优雅停机:Exit select loop if graceful shutdown has been completed
    9. 如果开启了interestOpsQueueing:processPendingInterestOps,默认关闭
  5. threads:使用threadFactory命名规则封装的Worker线程缓存

创建连接管理器connmgr

实现类:PoolingNHttpClientConnectionManager

  1. ioreactor : DefaultConnectingIOReactor
  2. configData
  3. pool:连接池实现类CPool
    1. connFactory:实现类InternalConnectionFactory
    2. addressResolver
    3. sessionRequestCallback:实现类InternalSessionRequestCallback,在会话请求(org.apache.http.nio.reactor.ConnectingIOReactor#connect)完成时处理pending队列中的待处理请求
    4. routeToPool:route与pool映射
    5. leasingRequests:实现类new LinkedList<LeaseRequest<T, C, E>>()
    6. pending:实现类new HashSet()
    7. leased:实现类new HashSet()
    8. available:new LinkedList()
    9. completedRequests:new ConcurrentLinkedQueue<LeaseRequest<T, C, E>>()
    10. maxPerRoute:new HashMap<T, Integer>()
    11. defaultMaxPerRoute:2
    12. maxTotal:20
  4. iosessionFactoryRegistry:RegistryBuilder.create()…build()

创建http异步客户端

实现类:InternalHttpAsyncClient

  1. connmgr:连接管理器
  2. connManagerShared:默认false,Defines the connection manager is to be shared by multiple client instances
  3. threadFactory
    1. connManagerShared默认false,使用配置线程工厂,兜底Executors.defaultThreadFactory()
    2. 否则为null
  4. eventHandler
    1. connManagerShared默认false,使用配置事件处理器,兜底HttpAsyncRequestExecutor
    2. 否则为null
  5. reactorThread
    1. 如果threadFactory与eventHandler不为空,使用threadFacotry创建匿名线程,线程使用connmgr执行内部IO事件分发调度(new InternalIODispatch(eventHandler))
    2. 否则为null
  6. status:初始化状态为INACTIVE
  7. exec:实现类MainClientExec(路由策略在prepare阶段决定org.apache.http.impl.nio.client.MainClientExec#prepare:routePlanner=new DefaultRoutePlanner(schemePortResolver=DefaultSchemePortResolver.INSTANCE))

创建Rest客户端

  1. client:http异步客户端
  2. nodeSelector:默认org.opensearch.client.NodeSelector#ANY
  3. chunkedEnabled:默认为空
  4. nodes:集群节点HttpHost.create(serverCluster),例如:https://my-es0-cluster.com
  5. nodeTuple:nodes与authCache映射
  6. compressionEnabled:如果chunkedEnabled不为空,取chunkedEnabled配置,否则为false

启动http异步客户端

实现类:InternalHttpAsyncClient

启动异步客户端

  1. 将客户端状态由INACTIVE设置为ACTIVE
  2. 如果reactorThread不为空,启动reactorThread线程
    1. ioreactor(DefaultConnectingIOReactor)执行内部事件(InternalIODispatch)分发:DefaultConnectingIOReactor.AbstractMultiworkerIOReactor.execute(InternalIODispatch)
    2. 默认根据服务核心数量(n)创建n个BaseIOReactor,并将n个BaseIOReactor与InternalIODispatch封装为n个Worker
    3. 遍历并启动Worker
    4. 自旋等待select事件:selector.select(mac系统默认实现类:KQueueSelectorImpl)
    5. DefaultConnectingIOReactor处理select事件(下面再聊这块的流程):org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor#processEvents
    6. 遍历workers,如果存在异常处理异常
  3. 客户端至此创建并初始化完成返回RestClient

DefaultConnectingIOReactor处理select事件

org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor#processEvents

  1. 处理会话请求:org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor#processSessionRequests
  2. 遍历selectedKeys处理数据:org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor#processEvent
    1. 如果可以连接isConnectable,建立连接
    2. 如果连接未完成(未中断,例如:超时/IO异常/主动释放/主动取消),将会话具柄(SessionRequestHandle)中的会话请求(SessionRequestImpl)封装为通道条目ChannelEntry,添加至BaseIOReactor的新通道(newChannels)
    3. 唤醒selector等待处理通道数据,即启动异步客户端中的2.c步骤逻辑
  3. 处理超时数据:org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor#processTimeouts

BaseIOReactor处理select事件

  1. 执行父类方法处理事件:org.apache.http.impl.nio.reactor.AbstractIOReactor#processEvents
  2. 遍历SelectionKey数据处理读写等事件
  3. 处理读写等数据均回调eventDispatch(即InternalIODispatch,handler=HttpAsyncRequestExecutor)处理,例如:org.apache.http.impl.nio.reactor.BaseIOReactor#readable,回调eventDispatch.inputReady

ES客户端线程设计

es客户端Reactor.drawio.png

异步写流程bulkAsync

bulkRequest.drawio.png

RouteSpecificPool

  1. available:pool entry可复用链表
  2. leased:已租借集合,可复用链表转移而来
  3. pending:待处理会话请求与回调映射(Map<SessionRequest, BasicFuture> pending),key值等同CPool.pengding

方法

  1. getFree:返回空闲资源,不为空则将LeaseRequest设置为已完成(即isDone=true)。并且将CPool的该资源由available转移至leased

CPool

  1. maxTotal:全局最大可用资源数量
  2. available:pool entry可复用链表
  3. leased:已租借集合,可复用链表转移而来。包含RouteSpecificPool:leased结合
  4. pending:待处理会话请求集合,当RouteSpecificPool已分配数量小于maxPerRoute并且maxTotal存在剩余空间,创建的待连接的会话请求
  5. leasingRequests:租赁中的请求链表,当LeaseRequest请求未完成,并且processPendingRequest未完成时,将LeaseRequest添加至该链表
  6. completedRequests:已完成请求队列,当LeaseRequest请求完成时,将LeaseRequest添加至该队列
  7. totalUsed=maxTotal-pending-leased

方法

  1. fireCallbacks:处理completedRequests队列
  2. release:释放已租借资源

LeaseRequest

  1. future:状态机变化时回调该动作,例如:完结时回调PoolingNHttpClientConnectionManager.FutureCallback#completed->DefaultClientExchangeHandlerImpl#requestConnection->connectionAllocated->将LeaseRequest请求数据写入es服务端等待响应

小结

  1. leased:已租借的连接资源。在请求响应完成时回调callback释放已租借资源,例如:org.apache.http.impl.nio.client.DefaultClientExchangeHandlerImpl#responseCompleted/org.apache.http.impl.nio.client.MainClientExec#responseCompleted。一些关闭或异常场景也会释放连接资源,例如:org.apache.http.impl.nio.client.AbstractClientExchangeHandler#discardConnection
  2. available:可租借的连接资源。如果存在直接获取链接,将其转移至leased
  3. leasingRequests:正在租借连接资源的请求,等待有可用连接时处理该请求,并将该请求转移至leased或pending
  4. completedRequests:已完成租借并且已与服务端建立连接的请求,等待客户端请求写入服务端完成,服务端响应数据后将其再次出借或释放
  5. pending:已完成租借,且正在与服务端建立连接中的请求,建立完成后回调org.apache.http.nio.pool.AbstractNIOConnPool#requestCompleted租借连接将客户端请求写入服务端,租借成功则转移至leased,否则释放资源转移至available

问题推断

结合问题背景,有朋友可能已经有原因推断了,如果消息不断产生,生产的速度大于异步写es数据的速度,那么积压的请求都会堆积在leasingRequests这个无限链表里,那么就会出现gc频繁,并且无法回收,导致cpu飙高,降低服务的并发与吞吐量

问题复现

代码很简单,并发100线程异步写es数据,因为是异步写入es,因此不会阻塞,会很快完成写入,在完成1W条数据写入时可以手工dump内存快照

int size = 100;
ExecutorService es = Executors.newFixedThreadPool(size);
Thread.sleep(10 * 1000);
for (int i = 0; i < 10000; i++) {
  int finalI = i;
  es.submit(() -> {
    try {
      indexWriterService.indexDelete(docMessage);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
    System.out.println(System.currentTimeMillis() + ":"+ finalI);
  }
  );
}
Thread.sleep(Integer.MAX_VALUE);

问题分析

dump命令

jmap -dump:live,format=b,file=dump.hprof 30652

使用ibm工具分析dump文件,工具jar可以在官网下载,执行命令如下(因为是jdk17所以有很多参数,如果不是17可以直接执行工具)

java 
# jdk17导致不得不加的参数
--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/sun.net.util=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED --add-opens java.desktop/sun.swing=ALL-UNNAMED 
# jdk8直接直接下面这个工具jar即可
-Xmx4G -jar ha457.jar

分析结果,可以看到72%的内存暂用被列举为嫌疑对象了,而其中42%也正是与我们推断一致,蓝色部分为对象入口PoolingNHttpClientConnectionManager->CPool->LinkedList->Node(LeaseRequest)。至此破案
1

另外的30%呢,同样可以通过工具跟踪到其中23%的占用其实是我们的spring框架中加载的环境配置数据
2

压测时使用arthas对生产进行dump,也验证了我们的推断-.-
3

解决方法

  1. 为无限队列增加限制,方法很多,例如:增加一个请求计数器,请求进来时判断处理中数量,放行则递增,完结或异常时递减
  2. 将租借超时时间(对应配置:org.apache.http.client.config.RequestConfig.Builder#connectionRequestTimeout,默认Long的最大值)设置小一些(不推荐),超时不会再占用leasingRequests而是直接进入completedRequests并fireCallbacks,可能会有大量超时异常依然会消耗系统资源得不偿失,本文复现时也出现了该异常,堆栈见:注1
  3. 通过连接池状态限制请求数量(org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager#getStats)。es客户端没有对外暴露任何连接池相关的方法,如果想要通过该方式处理则需要实现es的回调接口org.opensearch.client.RestClientBuilder.HttpClientConfigCallback#customizeHttpClient,通过该回调传入定义好的连接池,例如:注2,实际如果选择该方案可以参考官方的兜底构建方式(org.apache.http.impl.nio.client.HttpAsyncClientBuilder#build)。例如我们增加了一个简单的监控打点(见注3),可以观察到每个路由的任务积压状态:pool_status=[leased: 0; pending: 6561(包含leasingRequests数量); available: 0; max: 2]

注1:

  at org.opensearch.client.RestHighLevelClient$1.onFailure(RestHighLevelClient.java:1966) ~[opensearch-rest-high-level-client-2.3.0.jar:2.3.0]
	at org.opensearch.client.RestClient$FailureTrackingResponseListener.onDefinitiveFailure(RestClient.java:707) ~[opensearch-rest-client-2.3.0.jar:2.3.0]
	at org.opensearch.client.RestClient$1.failed(RestClient.java:450) ~[opensearch-rest-client-2.3.0.jar:2.3.0]
	at org.apache.http.concurrent.BasicFuture.failed(BasicFuture.java:137) ~[httpcore-4.4.11.jar:4.4.11]
	at org.apache.http.impl.nio.client.DefaultClientExchangeHandlerImpl.executionFailed(DefaultClientExchangeHandlerImpl.java:101) ~[httpasyncclient-4.1.4.jar:4.1.4]
	at org.apache.http.impl.nio.client.AbstractClientExchangeHandler.failed(AbstractClientExchangeHandler.java:426) ~[httpasyncclient-4.1.4.jar:4.1.4]
	at org.apache.http.impl.nio.client.AbstractClientExchangeHandler.connectionRequestFailed(AbstractClientExchangeHandler.java:348) ~[httpasyncclient-4.1.4.jar:4.1.4]
	at org.apache.http.impl.nio.client.AbstractClientExchangeHandler.access$100(AbstractClientExchangeHandler.java:62) ~[httpasyncclient-4.1.4.jar:4.1.4]
	at org.apache.http.impl.nio.client.AbstractClientExchangeHandler$1.failed(AbstractClientExchangeHandler.java:392) ~[httpasyncclient-4.1.4.jar:4.1.4]
	at org.apache.http.concurrent.BasicFuture.failed(BasicFuture.java:137) ~[httpcore-4.4.11.jar:4.4.11]
	at org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager$1.failed(PoolingNHttpClientConnectionManager.java:316) ~[httpasyncclient-4.1.4.jar:4.1.4]
	at org.apache.http.concurrent.BasicFuture.failed(BasicFuture.java:137) ~[httpcore-4.4.11.jar:4.4.11]
	at org.apache.http.nio.pool.AbstractNIOConnPool.fireCallbacks(AbstractNIOConnPool.java:503) ~[httpcore-nio-4.4.11.jar:4.4.11]
	at org.apache.http.nio.pool.AbstractNIOConnPool.requestTimeout(AbstractNIOConnPool.java:633) ~[httpcore-nio-4.4.11.jar:4.4.11]
	at org.apache.http.nio.pool.AbstractNIOConnPool$InternalSessionRequestCallback.timeout(AbstractNIOConnPool.java:894) ~[httpcore-nio-4.4.11.jar:4.4.11]
	at org.apache.http.impl.nio.reactor.SessionRequestImpl.timeout(SessionRequestImpl.java:183) ~[httpcore-nio-4.4.11.jar:4.4.11]
	at org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor.processTimeouts(DefaultConnectingIOReactor.java:210) ~[httpcore-nio-4.4.11.jar:4.4.11]
	at org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor.processEvents(DefaultConnectingIOReactor.java:155) ~[httpcore-nio-4.4.11.jar:4.4.11]
	at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor.execute(AbstractMultiworkerIOReactor.java:351) ~[httpcore-nio-4.4.11.jar:4.4.11]
	at org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager.execute(PoolingNHttpClientConnectionManager.java:221) ~[httpasyncclient-4.1.4.jar:4.1.4]
	at org.apache.http.impl.nio.client.CloseableHttpAsyncClientBase$1.run(CloseableHttpAsyncClientBase.java:64) ~[httpasyncclient-4.1.4.jar:4.1.4]
	at java.lang.Thread.run(Thread.java:833) [?:?]
Caused by: java.util.concurrent.TimeoutException: Connection lease request time out
	at org.apache.http.nio.pool.AbstractNIOConnPool.processPendingRequest(AbstractNIOConnPool.java:411) ~[httpcore-nio-4.4.11.jar:4.4.11]
	at org.apache.http.nio.pool.AbstractNIOConnPool.processNextPendingRequest(AbstractNIOConnPool.java:391) ~[httpcore-nio-4.4.11.jar:4.4.11]
	at org.apache.http.nio.pool.AbstractNIOConnPool.requestTimeout(AbstractNIOConnPool.java:629) ~[httpcore-nio-4.4.11.jar:4.4.11]
	... 8 more

注2:

RestClient.builder(HttpHost.create("myServerCluster")).setHttpClientConfigCallback(httpClientBuilder -> {
    httpClientBuilder.setMaxConnTotal(apolloConfig.getEsMaxConnectTotal());
    httpClientBuilder.setMaxConnPerRoute(apolloConfig.getEsMaxConnectPerRoute());
    ConnectingIOReactor ioreactor = IOReactorUtils.create(
        defaultIOReactorConfig != null ? defaultIOReactorConfig : IOReactorConfig.DEFAULT, threadFactory);
    PoolingNHttpClientConnectionManager poolingmgr = new PoolingNHttpClientConnectionManager(
        ioreactor,
        RegistryBuilder.<SchemeIOSessionStrategy>create()
        .register("http", NoopIOSessionStrategy.INSTANCE)
        .register("https", null)
        .build());
    httpClientBuilder.setConnectionManager(poolingmgr);
    return httpClientBuilder;
});

注3:

PoolingNHttpClientConnectionManager poolingMgr = esClientFactory.getPoolingmgr();
    if (poolingMgr != null) {
      for (HttpRoute route : poolingMgr.getRoutes()) {
        System.out.println("pool_status="+poolingMgr.getStats(route));
      }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/113813.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

七、Kubernetes1.25应用部署、发布的两种方式

1、概述 通过现代的 Web 服务&#xff0c;用户希望应用程序能够 24/7 全天候使用&#xff0c;开发人员希望每天可以多次发布部署新版本的应用程序。 容器化可以帮助软件包达成这些目标&#xff0c;使应用程序能够以简单快速的方式发布和更新&#xff0c;而无需停机。这段话是Ku…

智子商城项目实践开发文档

ZutShop Junior practical training project 在csdn暂存一下开发文档 本人大三做的实训项目&#xff0c;前后端分离。 后端&#xff1a;https://github.com/roydonGuo/ZutShop 前端使用Vue&#xff0c;前端项目地址&#xff1a;https://github.com/roydonGuo/ZutShop-Vue 0. …

python利用json和pyecharts画折线图实例

目录 一.json模块对数据进行处理 二.利用pyecharts画折线图 三.利用pyecharts画美、日、印三国家折线图 四.本文数据集 注&#xff1a;本次实验的数据在文章最后面&#xff0c;我已上传至百度网盘 一.json模块对数据进行处理 上面三个txt文本是这三个国家疫情爆发相关的数据 …

linux有磁盘空间却显示不足 linux中inode使用率过高处理办法

linux中inode使用率过高处理办法 前几天收到监控告警&#xff0c;说Inode节点空间不足&#xff0c;之前没处理过这种问题&#xff0c;所以记录一下处理过程&#xff0c;便于以后查阅。 Inode使用率高并不会影响系统正常运行和新文件的创建&#xff0c;但是当使用率达到100%的…

【Linux】Linux编译器gcc/g++的使用

今天不学习&#xff0c;明天变垃圾。 文章目录一、程序的翻译过程1.预处理&#xff08;1.2.3把你的代码编译成二进制代码&#xff09;2.编译&#xff08;C语言 > 汇编语言&#xff09;3.汇编&#xff08;无法被执行的二进制文件&#xff0c;为什么捏&#xff1f;&#xff09…

腾讯云Windows 轻量应用服务器如何搭建 FTP 服务?

本文档介绍如何在 Windows 操作系统的轻量应用服务器上通过 IIS 搭建 FTP 站点。 本文搭建 FTP 服务组成版本如下&#xff1a; Windows 操作系统&#xff0c;本文以系统镜像 Windows Server 2012 为例。IIS&#xff1a;Web 服务器&#xff0c;本文以 IIS 8.5 为例。 步骤1&am…

自行车在线租赁管理系统的设计与实现

自行车在线租赁管理系统 摘 要 随着Internet的不断发展&#xff0c;在线租赁在现实生活中的使用和普及&#xff0c;自行车在线租赁行业成为近年内出现的一个新行业&#xff0c;并且能够成为大众广为认可和接受的行为和选择。设计自行车在线租赁管理系统的目的就是借助计算机…

(四)汇编语言——简单程序

目录 编写程序的工作过程 编写汇编源程序 伪指令 汇编指令 注释 编写步骤 编译连接 编译 连接 运行 总结 编写程序的工作过程 接下来&#xff0c;我们简单介绍一下一个汇编程序&#xff0c;从写出到最后执行&#xff0c;他到底经历了哪些步骤。 编写汇编源程序 首先…

vue3 antd项目实战——修改table表格的默认样式(一)调整table表格每行(row)行高过高问题

vue3 antd项目实战——修改ant design vue table组件的默认样式&#xff08;调整每行行高&#xff09;知识调用场景复现实际操作解决a-table表格padding过宽知识调用 文章中可能会用到的知识链接vue3ant design vuets实战【ant-design-vue组件库引入】css样式穿透&#xff08;…

node.js+uni计算机毕设项目基于微信小程序的房屋交易平台(程序+小程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等…

智能超表面(RIS)辅助双功能雷达和通信波束形成设计(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 智能超表面&#xff0c;也叫做“可重配智能表面”&#xff0c;或者“智能反射表面”&#xff0c;英文为RIS&#xff08;Reconf…

springboot消息

发送短信的简单原理 activemq 5.17 版本的 需要java11 环境 mq 网页版本控制台 账号密码为admin 指定发送的名 即上图的默认名为itheima 监听器 自动监听消息 接受 如果接受到消息 还想再其他地方使用 可以使用sendto 使用管理员权限 登录 然后列出插件 安装插件 r…

Java 注解 自定义注解 注解的解析

目录 一、认识Java自带注解 二、自定义注解 1、认识元注解 2、自定义注解 3、注解的使用 4、反射解析注解 一、认识Java自带注解 jdk中自带了一些注解&#xff0c;如下四个&#xff1a; Override类方法的的重写注解Deprecated类或方法被废除的注解FunctionalInterface函…

数据结构---串

&#xff08;一&#xff09;串的基本概念 串&#xff08;string或字符串&#xff09;是由零个或多个字符组成的有限序列&#xff0c;一般记为&#xff1a;s′a1a2…a′n(n≥0) 其中&#xff0c;s是串的名称&#xff0c;用单括号括起来的字符序列是串的值; ai(1≤i≤n)ai(1≤i…

CSS优先级CSS盒子模型

1、CSS继承 文字相关的样式可以被继承【作用在父元素上面&#xff0c;子元素可以继承】布局相关的样式不可以被继承【可以通过inherit值进行继承】 2、CSS优先级 书写了相同样式时&#xff0c;后写的样式优先级较高当内部样式和外部样式有相同的样式时&#xff0c;后写的样式…

操作符(8)

目录 1、算术操作符 2、移位操作符 3、位操作符 1、不能创建临时变量&#xff08;第三个变量&#xff09;&#xff0c;实现两个数的交换 4、赋值操作符 5、单目操作符 6、关系操作符 7、逻辑操作符 8、条件操作符 9、逗号表达式 10、下标引用、函数调用和结构成员 …

WPF开发之Prism详解【内附源码】

在实际应用开发中&#xff0c;随着项目业务逐渐复杂&#xff0c;耦合度会越来越高&#xff0c;维护成本也会直线上升&#xff0c;所以解耦也变得越来越重要。Prism框架为WPF开发中解耦提供了非常便捷的应用。今天主要以一个简单的小例子&#xff0c;简述WPF开发中Prism框架的简…

基于Arch Linux的SystemRescue 9.06工具包新特性

导读在上次发布两个月后&#xff0c;SystemRescue&#xff08;原名SystemRescueCd&#xff09;Linux系统救援工具包今天更新到了9.06版本&#xff0c;这个版本在启动菜单中增加了新的选项&#xff0c;更新了组件和新工具。 SystemRescue 9.06在这里采用了最新、最棒的Xfce 4.18…

【三年面试五年模拟】算法工程师的独孤九剑秘籍(第十一式)

Rocky Ding公众号&#xff1a;WeThinkIn写在前面 【三年面试五年模拟】栏目专注于分享CV算法与机器学习相关的经典&&必备&&高价值的面试知识点&#xff0c;并向着更实战&#xff0c;更真实&#xff0c;更从容的方向不断优化迭代。也欢迎大家提出宝贵的意见或优…

我是真没想道,这个面试题居然从11年前就开始讨论了,而官方今年才表态。

大家好 这期给大家盘一个面试题啊&#xff0c;就是下面的第二题。 这个面试题的图片都被弄的有一点“包浆”了。 所以为了你的观感&#xff0c;我还是把第二道题目手打一遍。 啧啧啧&#xff0c;这行为&#xff0c;暖男作者实锤了&#xff1a; spring 在启动期间会做类扫描&…