Java-Kubernetes-运行的内存调优最佳通常-中 (java考证怎么考)
前言
在Kubees环境中运转运行程序只管很经常出现,但往往也充溢各种疑问,特意是在治理内存资源时。在本文中,咱们将讨论性能运行程序以优化Kubernetes环境中的内存经常使用并防止内存无余疑问的一些最佳通常。
OpenJDK17中的内存空间
OpenJDK17蕴含Java虚构机(JVM)经常使用的多个内存空间来治理Java运行程序的内存。了解这些不同的内存空间可以协助开发人员针对Kubernetes环境优化其Java运行程序。
HeapMemory-堆内存
堆内存会在Java运转时调配给对象(Object)或许JRE类。每当咱们创立一个对象的时刻,在堆内存中就会调配一块贮存空间给这个对象。Java的渣滓回收机制就是运转在堆内存上的,用以监禁那些没有任何援用指向自身的对象(无法达的对象。留意Java的渣滓回收也会处置几个相互援用但没有任何外部援用的对象)。任何在堆内存中调配的对象都有全局访问权限,可以从运行的任何中央被援用。
堆内存是存储Java运行程序创立的对象的中央。它是Java运行程序最关键的内存空间。在OpenJDK17中,自动堆大小是依据可用物理内存计算的,并设置为可用内存的1/4。
YoungGeneration-年轻代
对象被创立时,内存的调配首先出当初年轻代(大对象可以间接被创立在年轻代),大局部的对象在创立后很快就不再经常使用,因此很快变得无法达,于是被年轻代的GC机制清算掉(IBM的钻研标明,98%的对象都是很快沦亡的),这个GC机制被称为MinorGC或叫YoungGC。留意,MinorGC并不代表年轻代内存无余,它理想上只示意在Eden区上的GC。
年轻代上的内存调配是这样的,年轻代可以分为3个区域:Eden区(伊甸园,亚当和夏娃偷吃禁果生娃娃的中央,用来示意内存初次调配的区域,再贴切不过)和两个存活区(Survivor0、Survivor1)。
OldGeneration-老一辈
对象假设在年轻代存活了足够长的期间而没有被清算掉(即在几次YoungGC后存活了上去),则会被复制到年轻代,年轻代的空间普通比年轻代大,能寄存更多的对象,在年轻代上出现的GC次数也比年轻代少。当年轻代内存无余时,将口头MajorGC,也叫FullGC。
可以经常使用-XX:+UseAdaptiveSizePolicy开关来控制能否驳回灵活控制战略,假设灵活控制,则灵活调整Java堆中各个区域的大小以及进入老年代的年龄。
假设对象比拟大(比如长字符串或大数组),Young空间无余,则大对象会间接调配到老年代上(大对象或许触发提早GC,应少用,更应防止经常使用长命的大对象)。用-XX:PretenureSizeThreshold来控制间接升入老年代的对象大小,大于这个值的对象会间接调配在老年代上。
或许存在年轻代对象援用重生代对象的状况,假设须要口头YoungGC,则或许须要查问整个老年代以确定能否可以清算回收,这显然是低效的。处置的方法是,年轻代中保养一个512byte的块——cardtable,一切老年代对象援用重生代对象的记载都记载在这里。YoungGC时,只需查这里即可,不用再去查所有老年代,因此性能大大提高。
Metaspace-元空间
非堆空间被JVM用于存储元数据和类定义。在旧版本的Java中,它也称为终身代(PermGen)。在OpenJDK17中,PermGen空间已被新的Metaspace取代,其设计愈加高效和灵敏。
CodeCache-代码缓存
简而言之,JVMCodeCache(代码缓存)是JVM存储编译老本机代码的字节码的区域。咱们将可口头本机代码的每个块称为nmethod。nmethod或许是一个完整的或内联的Java方法。
即时(JIT)编译器是代码缓存区的最大消费者。这就是为什么一些开发人员将此内存称为JIT代码缓存。
ThreadStackSpace-线程堆栈空间
Java程序中,每个线程都有自己的StackSpace(堆栈)。这个StackSpace不是来自Heap的调配。所以StackSpace的大小不会遭到-Xmx和-Xms的影响,这2个JVM参数仅仅是影响Heap的大小。
StackSpace用来做方法的递归调用时压入StackFrame(栈帧)。所以当递归调用太深的时刻,就有或许耗尽StackSpace,爆出StackOverflow的失误。
-Xss128k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。依据运行的线程所需内存大小启动调整。在相反物理内存下,减小这个值能生成更多的线程。然而操作系统对一个进程内的线程数还是有限制的,不能有限生成,阅历值在3000~5000左右。
线程栈的大小是个双刃剑,假设设置过小,或许会出现栈溢出,特意是在该线程内有递归、大的循环时出现溢出的或许性更大,假设该值设置过大,就有影响到创立栈的数量,假设是多线程的运行,就会出现内存溢出的失误。
Sharedlibs-共享库
JavaJVM中的共享库空间(也称为共享类数据空间)是用于存储共享类元数据和其余数据结构的内存空间。该内存空间在多个Java进程之间共享。这准许在同一台机器上运转的各种Java运行程序共享类元数据和其余数据结构的相反正本。
共享库空间的目的是经过防止同一类元数据的重复正原本缩小内存经常使用并提高性能。当多个Java进程经常使用相反的类元数据时,它们可以共享该元数据的相反正本,从而缩小内存经常使用并缩短运行程序的启动期间。
为什么要微调JVM的内存设置?
JVM的自动行为会给Kubernetes带来很多费事。正如咱们之前看到的,堆自动设置为可用内存的1/4。因为JVM将思考pod可用的最大内存(有限制),因此堆的大小或许会比咱们想要的大。此外,其余自动值将运行于其余空间,例如代码缓存或元空间。假设从JVM的角度来看最大可用内存,它将大于提供应pod的最大可用内存。这将造成运行程序出现许多内存无余的状况(在Kubernetes局部)。
防止Java运行程序在Kubernetes上出现OOM
大少数时刻,都是为了微调JVM。因为咱们看到JVM触及不同的内存空间,因此咱们必定为每个空间设置特定的大小。这将协助咱们更准确地计算pod的内存限制。以下是显示每个内存空间可用选项的架构:
基本公式是:
Heap+Metaspace+CodeCache
意思是:
-XmX+-XX:MaxMetaspaceSize+-XX:ReservedCodeCacheSize
因为线程的数量取决于运行程序的高低文,因此倡导为此局部参与一些缓冲内存。自动状况下,线程堆栈最大设置为1MB。
假构想处置来自JVM的堆转储,则须要参与堆的大小作为第二次可用的额外内存。最后,设置pod限制的公式为:
(-XmX*2)+-XX:MaxMetaspaceSize+-XX:ReservedCodeCacheSize+SomeBuffer
缓冲区局部取决于高低文,128MB应该可以开局。
Helm模板性能
既然有了公式,咱们就可以经常使用一些Helm模板智能计算pod的恳求和限制。为开发人员提供一个便捷的选项来设置不同的参数,而无需担忧Pods设置,这也是一个好的模式。以下是自动值的示例:
jvm:garbageCollector:-XX:+UseG1GC#valuesinMimemory:heap:128metaspace:256compressedClassSpaceSize:64nonMethodCodeHeapSize:5profiledCodeHeapSize:48nonProfiledCodeHeapSize:48buffer:128
经常使用Helper来设置JAVA_TOOL_OPTIONS:
{{/*JVMcustomisation*/}}{{-define"chart.javaToolOptions"-}}-Xms{{.Values.jvm.memory.heap}}m-Xmx{{.Values.jvm.memory.heap}}m-XX:MetaspaceSize={{.Values.jvm.memory.metaspace}}m-XX:MaxMetaspaceSize={{.Values.jvm.memory.metaspace}}m-XX:CompressedClassSpaceSize={{.Values.jvm.memory.compressedClassSpaceSize}}m-XX:+TieredCompilation-XX:+SegmentedCodeCache-XX:Nnotallow={{.Values.jvm.memory.nonMethodCodeHeapSize}}m-XX:ProfiledCodeHeapSize={{.Values.jvm.memory.profiledCodeHeapSize}}m-XX:Nnotallow={{.Values.jvm.memory.nonProfiledCodeHeapSize}}m-XX:ReservedCodeCacheSize={{add.Values.jvm.memory.nonMethodCodeHeapSize.Values.jvm.memory.profiledCodeHeapSize.Values.jvm.memory.nonProfiledCodeHeapSize}}m{{-end-}}
在deployment.yaml文件中经常使用:
-name:{{include"chart.name".}}image:"{{.Values.contner.image.repository}}:{{.Values.container.image.tag}}"env:-name:JAVA_TOOL_OPTIONSvalue:{{include"chart.javaToolOptions".}}
依据提供的参数智能性能内存恳求和限制:
resources:limits:memory:{{add.Values.jvm.memory.heap.Values.jvm.memory.heap.Values.jvm.memory.metaspace.Values.jvm.memory.nonMethodCodeHeapSize.Values.jvm.memory.profiledCodeHeapSize.Values.jvm.memory.nonProfiledCodeHeapSize.Values.jvm.memory.buffer|printf"%dMi"}}cpu:{{.Values.container.resources.limits.cpu}}requests:memory:{{add.Values.jvm.memory.heap.Values.jvm.memory.metaspace.Values.jvm.memory.nonMethodCodeHeapSize.Values.jvm.memory.profiledCodeHeapSize.Values.jvm.memory.nonProfiledCodeHeapSize|printf"%dMi"}}cpu:{{.Values.container.resources.requests.cpu}}
论断
经过这一设置,咱们将Kubernetes一侧的"内存无余"(OutOfMemory)失误数量降至零。如今,JVM会在自己这边出现OOM,并生成堆转储,协助开发人员剖析内存。咱们会发现能否有一些优化须要推动,或许咱们能否须要参与堆大小(或其余内存空间)。
经过微调JVM内存性能,咱们冲破了恶性循环,即每次OOM都象征着为pod参与内存,以防止未来出现疑问。咱们能更好地了解每个内存空间,以及如何和何时参与它们。
每次调整都须要测试,因此咱们倡导经常使用一些工具,例如Micrometer,来取得无关JVM经常使用状况的一些目的。而且,最关键的是,咱们缩小了运行程序的内存需求,并经过缩小内存糜费理想上降落了基础设备的老本!
什么是K8S?
k8s是什么?
Kubernetes 是一个可移植的,可扩展的开源容器编排平台,用于管理容器化的工作负载和服务,方便了声明式配置和自动化。它拥有一个庞大且快速增长的生态系统。Kubernetes 的服务,支持和工具广泛可用。
为什么现在流行使用容器?
早期: 在物理服务器上面部署应用程序存在资源分配问题,因为其不能在物理服务器中的应用程序定义资源边界,导致应用程序资源利用不足而无法扩展.
后来: 为了解决该问题,引入了虚拟化技术, 虚拟化技术是指允许你在单个物理服务器的 CPU 上运行多个虚拟机,可以让多个应用程序在虚拟机之间进行隔离,具有一定的安全性, 每一个虚拟机就是一台完整的计算机, 在虚拟化硬件之上运行所有组件.
现在: 多数在物理服务器上面部署应用程序都是采kubectl用容器的方式,容器类似于虚拟机,它们都具有自己的文件系统、CPU、内存、进程空间等, 且由于它们与基础架构分离,因此可以跨云和 OS 发行版本进行移植。基于此特点被企业大范围使用.
为什么需要使用k8s容器?
若出现这样一个环境: 在生产环境中如果一个容器发生故障,则我们需要手动去启动另外一个容器,这样的操作是对我们的管理员来说是不太方便的, 若一个容器出现故障,另一个容器可以自动启动容器接管故障的容器,这样是最好的.
k8s就可以实现该效果,Kubernetes 提供了一个可弹性运行分布式系统的框架。 Kubernetes 会满足你的扩展要求、故障转移、部署模式等。
k8s功能: 服务发现和负载均衡, 存储编排, 自动部署和回滚, 自动完成装箱计算, 自我修复, 密钥与配置管理
名词解释
Secret有三种类型:
k8s的组成
k8s是由组件,API,对象等组成.
包含所有相互关联组件的 Kubernetes 集群图如下:
组件
Kubernetes 控制面 的核心是 API 服务器。 API 服务器负责提供 HTTP API,以供用户、集群中的不同部分和集群外部组件相互通信。
对象
Kubernetes对象是Kubernetes系统中的持久实体。Kubernetes使用这些实体来表示集群的状态.
具体来说,他们可以描述:
Kubernetes 架构
Kubernetes 架构由节点,控制面到节点通信, 控制器, 云控制器管理器组成.
master 流程图
节点
节点可以是一个虚拟机或者物理机器,取决于所在的集群配置。 每个节点包含运行 Pods 所需的服务, 这些 Pods 由 控制面 负责管理.
节点上的组件包括 kubelet、 容器运行时以及 kube-proxy。
节点状态
可以使用 kubectl 来查看节点状态和其他细节信息:
kubectl describe node <�节点名称>
一个节点包含以下信息:
控制面到节点通信
控制器
在 Kubernetes 中,控制器通过监控集群 的公共状态,并致力于将当前状态转变为期望的状态。
举个例子: 当前室内温度为20度, 我们通过调节遥控器,使其温度上升至24度, 这20度到24度的变化即为让其从当前状态接近期望状态。
控制器模式分为直接控制和通过API服务器来控制.
云控制器管理器
云控制器管理器是指嵌入特定云的控制逻辑的 控制平面组件。 云控制器管理器允许您链接聚合到云提供商的应用编程接口中, 并分离出相互作用的组件与您的集群交互的组件。
云控制器管理器中的控制器包括:
Kubernetes 安全性
云原生安全
云原生安全4个C: 云(Cloud)、集群(Cluster)、容器(Container)和代码(Code)
云原生安全模型的每一层都是基于下一个最外层,代码层受益于强大的基础安全层(云、集群、容器)。我们无法通过在代码层解决安全问题来为基础层中糟糕的安全标准提供保护。
基础设施安全
Kubetnetes 基础架构关注领域
![Java](https://tyye.cn/zb_users/theme/tpure/style/images/lazyload.png)
建议
通过网络访问 API 服务(控制平面)
所有对 Kubernetes 控制平面的访问不允许在 Internet 上公开,同时应由网络访问控制列表控制,该列表包含管理集群所需的 IP 地址集。
通过网络访问 Node(节点)
节点应配置为 仅能 从控制平面上通过指定端口来接受(通过网络访问控制列表)连接,以及接受 NodePort 和 LoadBalancer 类型的 Kubernetes 服务连接。如果可能的话,这些节点不应完全暴露在公共互联网上。
Kubernetes 云访问提供商的 API
每个云提供商都需要向 Kubernetes 控制平面和节点授予不同的权限集。为集群提供云提供商访问权限时,最好遵循对需要管理的资源的最小特权原则。Kops 文档提供有关 IAM 策略和角色的信息。
访问 etcd
对 etcd(Kubernetes 的数据存储)的访问应仅限于控制平面。根据配置情况,你应该尝试通过 TLS 来使用 etcd。更多信息可以在 etcd 文档中找到。
etcd 加密
在所有可能的情况下,最好对所有驱动器进行静态数据加密,但是由于 etcd 拥有整个集群的状态(包括机密信息),因此其磁盘更应该进行静态数据加密。
集群组件安全
容器安全
代码安全
Kubernetes架构常见问题
Kubernetes ATTACK 矩阵
信息泄露
云账号AK泄露
API凭证(即阿里云AccessKey)是用户访问内部资源最重要的身份凭证。用户调用API时的通信加密和身份认证会使用API凭证.
API凭证是云上用户调用云服务API、访问云上资源的唯一身份凭证。
API凭证相当于登录密码,用于程序方式调用云服务API.
k8s configfile泄露
kubeconfig文件所在的位置:
$HOME//config
Kubeconfig文件包含有关Kubernetes集群的详细信息,包括它们的位置和凭据。
云厂商会给用户提供该文件,以便于用户可以通过kubectl对集群进行管理. 如果攻击者能够访问到此文件(如办公网员工机器入侵、泄露到Github的代码等),就可以直接通过API Server接管K8s集群,带来风险隐患。
Master节点SSH登录泄露
常见的容器集群管理方式是通过登录Master节点或运维跳板机,然后再通过kubectl命令工具来控制k8s。
云服务器提供了通过ssh登陆的形式进行登陆master节点.
若Master节点SSH连接地址泄露,攻击者可对ssh登陆进行爆破,从而登陆上ssh,控制集群.
容器组件未鉴权服务
Kubernetes架构下常见的开放服务指纹如下:
注:前六个重点关注: 一旦被控制可以直接获取相应容器、相应节点、集群权限的服务
了解各个组件被攻击时所造成的影响
组件分工图:
假如用户想在集群里面新建一个容器集合单元, 流程如下:
攻击apiserver
apiserver介绍:在Kubernetes中,对于未鉴权对apiserver, 能访问到 apiserver 一般情况下就能获取了集群的权限.
在攻击者眼中Kubernetes APIServer
默认情况下apiserver都有鉴权:
未鉴权配置如下:
对于这类的未鉴权的设置来说,访问到 apiserver 一般情况下就获取了集群的权限:
如何通过apiserver来进行渗透,可参考:攻击kubelet
每一个Node节点都有一个kubelet(每个节点上运行的代理)服务,kubelet监听了,,等端口。
端口,是kubelet与apiserver进行通信对主要端口, 通过该端口,kubelet可以知道当前应该处理的任务.该端口在最新版Kubernetes是有鉴权的, 但在开启了接受匿名请求的情况下,不带鉴权信息的请求也可以使用提供的能力, 在Kubernetes早期,很多挖矿木马基于该端口进行传播.
在配置文件中,若进行如下配置,则可能存在未授权访问漏洞.
/var/bin/kubulet/config/yaml
若端口存在未授权访问漏洞,我们可以直接访问/pods进行查看
根据在pods中获取的信息,我们可以在容器中执行命令
curl -Gks{namespace}/{podname}/{containername} \-d input=1 -d output=1 -d tty=1 \-d command=whoami
上述命令得到websocket地址,连接websocket得到命令结果:
使用wscat工具连接websocket
wscat -c “{websocket}” --no-check
即可得到我们执行命令的结果.
获取token
/var/run/secrets//serviceaccount
然后即可访问kube-api server,获取集群权限
curl -ks -H Authorization: Bearer \ ttps://master:6443/api/v1/namespaces/{namespace}/secrets
攻击kubelet总体步骤如下:
攻击dashboard
dashboard登陆链接如下:
界面如下:
dashboard是Kubernetes官方推出的控制Kubernetes的图形化界面.在Kubernetes配置不当导致dashboard未授权访问漏洞的情况下,通过dashboard我们可以控制整个集群。
默认情况下, dashboard是需要进行鉴权操作的,当用户开启了enable-skip-login时可以在登录界面点击Skip跳过登录进入dashboard.
通过skip登陆的dashboard默认是没有操作集群的权限,因为Kubernetes使用RBAC(Role-based access control)机制进行身份认证和权限管理,不同的serviceaccount拥有不同的集群权限。
但有些开发者为了方便或者在测试环境中会为Kubernetes-dashboard绑定cluster-admin这个ClusterRole(cluster-admin拥有管理集群的最高权限).
为Kubernetes-dashboard绑定cluster-admin 设置如下:
后通过skip登陆dashboard便有了管理集群的权限.
创建Pod控制node节点,该pod主要是将宿主机根目录挂载到容器tmp目录下。
新建一个Pod如下:
通过该容器的tmp目录管理node节点的文件
攻击etcd
Kubernetes默认使用了etcd v3来存储数据, 若能naetcd对内暴露2379端口,本地127.0.0.1可免认证访问. 其他地址要带—endpoint参数和cert进行认证。
未授权访问流程:
攻击docker remote api(Docker daemon公网暴露)
2375是docker远程操控的默认端口,通过这个端口可以直接对远程的docker 守护进程进行操作。Docker 守护进程默认监听2375端口且未鉴权.
当机器以方式启动daemon时,可以在外部机器对该机器的docker daemon进行直接操作:
docker daemon -H=0.0.0.0:2375
之后依次执行systemctl daemon-reload、systemctl restart docker
外部主机使用 即可操作暴露2375端口的主机.
因此当你有访问到目标Docker API 的网络能力或主机能力的时候,你就拥有了控制当前服务器的能力。我们可以利用Docker API在远程主机上创建一个特权容器,并且挂载主机根目录到容器.
检测目标是否存在docker api未授权访问漏洞的方式也很简单,访问路径是否含有ContainersRunning、DockerRootDir等关键字。
攻击kubectl proxy
二次开发所产生的问题
管理Kubernetes无论是使用 kubectl 或 Kubernetes dashboard 的UI功能,其实都是间接在和 APIServer 做交互.
如果有需求对k8s进行二次开发的话,大部分的开发功能请求了 APIServer 的 Rest API 从而使功能实现的。
例如:
-
DELETE类似于这样去调用apiserver, 攻击者若修改namespace、pod和容器名, 那么即可造成越权.
推荐工具
Kube-Hunter扫描漏洞
kube-hunter是一款用于寻找Kubernetes集群中的安全漏洞扫描器
下载地址:强推)
CDK是一款为容器环境定制的渗透测试工具,在已攻陷的容器内部提供零依赖的常用命令及PoC/EXP。集成Docker/K8s场景特有的 逃逸、横向移动、持久化利用方式,插件化管理。
下载地址:参考链接
2021面试网络工程师的题目
面试的目的是确定面试者如何处理他们所选择的研究领域的问题,以及他们如何批判性地思考问题。下面我给大家带来2021面试网络工程师的题目参考,希望能帮助到大家!
Java多线程面试题目
1、什么是线程?
线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速。比如,如果一个线程完成一个任务要100毫秒,那么用十个线程完成改任务只需10毫秒。
2、线程和进程有什么区别?
线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。每个线程都拥有单独的栈内存用来存储本地数据。
3、如何在Java中实现线程?
两种方式类的实例就是一个线程但是它需要调用接口来执行,由于线程类本身就是调用的Runnable接口所以你可以继承类或者直接调用Runnable接口来重写run()方法实现线程。
4、Java 关键字volatile 与 synchronized 作用与区别?
它所修饰的变量不保留拷贝,直接访问主内存中的。
在Java内存模型中,有main memory,每个线程也有自己的memory(例如寄存器)。为了性能,一个线程会在自己的memory中保持要访问的变量的副本。这样就会出现同一个变量在某个瞬间,在一个线程的memory中的值可能与另外一个线程memory中的值,或者mainmemory中的值不一致的情况。 一个变量声明为volatile,就意味着这个变量是随时会被其他线程修改的,因此不能将它cache在线程memory中。
synchronized:
当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
四、当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用。
5、有哪些不同的线程生命周期?
当我们在Java程序中新建一个线程时,它的状态是New。当我们调用线程的start()方法时,状态被改变为Runnable。线程调度器会为Runnable线程池中的线程分配CPU时间并且讲它们的状态改变为Running。其他的线程状态还有Waiting,Blocked和Dead。
6、你对线程优先级的理解是什么?
每一个线程都是有优先级的,一般来说,高优先级的线程在运行时会具有优先权,但这依赖于线程调度的实现,这个实现是和操作系统相关的(OSdependent)。
我们可以定义线程的优先级,但是这并不能保证高优先级的线程会在低优先级的线程前执行。线程优先级是一个int变量(从1-10),1代表最低优先级,10代表最高优先级。
7、什么是死锁(Deadlock)?如何分析和避免死锁?
死锁是指两个以上的线程永远阻塞的情况,这种情况产生至少需要两个以上的线程和两个以上的资源。
分析死锁,我们需要查看Java应用程序的线程转储。我们需要找出那些状态为BLOCKED的线程和他们等待的资源。每个资源都有一个唯一的id,用这个id我们可以找出哪些线程已经拥有了它的对象锁。
避免嵌套锁,只在需要的地方使用锁和避免无限期等待是避免死锁的通常办法。
8、什么是线程安全?Vector是一个线程安全类吗?
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
一个线程安全的计数器类的同一个实例对象在被多个线程使用的情况下也不会出现计算失误。很显然你可以将集合类分成两组,线程安全和非线程安全的。Vector是用同步方法来实现线程安全的, 而和它相似的ArrayList不是线程安全的。
9、Java中如何停止一个线程?
Java提供了很丰富的API但没有为停止线程提供API。JDK 1.0本来有一些像stop(),suspend()和resume()的控制方法但是由于潜在的死锁威胁因此在后续的JDK版本中他们被弃用了,之后JavaAPI的设计者就没有提供一个兼容且线程安全的方法来停止一个线程。
当run()或者 call()方法执行完的时候线程会自动结束,如果要手动结束一个线程,你可以用volatile布尔变量来退出run()方法的循环或者是取消任务来中断线程。
10、什么是ThreadLocal?
ThreadLocal用于创建线程的本地变量,我们知道一个对象的所有线程会共享它的全局变量,所以这些变量不是线程安全的,我们可以使用同步技术。但是当我们不想使用同步的时候,我们可以选择ThreadLocal变量。
每个线程都会拥有他们自己的Thread变量,它们可以使用get()set()方法去获取他们的默认值或者在线程内部改变他们的值。ThreadLocal实例通常是希望它们同线程状态关联起来是privatestatic属性。
Kubernetes面试题汇总
1、什么是Kubernetes?
Kubernetes是一个开源容器管理工具,负责容器部署,容器扩缩容以及负载平衡。作为Google的创意之作,它提供了出色的社区,并与所有云提供商合作。因此,我们可以说Kubernetes不是一个容器化平台,而是一个多容器管理解决方案。
2、Kubernetes与Docker有什么关系?
众所周知,Docker提供容器的生命周期管理,Docker镜像构建运行时容器。但是,由于这些单独的容器必须通信,因此使用Kubernetes。因此,我们说Docker构建容器,这些容器通过Kubernetes相互通信。因此,可以使用Kubernetes手动关联和编排在多个主机上运行的容器。
3、什么是Container Orchestration?
考虑一个应用程序有5-6个微服务的场景。现在,这些微服务被放在单独的容器中,但如果没有容器编排就无法进行通信。因此,由于编排意味着所有乐器在音乐中和谐共处,所以类似的容器编排意味着各个容器中的所有服务协同工作以满足单个服务器的需求。
4、Kubernetes如何简化容器化部署?
由于典型应用程序将具有跨多个主机运行的容器集群,因此所有这些容器都需要相互通信。因此,要做到这一点,你需要一些能够负载平衡,扩展和监控容器的东西。由于Kubernetes与云无关并且可以在任何公共/私有提供商上运行,因此必须是您简化容器化部署的选择。
5、您对Kubernetes的集群了解多少?
Kubernetes背后的基础是我们可以实施所需的状态管理,我的意思是我们可以提供特定配置的集群服务,并且集群服务将在基础架构中运行并运行该配置。
因此,正如您所看到的,部署文件将具有提供给集群服务所需的所有配置。现在,部署文件将被提供给API,然后由集群服务决定如何在环境中安排这些pod,并确保正确运行的pod数量。
因此,位于服务前面的API,工作节点和节点运行的Kubelet进程,共同构成了Kubernetes集群。
6、Kubernetes Architecture的不同组件有哪些?
Kubernetes Architecture主要有两个组件 -主节点和工作节点。如下图所示,master和worker节点中包含许多内置组件。主节点具有kube-controller-manager,kube-apiserver,kube-scheduler等。而工作节点具有在每个节点上运行的kubelet和kube-proxy。
7、您能否介绍一下Kubernetes中主节点的工作情况?
Kubernetesmaster控制容器存在的节点和节点内部。现在,这些单独的容器包含在容器内部和每个容器内部,您可以根据配置和要求拥有不同数量的容器。
因此,如果必须部署pod,则可以使用用户界面或命令行界面部署它们。然后,在节点上调度这些pod,并根据资源需求,将pod分配给这些节点。kube-apiserver确保在Kubernetes节点和主组件之间建立通信。
8、kube-apiserver和kube-scheduler的作用是什么?
kube-apiserver遵循横向扩展架构,是主节点控制面板的前端。这将公开Kubernetes主节点组件的所有API,并负责在Kubernetes节点和Kubernetes主组件之间建立通信。
kube-scheduler负责工作节点上工作负载的分配和管理。因此,它根据资源需求选择最合适的节点来运行未调度的pod,并跟踪资源利用率。它确保不在已满的节点上调度工作负载。
9、你对Kubernetes的负载均衡器有什么了解?
负载均衡器是暴露服务的最常见和标准方式之一。根据工作环境使用两种类型的负载均衡器,即内部负载均衡器或外部负载均衡器。内部负载均衡器自动平衡负载并使用所需配置分配容器,而外部负载均衡器将流量从外部负载引导至后端容器。
10、Replica Set 和 Replication Controller之间有什么区别?
Replica Set 和 ReplicationController几乎完全相同。它们都确保在任何给定时间运行指定数量的pod副本。不同之处在于复制pod使用的选择器。ReplicaSet使用基于集合的选择器,而Replication Controller使用基于权限的选择器。
Equity-Based选择器:这种类型的选择器允许按标签键和值进行过滤。因此,在外行术语中,基于Equity的选择器将仅查找与标签具有完全相同短语的pod。
示例:假设您的标签键表示app = nginx,那么,使用此选择器,您只能查找标签应用程序等于nginx的那些pod。
Selector-Based选择器:此类型的选择器允许根据一组值过滤键。因此,换句话说,基于Selector的选择器将查找已在集合中提及其标签的pod。
示例:假设您的标签键在(nginx,NPS,Apache)中显示应用程序。然后,使用此选择器,如果您的应用程序等于任何nginx,NPS或Apache,则选择器将其视为真实结果。
渗透攻击的测试步骤
1.如果原始值为2,我们使用(1+1)或(3-1),程序作出相同回应,表明易受攻击
2.如果单引号被过滤掉,我们可以用ASCII命令,使它返回字符的数字化代码,如51-ASCII(1)
3.在URL编码中,&和=用于链接名称/值对,建立查询字符串应当分别使用%26和%3d进行编码
4.如查询字符串不允许使用空格,使用+或%20编码
5.分号被用于分割cookie自读,使用%3d编码
★关于网络工程师的面试题有哪些
★网络管理员面试题及答案大全
★最新的运维工程师面试题目整理
★网络测试工程师面试题及答案
★计算机网络面试题及参考答案
★网络工程师面试自我介绍范文五篇
★面试网络技术工程师的有哪些提问
★最新的it运维工程师面试题整理
免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。