关于后端:面试题精讲JavaSe和JavaEE的区别

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 系列文章地址 1. 什么是 JavaSE 和 JavaEE?JavaSE(Java Platform, Standard Edition)是 Java 平台的标准版,提供了 Java 语言的外围 API 和运行环境。它蕴含了 Java 编程语言、JVM(Java 虚拟机)、根底类库等组件,用于开发桌面应用程序、命令行工具等。JavaEE(Java Platform, Enterprise Edition)是 Java 平台的企业版,建设在 JavaSE 之上,为开发大型、分布式、可扩大的企业级利用提供反对。它蕴含了 JavaSE 的所有性能,并且还提供了一系列的 API 和服务,如 Servlet、JSP、EJB、JMS 等,用于开发 Web 利用、企业级应用服务器等。2. 为什么须要 JavaSE 和 JavaEE?JavaSE 提供了 Java 语言的外围性能和根底类库,能够满足一般应用程序的开发需要。而对于大型、简单的企业级利用来说,须要更多的性能和服务来反对分布式计算、事务管理、安全性等方面的需要,这就是 JavaEE 的作用所在。 JavaEE 通过提供一系列的 API 和服务,简化了企业级利用的开发过程,进步了开发效率和代码品质。同时,JavaEE 还提供了各种容器和中间件,如 Web 容器、应用服务器等,能够不便地部署和治理企业级利用。 3. JavaSE 和 JavaEE 的实现原理?JavaSE 和 JavaEE 都是基于 Java 语言开发的,应用了雷同的编程模型和工具链。它们之间的区别次要体现在提供的性能和服务上。 JavaSE 的实现原理包含以下几个方面: JVM:Java 虚拟机负责将 Java 字节码转换为机器码,并执行程序。Java 编译器:将 Java 源代码编译成字节码文件(.class)。类加载器:负责将字节码文件加载到内存中,并解析成可执行的类对象。垃圾回收器:主动回收不再应用的内存空间,开释资源。JavaEE 的实现原理则更加简单,波及到以下几个要害组件: ...

September 26, 2023 · 1 min · jiezi

关于后端:spring源码解析IOC开启-bean-的加载

概述后面咱们曾经剖析了spring对于xml配置文件的解析,将剖析的信息组装成 BeanDefinition,并将其保留注册到相应的 BeanDefinitionRegistry 中。至此,Spring IOC 的初始化工作实现。接下来咱们将对bean的加载进行摸索。 BeanFactory当咱们显示或者隐式地调用 getBean() 时,则会触发加载 bean 阶段。如下: public class AppTest { @Test public void MyTestBeanTest() { BeanFactory bf = new XmlBeanFactory( new ClassPathResource("spring-config.xml")); MyTestBean myTestBean = (MyTestBean) bf.getBean("myTestBean"); }}咱们看到这个办法是在接口BeanFactory中定义的,咱们看下BeanFactory体系结构,如下图所示: 从上图咱们看到: (1)BeanFactory作为一个主接口不继承任何接口,暂且称为一级接口。 (2)有3个子接口继承了它,进行性能上的加强。这3个子接口称为二级接口。 (3)ConfigurableBeanFactory能够被称为三级接口,对二级接口HierarchicalBeanFactory进行了再次加强,它还继承了另一个外来的接口SingletonBeanRegistry (4)ConfigurableListableBeanFactory是一个更弱小的接口,继承了上述的所有接口,无所不包,称为四级接口。(这4级接口是BeanFactory的根本接口体系。 (5)AbstractBeanFactory作为一个抽象类,实现了三级接口ConfigurableBeanFactory大部分性能。 (6)AbstractAutowireCapableBeanFactory同样是抽象类,继承自AbstractBeanFactory,并额定实现了二级接口AutowireCapableBeanFactory (7)DefaultListableBeanFactory继承自AbstractAutowireCapableBeanFactory,实现了最弱小的四级接口ConfigurableListableBeanFactory,并实现了一个外来接口BeanDefinitionRegistry,它并非抽象类。 (8)最初是最弱小的XmlBeanFactory,继承自DefaultListableBeanFactory,重写了一些性能,使本人更弱小。 定义BeanFactory,以Factory结尾,示意它是一个工厂类(接口), 它负责生产和治理bean的一个工厂。在Spring中,BeanFactory是IOC容器的外围接口,它的职责包含:实例化、定位、配置应用程序中的对象及建设这些对象间的依赖。BeanFactory只是个接口,并不是IOC容器的具体实现,然而Spring容器给出了很多种实现,如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等,其中XmlBeanFactory就是罕用的一个,该实现将以XML形式形容组成利用的对象及对象间的依赖关系。XmlBeanFactory类将持有此XML配置元数据,并用它来构建一个齐全可配置的零碎或利用。 BeanFactory是Spring IOC容器的鼻祖,是IOC容器的根底接口,所有的容器都是从它这里继承实现而来。可见其位置。BeanFactory提供了最根本的IOC容器的性能,即所有的容器至多须要实现的规范。 XmlBeanFactory,只是提供了最根本的IOC容器的性能。而且XMLBeanFactory,继承自DefaultListableBeanFactory。DefaultListableBeanFactory理论蕴含了根本IOC容器所具备的所有重要性能,是一个残缺的IOC容器。 ApplicationContext蕴含BeanFactory的所有性能,通常倡议比BeanFactory优先。 BeanFactory体系结构是典型的工厂办法模式,即什么样的工厂生产什么样的产品。BeanFactory是最根本的形象工厂,而其余的IOC容器只不过是具体的工厂,对应着各自的Bean定义方法。但同时,其余容器也针对具体场景不同,进行了裁减,提供具体的服务。 如下: Resource resource = new FileSystemResource("beans.xml");BeanFactory factory = new XmlBeanFactory(resource);ClassPathResource resource = new ClassPathResource("beans.xml");BeanFactory factory = new XmlBeanFactory(resource);ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml"});BeanFactory factory = (BeanFactory) context;根本就是这些了,接着应用getBean(String beanName)办法就能够获得bean的实例;BeanFactory提供的办法及其简略,仅提供了六种办法供客户调用: ...

September 26, 2023 · 8 min · jiezi

关于后端:面试题精讲Java语言概念

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 系列文章地址 1. 什么是Java语言?Java是一种面向对象的编程语言,由Sun Microsystems(当初是Oracle)于1995年推出。它被设计成具备简略、可移植和安全性强的特点,并且能够利用于各种平台上的软件开发。 Java语言具备以下特点: 面向对象:Java反对面向对象的编程范式,通过类和对象来组织代码。跨平台:Java程序能够在不同的操作系统上运行,只需将源代码编译为字节码文件(.class),而后在Java虚拟机(JVM)上执行。主动内存治理:Java提供了垃圾回收机制,主动治理内存调配和开释,缩小了程序员对内存治理的累赘。异样解决:Java引入了异样解决机制,使得程序可能更好地处理错误和异常情况。多线程反对:Java提供了多线程编程的反对,容许程序同时执行多个工作。丰盛的库:Java领有宏大而丰盛的规范类库,蕴含了各种罕用的功能模块,如输入输出、网络通信、数据库连贯等。2. 为什么须要Java语言?Java语言之所以宽泛应用,次要有以下几个起因: 跨平台性:Java程序能够在不同的操作系统上运行,这使得开发人员可能编写一次代码,而后在多个平台上部署和执行。这种可移植性大大简化了软件开发和保护的工作。安全性:Java具备内置的平安机制,如字节码验证、平安沙箱等,能够避免恶意代码对计算机系统造成侵害。这使得Java成为开发网络应用和浏览器插件等平安敏感畛域的首选语言。丰盛的库反对:Java领有宏大而丰盛的规范类库,其中蕴含了各种罕用的功能模块,如输入输出、网络通信、数据库连贯等。这些库提供了高效、牢靠的解决方案,减速了开发过程。宽泛的应用领域:因为其灵活性和可扩展性,Java被广泛应用于各个领域,包含企业级利用、挪动利用、嵌入式零碎、游戏开发等。无论是大型企业还是初创公司,都能够利用Java构建弱小的软件解决方案。3. Java语言的实现原理?Java语言的实现原理次要波及以下几个方面: 编译:Java源代码通过Java编译器(javac)编译成字节码文件(.class),其中蕴含了与特定平台无关的中间代码。虚拟机:Java虚拟机(JVM)是Java语言的外围组件,负责解释和执行字节码文件。它提供了内存治理、垃圾回收、线程调度等性能,并将字节码转换为底层操作系统可能了解的机器指令。类加载:在运行时,JVM会动静加载字节码文件并生成对应的类对象。类加载器负责从文件系统或网络中加载类文件,并将其转换为可执行的类对象。即时编译:JVM还具备即时编译(Just-In-Time Compilation)的能力,能够将频繁执行的字节码转换为本地机器代码,以进步程序的执行效率。垃圾回收:Java的垃圾回收机制主动治理内存调配和开释,缩小了程序员对内存治理的累赘。垃圾回收器会周期性地查看不再应用的对象,并开释其占用的内存空间。4. Java语言的应用示例上面是一个简略的Java程序示例,实现了计算两个数之和并输入后果的性能: public class HelloWorld { public static void main(String[] args) { int num1 = 10; int num2 = 20; int sum = num1 + num2; System.out.println("Sum: " + sum); }}5. Java语言的长处Java语言具备以下几个长处: 跨平台性:Java程序能够在不同的操作系统上运行,实现了一次编写、到处运行的指标。面向对象:Java是一种纯正的面向对象编程语言,反对封装、继承和多态等个性,使得代码更加模块化、可重用和易于保护。丰盛的类库:Java领有宏大而丰盛的规范类库,提供了各种罕用的功能模块,如输入输出、网络通信、数据库连贯等。这些库可能极大地提高开发效率。安全性:Java具备内置的平安机制,如字节码验证、平安沙箱等,能够避免恶意代码对计算机系统造成侵害。多线程反对:Java提供了多线程编程的反对,容许程序同时执行多个工作,进步了程序的并发性能。6. Java语言的毛病Java语言也存在一些毛病: 绝对较慢:因为Java程序须要通过JVM解释执行,相比于间接编译成机器码的语言,如C++,Java程序的性能较低。内存耗费大:因为Java的主动内存管理机制,须要额定的内存空间来保护对象和垃圾回收信息,导致Java应用程序占用的内存较多。学习曲线平缓:绝对于其余编程语言,Java的语法和概念较为简单,初学者可能须要破费更多的工夫和精力来把握。7. Java语言的应用注意事项在应用Java语言时,须要留神以下几点: 版本兼容性:不同版本的Java语言可能存在一些差别,特地是在应用新个性或库时。因而,在开发过程中要确保所应用的Java版本与指标平台的兼容性。异样解决:Java引入了异样解决机制,倡议在代码中正当地捕捉和解决异样,以防止程序解体或产生未知谬误。资源开释:Java虚构机会主动进行垃圾回收,但并不代表所有资源都会被及时开释。对于一些须要手动敞开的资源,如文件、数据库连贯等,应该及时开释,以防止资源泄露。安全性:尽量避免应用不平安的代码和库,以避免歹意攻打或数据泄露。在网络通信、文件操作等敏感场景下,要留神增强安全措施。8. 总结Java语言是一种面向对象的编程语言,具备跨平台性、安全性、丰盛的类库反对等长处。它通过JVM实现了字节码解释执行,并提供了主动内存治理、多线程反对等性能。然而,Java也存在绝对较慢、内存耗费大等毛病。在应用Java时,须要留神版本兼容性、异样解决、资源开释和安全性等方面的问题。 <!-- md tj.md --> 本文由mdnice多平台公布

September 26, 2023 · 1 min · jiezi

关于后端:Netflix-零配置服务网格与按需集群发现

本文翻译自在 David Vroom, James Mulcahy, Ling Yuan, Rob Gulewich 编写的 Netflix 博客 Zero Configuration Service Mesh with On-Demand Cluster Discovery。 Netflix 置信大家并不生疏,在 Spring Cloud 生态中就有 Netflix 全家桶。多年前,我也曾将基于 Netflix OSS 构建的微服务架构搬上了 Kubernetes 平台,并继续折腾好几年。 Spring Cloud Netflix 有着宏大的用户群以及用户场景,其提供了微服务治理的一整套解决方案:服务发现 Eureka、客户端负载平衡 Ribbon、断路器 Hystrix、微服务网格 Zuul。 有过雷同经验的小伙伴应该都会同感,这样一套微服务解决方案的架构,通过多年的演进也会让人痛苦不堪:复杂度越来越高、版本碎片化重大、多语言多框架的反对和性能无奈对立等等。这也是 Netflix 本人也不得不面对的问题,随后他们将眼光转向了服务网格,并寻求一个无缝迁徙的计划。 这篇文章中,他们给出了答案:Netflix 与社区单干,并自建管制立体与已有的服务发现体系兼容。这套实现下来可能并不容易,也未看到他们要将其开源的想法,然而至多能够给大家一个参考。 顺便预报一下本人正在打算的一篇,如何将微服务平滑迁徙到 Flomesh 服务网格平台。不止无缝兼容 Eureka,还有 HashiCorp Consul,将来还会兼容更多的服务发现计划。 以下是原文的翻译: 在这篇文章中,咱们将探讨 Netflix 服务网格(Service Mesh)实际的相干信息:历史背景、动机,以及咱们如何与 Kinvolk 和 Envoy 社区单干,在简单的微服务环境中推动服务网格落地的一个特色:按需集群发现(On-demand Cluster Discovery)。 Netflix 的 IPC 简史Netflix 是晚期云计算的采纳者,特地是对于大规模的公司:咱们在 2008 年开始了迁徙,并且到 2010 年,Netflix的流媒体齐全运行在AWS上。明天咱们领有丰盛的工具,包含开源和商业的,所有这些都是为云原生环境设计的。然而,在 2010 年,简直没有这样的工具存在:CNCF 直到 2015 年才成立!因为没有现成的解决方案,咱们须要本人构建它们。 ...

September 26, 2023 · 2 min · jiezi

关于后端:制作python包并上传pypi

平时写Python,须要用到一个新包时,习惯了pip install packageName,写多了就会想,这些包都是怎么来的?本人能不能"制作"一个,任何人也都能够通过pip装置? 有此想法,躬行实践.答案显然是必定的,而且难度也绝没有想的那样大,或者说 It is easy. 1.编写代码如要制作的包名为dashen,新建如下目录构造 其中两个__init__.py为空即可README.md写一些该package的介绍,非必选your_func.py是具体的性能实现,在此示例如下:def dashen_address(): print('www.dashen.tech')def dashen_master(): print('shuang.cui')def author_hometown(): print('山东邹平')setup.py内容如下:import setuptoolswith open("README.md","r") as fh: long_description = fh.read()setuptools.setup( # 包的散发名称,应用字母、数字、_、- name="dashen", # 版本号, 版本号标准:https://www.python.org/dev/peps/pep-0440/ version="0.0.1", # 作者名 author="fliter", # 作者邮箱 author_email="i@dashen.tech", # 包的简介形容 description="我的第二个python包", # 包的具体介绍(个别通过加载README.md) long_description=long_description, # 和上条命令配合应用,申明加载的是markdown文件 long_description_content_type="text/markdown", # 我的项目开源地址 url="https://dashen.tech", # 如果我的项目由多个文件组成,咱们能够应用find_packages()主动发现所有包和子包,而不是手动列出每个包,在这种状况下,包列表将是example_pkg packages=setuptools.find_packages(), # 对于包的其余元数据(metadata) classifiers=[ # 该软件包仅与Python3兼容 "Programming Language :: Python :: 3", # 依据MIT许可证开源 "License :: OSI Approved :: MIT License", # 与操作系统无关 "Operating System :: OS Independent", ],)2.账号注册及打包注册Pypi更新pip,setuptools和wheelpip install --upgrade pip setuptools wheel ...

September 25, 2023 · 1 min · jiezi

关于后端:值类型与引用类型值传递与引用传递

值传递和援用传递 Go语言参数传递是传值还是传援用 一文整得明明白白~ Go全部都是值传递,不存在援用传递 值传递 是原始值copy出一份正本,而后传递; 援用传递 是间接传原始值的指针; 值传递并非不能批改原始值,当原始值是援用类型时(指针、map、slice、chan等这些),值传递就能够批改原始值 (值传递传的指针是原始值指针的正本,但两个指针都指向同一个地址) 值类型和援用类型 slice,map,channel,interface,func这5种数据类型 是援用类型,都(或者至多某个字段)是指针 (援用类型能够看作是对指针的封装) (应用make函数创立的map,channel 其实都是一个指针,slice是其构造体SliceHeader的Data字段是指针) // SliceHeader is the runtime representation of a slice.// It cannot be used safely or portably and its representation may// change in a later release.// Moreover, the Data field is not sufficient to guarantee the data// it references will not be garbage collected, so programs must keep// a separate, correctly typed pointer to the underlying data.type SliceHeader struct { Data uintptr Len int Cap int}int、float、bool、array、sturct 是值类型 ...

September 25, 2023 · 1 min · jiezi

关于后端:三个月内遭遇的第二次比特币勒索

早前搭过一个wiki (可点击wiki.dashen.tech 查看),用于"团队合作与常识分享".把游客账号给一位前共事,其告知登录出错. 用我记录的账号密码登录,同样报错; 关上数据库一看,纳闷全消. To recover your lost Database and avoid leaking it: Send us 0.05 Bitcoin (BTC) to our Bitcoin address 3F4hqV3BRYf9JkPasL8yUPSQ5ks3FF3tS1 and contact us by Email with your Server IP or Domain name and a Proof of Payment. Your Database is downloaded and backed up on our servers. Backups that we have right now: mm_wiki, shuang. If we dont receive your payment in the next 10 Days, we will make your database public or use them otherwise.(依照今日比特币价格,0.05比特币折合人民币4 248.05元..) ...

September 25, 2023 · 1 min · jiezi

关于后端:听GPT-讲Istio源代码security2

File: istio/security/pkg/server/ca/authenticate/oidc.go文件形容: oidc.go文件是istio/security/pkg/server/ca/authenticate门路下的文件。该文件实现了基于OIDC验证的身份验证器性能。 _变量作用: _变量是一个空标识符,用于抛弃不须要的返回值。在该文件中,它能够疏忽某些没有应用的返回值。构造体作用: JwtAuthenticator构造体是一个OIDC身份验证器的实现。它蕴含了OIDC身份验证所需的属性和办法。JwtPayload构造体是JWT的负载局部的示意。它蕴含了JWT中的申明(claims)。函数作用: NewJwtAuthenticator函数是一个工厂函数,用于创立并返回一个新的JwtAuthenticator实例。它承受必须的OIDC配置参数(如提供者的URL、客户端ID等)。Authenticate函数用于验证传入的JWT令牌的有效性。它承受JWT令牌字符串,并返回一个布尔值,示意该令牌是否无效。authenticate函数是JwtAuthenticator构造体的办法,用于理论执行JWT令牌的验证过程。它承受JWT令牌字符串,并返回一个布尔值,示意该令牌是否无效。checkAudience函数用于查看JWT令牌的受众(audience)是否与预期值匹配。它承受JWT令牌字符串和预期的受众列表,并返回一个布尔值,示意是否匹配。AuthenticatorType函数是JwtAuthenticator构造体的办法,用于返回验证器的类型。以上就是oidc.go文件中各个变量和函数的作用。 File: istio/security/pkg/server/ca/node_auth.go在Istio我的项目中,istio/security/pkg/server/ca/node_auth.go文件的作用是实现 Istio Secure Ingress Gateway(SIG)中节点身份验证的相干性能。 该文件定义了一个名为 NodeAuthorizer 的接口和几个实现该接口的构造体。这些构造体别离是: RequestAuthorizer: 用于验证申请是否具备无效的受权。NewNodeAuthorizer: 用于创立新的节点受权器对象。authenticateImpersonation: 用于验证代理受权是否容许身份假冒。接下来,咱们将逐个介绍这些构造体以及函数的具体作用: NodeAuthorizer 这个接口定义了节点受权器的基本功能和行为。该接口蕴含了 Authorize 函数,用于验证申请是否具备无效受权。RequestAuthorizer 这个构造体是 NodeAuthorizer 接口的一个实现。次要性能是验证申请是否具备无效的受权。它通过读取申请中的凭证信息,并与Istio的受权策略进行比拟来进行验证。如果申请中的凭证信息无效且与受权策略匹配,则申请被受权通过。NewNodeAuthorizer 这个函数用于创立一个新的节点受权器对象,并返回该对象的指针。它会依据传入的参数来创立不同类型的节点受权器对象,包含 RequestAuthorizer。authenticateImpersonation 这个函数用于验证代理受权是否容许身份假冒。身份假冒是一种身份验证技术,容许代理以一个实体的身份进行申请,而不是理论发动申请的实体身份。这种技术在安全性和隐衷爱护方面十分重要。该函数会查看申请中的凭证信息,并与Istio的代理受权配置进行比拟来验证身份假冒。总结:istio/security/pkg/server/ca/node_auth.go文件中定义了用于节点身份验证的相干构造体和函数。其中 NodeAuthorizer 接口和 RequestAuthorizer 构造体用于验证申请的受权信息,NewNodeAuthorizer 函数用于创立受权器对象,authenticateImpersonation 函数用于验证身份假冒。这些性能在Istio的安全性和身份验证机制中起着重要的作用。 File: istio/security/pkg/testing/sdsc/sdsclient.go在Istio我的项目中,sdsclient.go文件位于istio/security/pkg/testing/sdsc/目录下,它的作用是实现与SDS (Secret Discovery Service)服务器的通信,用于动静治理和更新Istio代理的密钥和证书。 上面对文件中的构造体和函数进行具体介绍: 构造体Client:代表SDS客户端,用于与SDS服务器进行交互。它蕴含一个grpc.ClientConn,用于与SDS服务器建设连贯,并通过此连贯发送和接管申请。ClientOptions:用于配置SDS客户端的选项。其中蕴含以下字段: Address:SDS服务器的地址。Port:SDS服务器的端口。RootCA:SDS服务器的根证书文件门路。函数constructSDSRequestContext:依据提供的证书和密钥,构建SDS申请上下文。该上下文将用于向SDS服务器发送申请,以获取证书和密钥。NewClient:创立新的SDS客户端。依据提供的选项创立一个新的Client实例,并返回该实例。Start:启动SDS客户端。它负责建设客户端和SDS服务器之间的连贯。Stop:进行SDS客户端。敞开与SDS服务器的连贯。WaitForUpdate:期待并接管来自SDS服务器的证书和密钥的更新。在接管到更新后,将触发回调函数。Send:向SDS服务器发送申请,以获取证书和密钥。ValidateResponse:验证从SDS服务器接管的证书和密钥的有效性。这些函数组合在一起,使SDS客户端可能与SDS服务器进行通信,并治理和更新Istio代理的密钥和证书。 File: istio/security/pkg/credentialfetcher/plugin/token.go在Istio我的项目中,istio/security/pkg/credentialfetcher/plugin/token.go文件的作用是实现了用于获取令牌凭据的插件接口。 该文件中定义了KubernetesTokenPlugin构造体,它是TokenPlugin接口的一个实现。该构造体的次要作用是通过Kubernetes的Service Account令牌,获取到拜访Kubernetes API所需的令牌凭据。 _这个变量在Go语言中示意疏忽某个值,罕用于疏忽不须要应用的返回值或未应用的变量。 KubernetesTokenPlugin构造体负责实现一些接口办法,其中: CreateTokenPlugin函数是一个工厂函数,用于创立并返回KubernetesTokenPlugin对象。GetPlatformCredential函数用于获取插件所需的平台凭据。在该构造体中,该函数返回一个空的凭据切片。GetIdentityProvider函数用于获取身份提供者的惟一标识符。在该构造体中,该函数返回kubernetes作为惟一标识符。Stop函数用于进行插件的运行。在该构造体中,该函数为空实现。应用token.go文件的目标是为了提供一个插件接口,以便于获取到Kubernetes API的拜访令牌凭据。插件的实现能够依据具体情况从不同的起源获取凭据,例如从Kubernetes的Service Account令牌中获取。这样,其余组件就能够通过插件接口对立获取到凭据,而无需关怀具体的实现细节。 File: istio/security/pkg/credentialfetcher/plugin/gce.go在Istio我的项目中,istio/security/pkg/credentialfetcher/plugin/gce.go文件的作用是为了从Google Compute Engine(GCE)实例元数据服务中获取身份验证凭据。 让咱们一一介绍这些变量和函数的作用: 变量: gcecredLog:这是用于日志记录的logger对象。rotationInterval:定义了凭据轮换的工夫距离。gracePeriod:定义了凭据在过期前的宽限期。rotateToken:一个布尔值,批示是否启用凭据轮换。构造体: GCEPlugin:代表一个GCE插件对象,用于治理与GCE实例元数据服务的交互。函数: SetTokenRotation:设置是否启用凭据轮换。CreateGCEPlugin:创立一个GCE插件对象。Stop:进行凭据轮换的作业。startTokenRotationJob:启动凭据轮换的作业。rotate:执行凭据轮换。shouldRotate:查看凭据是否须要进行轮换。GetPlatformCredential:从GCE实例元数据服务获取平台凭据。GetIdentityProvider:获取身份提供者。总体而言,gce.go文件实现了与GCE实例元数据服务进行交互,获取身份验证凭据,并解决凭据的轮换。这对于Istio我的项目中应用GCE实例的身份验证十分重要,以确保利用程序运行时领有无效且平安的凭据。 File: istio/security/pkg/credentialfetcher/fetcher.go在Istio我的项目中,istio/security/pkg/credentialfetcher/fetcher.go文件是Istio的平安插件之一。它的作用是从不同凭据源中检索和治理证书和密钥,以供Istio进行TLS身份验证和平安通信应用。 该文件中的NewCredFetcher函数有以下几个作用: NewCredFetcher函数是一个构造函数,用于创立CredFetcher实例。CredFetcher是一个用于证书和密钥检索的接口,它定义了几种办法来获取和治理不同凭据源的凭据。NewCertFetcher函数是NewCredFetcher的一部分,它负责创立证书检索器,用于从不同的凭据源获取TLS证书。证书用于对身份进行认证,并用于建设TLS连贯。NewKeyFetcher函数是NewCredFetcher的另一部分,它负责创立密钥检索器,用于从不同的凭据源获取密钥。密钥用于加密和解密通信内容以确保安全性。这些NewCredFetcher函数是通过应用不同的实现,依据配置和环境变量,从不同的凭据源(如Kubernetes Secrets、Vault等)中获取证书和密钥。依据所选的凭据源和配置,NewCredFetcher函数返回适当的CredFetcher实例,该实例通过定义的接口办法来获取和治理凭据。 因为Istio的安全性高度依赖于正确的证书和密钥治理,fetcher.go文件中的NewCredFetcher办法是要害之一,确保Istio能够取得所需的凭据来爱护其通信和身份验证。 ...

September 25, 2023 · 2 min · jiezi

关于后端:听GPT-讲Istio源代码security1

File: istio/security/proto/providers/google/meshca.pb.go在istio我的项目中,istio/security/proto/providers/google/meshca.pb.go这个文件是用于定义与Google Mesh CA提供者相干的协定缓冲区音讯的文件。 这个文件次要蕴含以下内容: File_security_proto_providers_google_meshca_proto变量: 是用于保留meshca.proto文件的门路。file_security_proto_providers_google_meshca_proto_rawDesc、file_security_proto_providers_google_meshca_proto_rawDescOnce和file_security_proto_providers_google_meshca_proto_rawDescData变量:用于存储原始描述符数据,以及一些初始化描述符的函数。file_security_proto_providers_google_meshca_proto_msgTypes变量:用于存储meshca.proto文件中定义的所有音讯类型。file_security_proto_providers_google_meshca_proto_goTypes变量:用于存储meshca.proto文件中定义的所有Go类型。file_security_proto_providers_google_meshca_proto_depIdxs变量:用于存储meshca.proto文件中定义的所有依赖的音讯类型索引。MeshCertificateRequest构造体,定义了向Mesh CA申请证书时须要发送的申请信息,包含申请ID、CSR(证书签名申请)和证书的有效期等。MeshCertificateResponse构造体,定义了从Mesh CA接管到的证书响应的音讯格局,包含申请ID、证书链和有效期等。 Reset、String、ProtoMessage、ProtoReflect、Descriptor、GetRequestId、GetCsr、GetValidity、GetCertChain、file_security_proto_providers_google_meshca_proto_rawDescGZIP、init和file_security_proto_providers_google_meshca_proto_init等函数,是用于操作和解决与Google Mesh CA通信的协定音讯的一些帮忙函数。 这些变量和函数的作用是为了定义和解决与Google Mesh CA提供者之间的通信协议,使得istio可能与Google Mesh CA进行平安证书的交互操作。 File: istio/security/proto/providers/google/meshca_grpc.pb.go在istio我的项目中,istio/security/proto/providers/google/meshca_grpc.pb.go文件是由Protocol Buffers工具主动生成的,用于定义与Google Mesh CA服务之间的gRPC通信的接口和数据结构。 该文件中的MeshCertificateService_ServiceDesc变量是一个gRPC服务描述符,用于形容MeshCertificateService服务的各种信息,包含服务名称、办法列表等。 MeshCertificateServiceClient和meshCertificateServiceClient是客户端API的构造体定义,用于与Google Mesh CA服务进行通信。MeshCertificateServiceClient提供了与Mesh CA服务交互的各种办法,如创立证书、验证证书等,meshCertificateServiceClient是对MeshCertificateServiceClient构造体的一个包装。 MeshCertificateServiceServer和UnimplementedMeshCertificateServiceServer是与Mesh CA服务交互的服务器API的构造体定义。MeshCertificateServiceServer定义了解决来自客户端的申请的办法,而UnimplementedMeshCertificateServiceServer是一个空的、未实现的服务构造体。 UnsafeMeshCertificateServiceServer是一个与UnimplementedMeshCertificateServiceServer构造体关联的未实现的gRPC服务,用于解决来自客户端的申请。 NewMeshCertificateServiceClient是一个工厂函数,用于创立新的MeshCertificateServiceClient实例。 CreateCertificate是一个用于创立证书的函数。 mustEmbedUnimplementedMeshCertificateServiceServer是一个兼容函数,用于确保gRPC服务构造体UnimplementedMeshCertificateServiceServer正确实现了gRPC服务接口。 RegisterMeshCertificateServiceServer用于注册MeshCertificateServiceServer构造体实例,使其可能接管并解决来自客户端的申请。 _MeshCertificateService_CreateCertificate_Handler是一个gRPC服务处理函数,用于解决CreateCertificate办法的具体实现。 File: istio/security/pkg/util/jwtutil.goistio/security/pkg/util/jwtutil.go文件位于Istio我的项目的istio/security包中。这个文件提供了一些用于解决JSON Web Tokens (JWT) 的工具函数和构造体。 首先,让咱们理解一下JWT是什么。JWT是一种凋谢规范,用于在不同实体之间平安地传输信息。它由三个局部组成:头部(Header)、载荷(Payload)和签名(Signature)。头部通常蕴含加密算法和类型信息,载荷蕴含须要传输的数据,签名用于验证真实性和完整性。 在jwtutil.go文件中,有三个次要的构造体:jwtPayload、Claims和Header。它们别离示意JWT的载荷、申明和头部。这些构造体用于解析和验证JWT的不同局部。 jwtPayload构造体示意JWT的载荷局部,其中蕴含了一些规范官网申明(例如:"exp"、"aud"等)。它还有一些不便的办法用于提取和验证特定的申明数据。 GetExp函数返回JWT的过期工夫(exp申明)。GetAud函数返回JWT的指标受众(aud申明)。IsK8SUnbound函数用于判断JWT是否不受限制地绑定到Kubernetes ServiceAccount。Claims构造体示意JWT的申明局部,用于存储和拜访JWT的所有申明。 ExtractJwtAud函数从JWT中提取受众(aud)申明。parseJwtClaims函数用于解析JWT的申明局部,返回Claims对象。DecodeJwtPart函数用于对JWT的指定局部进行解码,并返回对应的字节数组。Header构造体示意JWT的头部,用于存储和拜访JWT的头部信息。这些工具函数和构造体提供了一种简便的形式来解决JWT,例如提取和验证JWT中的申明、解析JWT的各个局部,以及判断JWT是否受限制地绑定到Kubernetes ServiceAccount等。 总结:jwtutil.go文件中的jwtPayload构造体和相干的函数提供了解决JWT载荷的办法,而Claims构造体和相干的函数用于解决JWT的申明局部。同时,Header构造体用于解决JWT的头部信息。这些工具函数和构造体使得在Istio我的项目中解决JWT变得更加不便和牢靠。 File: istio/security/pkg/util/mock/fakecertutil.go在Istio我的项目中,istio/security/pkg/util/mock/fakecertutil.go文件的作用是提供一个用于测试的伪造证书工具。它用于模仿生成和治理证书的过程,以便在测试中应用。 该文件定义了三个构造体FakeCertUtil、FakeCertificate和FakeKeys,并提供了一些办法用于创立和治理伪造证书。 FakeCertUtil构造体:该构造体实现了CertificateUtil接口,并提供了生成证书、加载证书和其余伪造证书的办法。它是伪造证书工具的次要实现。FakeCertificate构造体:该构造体用于示意伪造的证书。它蕴含证书的根本信息,如Common Name、Subject等,并提供了一些办法用于获取证书的各种属性。FakeKeys构造体:该构造体用于示意伪造的密钥。它蕴含密钥的次要信息,并提供了一些办法用于获取和治理密钥。FakeCertUtil构造体提供了以下几个办法: GenerateRootCertAndKey():生成伪造的根证书和密钥。GenerateServerCertAndKey():生成伪造的服务器证书和密钥。GenerateClientCertAndKey():生成伪造的客户端证书和密钥。LoadCertAndKey():加载伪造的证书和密钥。GetFakeRootCert():获取伪造的根证书。GetFakeServerCertAndKey():获取伪造的服务器证书和密钥。GetFakeClientCertAndKey():获取伪造的客户端证书和密钥。GetWaitTime这几个函数用于提供等待时间的工具函数。这些函数用于模仿期待的过程,并返回一个等待时间,用于测试时控制代码的执行程序和并发状况。这些函数依据不同的状况返回不同的等待时间,以便测试代码的各种分支和状况。具体的作用和应用场景能够依据理论的测试需要来确定。 File: istio/security/pkg/util/certutil.go在Istio我的项目中,istio/security/pkg/util/certutil.go文件是用于证书治理的工具类。该文件定义了CertUtil和CertUtilImpl两个构造体,以及NewCertUtil和GetWaitTime两个函数。 CertUtil构造体是一个接口,定义了证书治理的一些基本操作办法,如生成证书、加载证书、验证证书等。CertUtilImpl是CertUtil的实现,实现了这些操作方法。 NewCertUtil函数用于创立一个CertUtilImpl的实例,来进行证书治理。它接管配置参数,并将其用于创立CertUtilImpl实例。通过NewCertUtil函数,咱们能够创立一个CertUtilImpl实例,并应用其提供的办法进行证书治理。 GetWaitTime函数是用于获取等待时间的办法。它接管一个Duration类型的参数,示意期待的持续时间,而后依据此信息计算等待时间并返回。 总之,certutil.go文件提供了一些证书治理的工具类和办法,用于生成、加载、验证证书等操作,并提供了一些便捷的函数来创立证书治理实例和获取等待时间。这些性能对于Istio我的项目中的证书治理模块十分重要。 File: istio/security/pkg/k8s/tokenreview/k8sauthn.go在Istio我的项目中,istio/security/pkg/k8s/tokenreview/k8sauthn.go文件的作用是执行与Kubernetes令牌验证相干的操作。它提供了与Kubernetes API服务器进行交互的性能,以验证JWT(JSON Web Token)令牌的有效性并提取额定的信息。 上面是k8sauthn.go文件中几个重要函数的作用阐明: ValidateK8sJwt: 此函数用于验证Kubernetes中的JWT令牌的有效性。它接管一个JWT令牌字符串作为参数,并应用Kubernetes API服务器提供的TokenReview接口执行验证操作。验证后果会作为构造体返回。getTokenReviewResult: 此函数用于执行TokenReview申请,并解析返回的后果。它接管一个TokenReview申请对象作为参数,并应用Kubernetes API服务器提供的TokenReview接口执行令牌验证操作。验证后果会作为构造体返回。extractExtra: 这个函数用于从验证后果中提取额定的信息。在验证JWT令牌后,可能会有一些额定的信息与用户相关联,如用户的身份信息、角色等。这个函数用于从验证后果中解析和提取这些额定信息,并将其返回。总的来说,k8sauthn.go文件中的函数提供了与Kubernetes令牌验证和相干操作的性能,包含验证JWT令牌的有效性,并提取验证后果中的额定信息。这些性能是Istio我的项目中用于平安拜访和身份验证的要害局部。 ...

September 25, 2023 · 2 min · jiezi

关于后端:听GPT-讲Istio源代码pkg13

File: istio/pkg/monitoring/counter.go在Istio我的项目中,istio/pkg/monitoring/counter.go文件是用于实现计数器性能的。它提供了用于计算和记录各种类型的计数器的性能。 首先,下划线(_)是一个非凡标识符,被用作“空标识符”。在Go中,它能够用于示意一个不关怀的变量或值,通常用于疏忽某些返回后果或未应用的变量。 在counter.go文件中,_这些变量用于疏忽一些返回值,以达到疏忽不关怀的成果。 接下来,counter.go中定义了几个构造体,用于示意不同类型的计数器: counter: 示意一个通用计数器的构造体。它蕴含了一个名称字段用于标识计数器,一个计数器的值,以及一个统计计数器增量的办法。integerCounter: 示意一个整数计数器的构造体。它继承了counter构造体,并减少了一个办法用于递增计数器的值。floatCounter: 示意一个浮点数计数器的构造体。它也继承了counter构造体,并减少了一个办法用于递增计数器的值。这些构造体提供了不同类型的计数器对应的性能,并能够依据须要将其封装在不同的上下文中应用。 接下来是一些次要函数的介绍: newCounter: 是一个工厂函数,用于创立一个counter构造体的实例。它承受一个字符串作为计数器的名称,并返回一个新的计数器实例。该函数还会主动注册计数器,以便在监控过程中能够应用。Record: 是一个办法,用于记录和减少计数器的值。它承受一个参数,用于指定要减少的计数器值。With: 是一个装璜器函数,用于包装一个计数器,并返回一个新的counter构造体实例。它承受一个原始的counter实例和一个可变的参数列表,而后将计数器增量值传递给原始counter。通过应用这些函数和构造体,能够不便地创立和治理各种类型的计数器,以用于监控和记录不同的零碎指标。 File: istio/pkg/monitoring/distribution.go在Istio我的项目中,istio/pkg/monitoring/distribution.go文件的作用是提供一组用于监督和记录分布式数据的工具办法和数据结构。 文件中的_变量用于疏忽未应用的导入包,以避免编译器报错。 distribution构造体示意一个分布式数据的统计散布。它蕴含了以下字段: Count用于记录样本的数量。Sum用于存储样本的和。SumOfSquares用于存储样本的平方和。distributions构造体是一个分布式数据的汇合,它由一个sync.RWMutex锁爱护。它蕴含了多个distribution,每个distribution通过一个字符串键进行索引。 newDistribution函数用于创立一个新的distribution对象,该对象蕴含指定的名称和标签。 Record函数用于记录一个样本值到指定的distribution。它将样本值增加到distribution的Sum和SumOfSquares中,并减少Count的计数。 With函数用于返回给定名称的distribution对象的援用。如果该名称的distribution不存在,则会创立一个新的distribution对象。 这些办法和数据结构提供了一种不便的形式来收集、统计和剖析分布式数据,例如申请提早、响应工夫等。 File: istio/pkg/monitoring/base.go在Istio我的项目中,istio/pkg/monitoring/base.go文件的作用是定义了根本的监控性能,提供了用于记录和报告度量指标的办法。 该文件中定义了一些重要的构造体和函数,包含: baseMetric构造体:用于示意一个根本的度量指标,蕴含了该指标的名称(Name字段)、默认值(defaultVal字段)、值类型(valueType字段)等属性。Name函数:用于获取度量指标的名称。Increment函数:用于减少度量指标的值。Decrement函数:用于缩小度量指标的值。runRecordHook函数:用于运行记录钩子函数,将度量指标的以后值记录到监控零碎中。Register函数:用于注册一个度量指标,将其增加到监控零碎中进行跟踪。RecordInt函数:用于记录一个整数类型的度量指标。rebuildAttributes函数:用于从新构建度量指标的属性,如标签。这些函数和构造体的作用如下: baseMetric构造体定义了一个度量指标的根本属性,并提供了对该指标的增减操作。Name函数返回度量指标的名称,用于标识该指标。Increment函数用于减少度量指标的值,可针对某个指标进行累加操作。Decrement函数用于缩小度量指标的值,可针对某个指标进行递加操作。runRecordHook函数用于运行记录钩子函数,将度量指标的以后值记录到监控零碎中,以便进行监控和报告。Register函数用于注册一个度量指标,将其增加到监控零碎中进行跟踪。RecordInt函数用于记录一个整数类型的度量指标,将其值保留到监控零碎中。rebuildAttributes函数用于从新构建度量指标的属性,如标签,以便在度量指标发生变化时进行更新。这些函数和构造体的综合作用是提供一个不便且可扩大的接口,用于记录和报告度量指标,从而实现对Istio我的项目的监控和性能优化。 File: istio/pkg/monitoring/gauge.go在Istio我的项目中,istio/pkg/monitoring/gauge.go文件的作用是定义和实现了度量计(Gauge)的性能。Gauge是一种度量类型,用于跟踪某个值的刹时状态。它能够用于记录和监控要害指标,比方连接数、申请解决工夫等。 在该文件中,有几个重要的变量和构造体: _:这些变量用于导入包时进行空白辨认,示意疏忽导入的包,因为在Istio中,该文件只导入了prometheus包,而不应用其中的变量。gauge:这个构造体示意度量计对象,它蕴含了一个Prometheus Gauge对象,并提供了一些办法来操作和记录该度量计的值。gaugeValues:这个构造体示意记录度量计值的对象,蕴含了具体的度量计和值的信息。newGauge函数用于创立一个新的度量计对象,它承受一个形容度量计的名称和标签(labels),并返回一个度量计对象的指针。这个函数会在度量计注册表中注册该度量计。 Record函数用于记录度量计的值,它承受一个度量计对象和一个浮点数作为值,并将值记录到度量计对象中。 With函数用于为度量计对象减少标签,它承受一个度量计对象和一个蕴含标签的映射(map),并返回一个带有新增标签的新的度量计对象。 通过这些函数和构造体,能够不便地创立、记录和操作度量计对象,在Istio我的项目中用于对系统的各项指标进行度量和监控。 File: istio/pkg/monitoring/disabled.go在Istio我的项目中,istio/pkg/monitoring/disabled.go文件的作用是为禁用的度量提供一个简略的实现。这个文件中定义了一些变量、构造体和函数,用于解决禁用的度量的操作。 首先,下划线 "_" 是一个空标识符,用于申明变量但不应用它们。在这个文件中,它被用于疏忽一些不须要的变量。 disabledMetric构造体是对禁用度量的定义。它蕴含了度量的名称(Name)和标签(Labels),以及与度量相干的办法。 Decrement办法用于将度量递加指定的值。Increment办法用于将度量递增指定的值。Name办法返回度量的名称。Record办法用于记录度量的值。RecordInt办法用于记录整数类型的度量的值。Register办法用于注册度量。With办法用于创立一个带有指定标签的度量。禁用的度量通常是在Istio中配置禁用的一种度量类型。如果度量是禁用的,那么将应用这个文件中定义的禁用度量进行解决,而不是真正的度量。 这个文件的目标是提供禁用的度量的一个默认实现,以便在度量禁用时不会导致谬误。它对度量的操作实际上是不执行任何操作,它只是提供了一个占位符实现。 总而言之,disabled.go文件为禁用的度量提供了一个默认的占位符实现,用于解决禁用度量的操作。 File: istio/pkg/monitoring/units.go在Istio我的项目中,istio/pkg/monitoring/units.go文件定义了用于度量标准单位转换的性能。该文件中蕴含了一些用于单位转换的构造体类型。 以下是units.go文件中定义的构造体及其作用: Unit构造体:示意一种度量单位,蕴含单位的名称和符号。例如,Unit{name: "seconds", symbol: "s"}示意工夫的单位为秒。UnitGroup构造体:示意一组相干的单位,包含一个基准单位和一组衍生单位。该构造体蕴含以下字段: baseUnit:基准单位,用于进行单位转换的基准。例如,对于工夫而言,基准单位能够是秒。units:衍生单位的列表,示意能够转换为基准单位的其余单位。每个衍生单位蕴含一个乘法因子和一个单位对象。UnitConvert构造体:示意一个单位转换器,用于执行单位转换的操作。该构造体蕴含以下办法: ToBase:将给定的值从一种单位转换为基准单位。FromBase:将给定的基准单位值转换为指定单位。Convert:将给定值从一种单位转换为另一种单位。这些构造体和办法的作用是为了提供更易于应用和了解的形式来执行单位转换。在Istio中,这些构造体和办法次要用于解决与度量标准单位相干的操作,如在监控和度量中进行单位转换和格式化显示等。 File: istio/pkg/monitoring/derived_gauge.go在Istio我的项目中,istio/pkg/monitoring/derived_gauge.go文件的作用是定义了DerivedGauge接口及其默认实现DerivedGaugeImpl,用于创立和治理衍生指标(Derived Gauge)。衍生指标是从其余根底指标计算得出的指标,可用于监控或度量特定的零碎或应用程序性能。 在这个文件中,_是一个空标识符,用于疏忽不须要的返回值或赋值操作。 而derivedGauge构造体定义了一个衍生指标的实例,用于存储指标的名称、标签和值。 newDerivedGauge函数是DerivedGaugeImpl的构造函数,用于创立DerivedGaugeImpl的实例,并将衍生指标的名称和标签传递给构造函数。Name函数是DerivedGaugeImpl构造体的办法,用于返回衍生指标的名称。Register函数是DerivedGaugeImpl构造体的办法,用于注册衍生指标到监控指标的注册表中。ValueFrom函数是DerivedGaugeImpl构造体的办法,用于计算和返回衍生指标的值。DerivedGauge接口和DerivedGaugeImpl默认实现提供了一种在Istio我的项目中掂量和监控零碎性能的形式。通过实例化并注册DerivedGauge,能够不便地衍生新的指标,并在程序运行时更新这些指标的值。这些衍生指标能够用于监控和度量Istio我的项目的各个方面,从而提供了对系统的深刻理解和性能优化的根底。 File: istio/pkg/webhooks/webhookpatch.gowebhookpatch.go文件是Istio我的项目中的一个组件,用于在运行时动静地批改Kubernetes中的mutatingwebhookconfigurations对象,以修补证书。这个组件称为Webhook Cert Patcher。 以下是文件中的几个变量的作用: errWrongRevision:示意在webhook配置中找不到正确的订正版本谬误。errNotFound:示意找不到指定名称的webhook配置谬误。errNoWebhookWithName:示意没有找到指定名称的webhook谬误。以下是文件中的几个构造体的作用: WebhookCertPatcher:示意用于动静修补证书的次要构造体。它蕴含了用于从Kubernetes API服务器获取webhook配置并修复证书的办法。CertPatcherConfig:示意用于配置Webhook Cert Patcher的构造体。其中包含Kubernetes API服务器的相干配置以及Webhook配置的修复策略。以下是文件中的几个函数的作用: ...

September 25, 2023 · 1 min · jiezi

关于后端:代码整洁之道程序员的职业素养十五

团队与我的项目组建团队是一个须要工夫和急躁的过程。团队成员须要建设关系,学习如何相互协作,并理解彼此的劣势和劣势。只有通过一段时间的相处和磨合,团队能力造成真正的凝聚力。 当团队克服个体差异,造成默契配合和相互信任的关系时,就会产生一种神奇的魔力。这个团队可能一起制订打算、解决问题,并独特面对和实现各种工作。这种团队凝聚力的造成须要工夫,但一旦造成,团队的效率和成绩将会大大晋升。 业余的开发组织会将我的项目调配给曾经造成凝聚力的团队,而不是围绕我的项目来组建团队。这样的团队能够同时承接多个我的项目,并依据成员的技能和能力来调配工作,从而顺利完成我的项目。 作为我的项目承包人,如果领有一个团队专一于本人的我的项目,就可能分明地计算团队的投入。他们晓得组建和遣散团队都是一项代价昂扬的工作,因而公司也不会轻易调走团队。这样的团队能够为公司节省时间和资源,并进步我的项目的成功率。 然而,组建和遣散团队只是人为的艰难,并不应该限度公司的决策。如果公司认为某个我的项目的优先级更高,应该迅速重新分配资源。我的项目承包人的职责就是清晰地定义和论述我的项目的价值和意义,以取得公司管理层的认可和反对。 团队的构建比我的项目自身更具挑战性。因而,建设稳固的团队,让他们在不同我的项目中继续单干,成为一个弱小的合作引擎,是更好的做法。团队也能够同时承接多个我的项目,进步整体效率。在组建团队时,给予他们短缺的工夫,让他们造成凝聚力,并继续独特工作,这样能力一直交付出优良的我的项目成绩。 总结起来,组建团队须要工夫和急躁。团队的凝聚力是一个神奇的魔力,可能让团队成员独特合作、解决问题,并获得优良的成绩。业余的开发组织会将我的项目调配给已有凝聚力的团队,以进步工作效率和成功率。团队的构建比我的项目自身更具挑战性,但只有通过继续单干和独特工作,团队能力成为一个弱小的合作引擎。 本文由mdnice多平台公布

September 25, 2023 · 1 min · jiezi

关于后端:LeetCode-mysql-刷题五按分类统计薪水用5种方法处理不存在的数据但要显示的数据

题目题目链接:按分类统计薪水 查问每个工资类别的银行账户数量。 工资类别如下: "Low Salary":所有工资 严格低于 20000 美元。"Average Salary": 蕴含 范畴内的所有工资 [$20000, $50000] 。"High Salary":所有工资 严格大于 50000 美元。后果表 必须 蕴含所有三个类别。 如果某个类别中没有帐户,则报告 0 。 按 任意程序 返回后果表。 查问后果格局如下示例。 输出:Accounts 表:+------------+--------+| account_id | income |+------------+--------+| 3 | 108939 || 2 | 12747 || 8 | 87709 || 6 | 91796 |+------------+--------+在 SQL 中,account_id 是这个表的主键。每一行都蕴含一个银行帐户的月支出的信息。输入:+----------------+----------------+| category | accounts_count |+----------------+----------------+| Low Salary | 1 || Average Salary | 0 || High Salary | 3 |+----------------+----------------+解释:低薪: 有一个账户 2.中等薪水: 没有.高薪: 有三个账户,他们是 3, 6和 8.Create table If Not Exists Accounts (account_id int, income int);Truncate table Accounts;insert into Accounts (account_id, income) values ('3', '108939');insert into Accounts (account_id, income) values ('2', '12747');insert into Accounts (account_id, income) values ('8', '87709');insert into Accounts (account_id, income) values ('6', '91796');解析因为表中没有 Average Salary 类型的数据,然而后果须要将 Average Salary 类型的数据用 0 示意 ...

September 25, 2023 · 2 min · jiezi

关于后端:JDK21新特性Record-Patterns记录模式详解

1 摘要通过应用记录模式来加强Java编程语言,以解构记录值。记录模式和类型模式可嵌套应用,从而实现弱小、申明式和可组合的数据导航和解决模式。 2 发展史由 JEP 405 提出的预览性能,并在JDK 19公布,而后由 JEP 432 再次预览,并在JDK 20公布。该性能与用于switch的模式匹配(JEP 441)独特演进,并且二者有相当大的交互作用。本JEP提议在继续的教训和反馈根底上对该功能完善。 除了一些主要的编辑更改,自第二个预览版以来的次要变动是删除了对加强for语句头部呈现记录模式的反对。这个性能可能会在将来的JEP中重提。 3 指标扩大模式匹配以解构记录类的实例,实现更简单的数据查问增加嵌套模式,实现更可组合的数据查问4 动机Java 16中, JEP 394 扩大了instanceof运算符,使其可承受类型模式并执行模式匹配。这个简略的扩大使得相熟的instanceof和强制转换习用法变得更简洁、更不易出错: // <Java 16if (obj instanceof String) { String s = (String)obj; ... 应用s ...}// ≥Java 16if (obj instanceof String s) { ... 应用s ...}新代码中,若obj在运行时是String的实例,则obj与类型模式String s匹配。若模式匹配胜利,则instanceof true,且模式变量s被初始化为obj强制转换为String的值,而后能够在蕴含的代码块中应用。 类型模式一次性打消了许多类型转换的呈现。然而,它们只是朝着更申明式、以数据为焦点的编程格调迈出的第一步。随Java反对新的、更具表现力的数据建模,模式匹配可通过让开发表白模型的语义用意来简化对这些数据的应用。 5 Pattern matching和records记录 (JEP 395) 是数据的通明载体。接管记录类实例的代码通常会应用内置的组件拜访器办法提取数据,即组件。 5.1 Point的实例如用类型模式测试一个值是否是记录类Point的实例,并在匹配胜利时从该值中提取x和y组件。 Java8class Point { private int x; private int y; public Point(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public int getY() { return y; }}static void printSum(Object obj) { if (obj instanceof Point) { Point p = (Point) obj; int x = p.getX(); int y = p.getY(); System.out.println(x + y); }}≥Java 16record Point(int x, int y) {}static void printSum(Object obj) { if (obj instanceof Point p) { int x = p.x(); int y = p.y(); System.out.println(x+y); }}仅应用模式变量p调用拜访办法x()、y(),这些办法返回组件x和y的值。 ...

September 25, 2023 · 3 min · jiezi

关于后端:添加阿里云maven镜像

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 文章更新打算 关上 maven 的配置文件( windows 机器个别在 maven 装置目录的 conf/settings.xml ),在<mirrors></mirrors>标签中增加 mirror 子节点: <mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/public</url> </mirror> <mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <name>阿里云公共仓库snapshots</name> <url>https://maven.aliyun.com/repository/apache-snapshots</url> </mirror>在你的 pom.xml 文件<denpendencies></denpendencies>节点中退出你要援用的文件信息: <dependency> <groupId>[GROUP_ID]</groupId> <artifactId>[ARTIFACT_ID]</artifactId> <version>[VERSION]</version></dependency><!-- md tj.md --> 本文由mdnice多平台公布

September 25, 2023 · 1 min · jiezi

关于后端:BUGFailedtoexecutegoalorgspringframework

uuid: 606989c0-5b73-11ee-b9af-9fe36aef5f9ftitle: tags: [Spring Boot, Maven, 插件, 报错, 类文件版本, 兼容, 解决方案 ]categories: [ ] date: 2023-09-25 15:15:59有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 系列文章地址 报错内容Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.1.1.RELEASE:repackage (default) on project leader-admin: Execution default of goal org.springframework.boot:spring-boot-maven-plugin:2.1.1.RELEASE:repackage failed: Unsupported class file major version 65 起因剖析这个谬误是因为您的我的项目中应用了一个类文件版本为65.0的类,而以后的Java运行时环境不反对该版本。 依据错误信息,您正在应用的是Spring Boot Maven插件,版本为2.1.1.RELEASE。该插件的默认指标是将我的项目打包为可执行的JAR文件。 要解决这个问题,您能够尝试以下几个步骤: 确认您应用的Java版本是否与该插件兼容。您能够查看Spring Boot官网文档或插件的文档,理解其兼容的Java版本范畴。确保您的我的项目中应用的所有依赖项(包含Spring Boot和其余库)的版本与您的Java版本兼容。您能够查看它们的文档或公布阐明,理解其兼容的Java版本要求。3.如果您的Java版本较低,并且您无奈降级到反对类文件版本65.0的Java版本,您能够尝试升高您的我的项目中的类文件版本。您能够在我的项目的pom.xml文件中配置maven-compiler-plugin插件,指定指标类文件版本。例如,您能够将指标版本设置为61.0,以与Java17兼容。 <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <target>17</target> <source>17</source> </configuration> </plugin> </plugins></build>请依据您的理论状况进行调整。 解决方案替换为 3.1.3 <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>3.1.3</version> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin><!-- md tj.md --> ...

September 25, 2023 · 1 min · jiezi

关于后端:javaioInvalidClassException-comxxxxxx

InvalidClassException异样通过类A在零碎应用ehcache作为缓存,当初A类中新增的一个字段aa;新增后启动我的项目后报错:java.io.InvalidClassException: xxx.xxx.xxx; local class incompatible: stream classdesc serialVersionUID = xxx, local class serialVersionUID = xxx;,报错的大略意思是缓存中serialVersionUID的与本地类不兼容;通过查看发现A类实现了Serializable却没有定义出serialVersionUID,导致缓存在验证serialVersionUID时前后不统一抛出异样; 这里须要解释一下:类没有显式申明serialVersionUID字段,则Java运行时零碎将依据类的各种详细信息主动生成一个serialVersionUID。解决办法既然原来会生成一个serialVersionUID,那么咱们获取到原来的serialVersionUID再给类设置下来,就保障统一了。通过报错信息外面就能够获取原来的serialVersionUID;或者通过上面的代码获取 ObjectStreamClass sc = ObjectStreamClass.lookup(A.class);long ASerialVersionUIDserialID = sc.getSerialVersionUID();System.out.println("A: " + ASerialVersionUIDserialID);//这里就是获取到的serialVersionUID留神:这里A类必须时批改之前的模样,能够通过git、svn等工具获取; 还有就是实现了Serializable肯定要加上serialVersionUID,没事不要乱动serialVersionUID private static final long serialVersionUID = XXXL;

September 25, 2023 · 1 min · jiezi

关于后端:quarkus依赖注入之十一拦截器高级特性上篇属性设置和重复使用

欢送拜访我的GitHub这里分类和汇总了欣宸的全副原创(含配套源码):https://github.com/zq2599/blog_demos本篇概览本篇是《quarkus依赖注入》系列的第十一篇,之前的[《拦截器》]学习了拦截器的基础知识,当初咱们要更加深刻的理解拦截器,把握两种高级用法:拦截器属性和重复使用拦截器先来回顾拦截器的基本知识,定义一个拦截器并用来拦挡bean中的办法,总共须要实现以下三步 业务需要设定为了让本篇所学知识点显得有实用型,这里假设一个业务需要,而后咱们用拦截器来满足这个需要假如有个名为SayHello的一般接口,此接口有三个实现类:SayHelloA、SayHelloB、SayHelloC,这些实现类都是bean,它们的源码如下接口SayHello.java public interface SayHello { String hello();}实现类SayHelloA.java @ApplicationScoped@Named("A")public class SayHelloA implements SayHello { @Override public void hello() { Log.info("hello from A"); }}实现类SayHelloB.java @ApplicationScoped@Named("B")public class SayHelloB implements SayHello { @Override public void hello() { Log.info("hello from B"); }}实现类SayHelloC.java @ApplicationScoped@Named("C")public class SayHelloC implements SayHello { @Override public void hello() { Log.info("hello from C"); }}以上是已知条件,当初来看业务需要要求设计一个拦截器,名为SendMessage,性能是对外发送告诉,告诉的形式有短信和邮件两种,具体用哪种是能够设置的用SendMessage拦截器拦挡SayHelloA,告诉类型是短信用SendMessage拦截器拦挡SayHelloB,告诉类型是邮件用SendMessage拦截器拦挡SayHelloC,告诉类型是短信和邮件都发送 性能实现剖析上述业务需要第二项和第三项,很显然拦截器的实现要同时反对短信告诉和邮件告诉两种性能,而问题的要害是:拦截器在工作的时候,如何晓得以后应该发送短信还是邮件,或者说如何将告诉类型精确的通知拦截器?这就牵扯到一个知识点:拦截器属性,拦截器本人是个注解,而注解是有属性的,咱们新增一个告诉类型的属性(名为sendType),只有在应用注解的中央配置sendType,而后在拦截器实现中获取到sendType的值,就解决了告诉类型的设置和获取的问题,业务需要2和3也就迎刃而解了,拦截器配置的成果大抵如下 @ApplicationScoped@SendMessage(sendType="sms")public class SayHelloA implements SayHello {再来看需要4,这又设计到拦截器的另一个知识点:同一个拦截器重复使用,只有间断两次用SendMessage注解润饰SayHelloC,而每个注解的sendType别离是短信和邮件,这样就能达到目标了,拦截器配置的成果大抵如下 @ApplicationScoped@SendMessage(sendType="sms")@SendMessage(sendType="email")public class SayHelloC implements SayHello {以上就是解决问题的大抵思路,接下来编码实现,将波及的知识点在代码中体现进去 编码:定义拦截器首先是拦截器定义SendMessage.java,有几处要留神的中央稍后会提到 package com.bolingcavalry.interceptor.define;import javax.enterprise.util.Nonbinding;import javax.interceptor.InterceptorBinding;import java.lang.annotation.*;@InterceptorBinding@Repeatable(SendMessage.SendMessageList.class)@Target({ElementType.TYPE, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface SendMessage { /** * 音讯类型 : "sms"示意短信,"email"示意邮件 * @return */ @Nonbinding String sendType() default "sms"; @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface SendMessageList { SendMessage[] value(); }}上述代码有以下几处须要留神容许在同一地位重复使用同一个注解,这是java注解的通用性能,并非quarkus独有重复使用注解时,必须定义注解容器,用来搁置反复的注解,这里的容器是SendMessageList**应用Repeatable润饰SendMessage,这样就能在同一地位重复使用SendMessage注解了,留神Repeatable的属性值是容器SendMessageListsendType是注解属性,用来保留告诉类型,任何应用SendMessage注解的中央都能通过设置sendType来指定告诉类型,如果不指定则应用默认值sms要留神sendType的注解Nonbinding,此注解十分重要,如果不增加此注解,在应用SendMessage的时候,设置sendType为email时拦截器不会失效quarkus对重复使用同一拦截器注解的限度尽管能够在同一地位重复使用SendMessage拦截器,然而要留神quarkus的限度能够作用在办法上不能作用在类上不能作用在stereotypes上对于2和3,官网的说法是未来会解决(This might be added in the future)编码:实现拦截器接下来是实现具体拦挡性能的SendMessageInterceptor.java,代码如下,有几处要留神的中央稍后会提到package com.bolingcavalry.interceptor.impl;import com.bolingcavalry.interceptor.define.SendMessage;import com.bolingcavalry.interceptor.define.TrackParams;import io.quarkus.arc.Priority;import io.quarkus.arc.runtime.InterceptorBindings;import io.quarkus.logging.Log;import javax.interceptor.AroundInvoke;import javax.interceptor.Interceptor;import javax.interceptor.InvocationContext;import java.lang.annotation.Annotation;import java.util.*;import static io.quarkus.arc.ArcInvocationContext.KEY_INTERCEPTOR_BINDINGS;@SendMessage@Interceptorpublic class SendMessageInterceptor { @AroundInvoke Object execute(InvocationContext context) throws Exception { // 先执行被拦挡的办法 Object rlt = context.proceed(); // 获取被拦挡办法的类名 String interceptedClass = context.getTarget().getClass().getSimpleName(); // 代码能走到这里,示意被拦挡的办法已执行胜利,未出现异常 // 从context中获取告诉类型,因为容许反复注解,因而告诉类型可能有多个 List<String> allTypes = getAllTypes(context); // 将所有音讯类型打印进去 Log.infov("{0} messageTypes : {1}", interceptedClass, allTypes); // 遍历所有音讯类型,调用对应的办法解决 for (String type : allTypes) { switch (type) { // 短信 case "sms": sendSms(); break; // 邮件 case "email": sendEmail(); break; } } // 最初再返回办法执行后果 return rlt; } /** * 从InvocationContext中取出所有注解,过滤出SendMessage类型的,将它们的type属性放入List中返回 * @param invocationContext * @return */ private List<String> getAllTypes(InvocationContext invocationContext) { // 取出所有注解 Set<Annotation> bindings = InterceptorBindings.getInterceptorBindings(invocationContext); List<String> allTypes = new ArrayList<>(); // 遍历所有注解,过滤出SendMessage类型的 for (Annotation binding : bindings) { if (binding instanceof SendMessage) { allTypes.add(((SendMessage) binding).sendType()); } } return allTypes; } /** * 模仿发送短信 */ private void sendSms() { Log.info("operating success, from sms"); } /** * 模仿发送邮件 */ private void sendEmail() { Log.info("operating success, from email"); }}上述代码,有以下几处须要留神发送短信和邮件不是本篇的重点,因而,对应的sendSms和sendEmail办法中只是日志打印,示意代码曾经走到了此处getAllTypes办法是重点,演示了如何从拦截器上下文对象invocationContext中获取所有注解,并过滤出所有SendMessage类型,再取其type属性对取出的sendType属性逐个解决,这样就做到了每个设置的类型都会被解决在某个办法上屡次用SendMessage注解润饰,最终只会执行一次SendMessageInterceptor#execute办法,这是要害!试想,如果SendMessageInterceptor#execute办法执行了屡次,而每次都会取出所有SendMessage类型去解决,那么每种SendMessage类型都会反复解决编码:应用拦截器拦截器的定义和实现都曾经实现,接下来就是应用拦截器了,留神后面提到的限度,这里要用SendMessage去润饰办法,而不能润饰类首先是SayHelloA,拦挡它的时候,业务需要是发送短信,批改后的残缺源码如下,用SendMessage注解润饰hello办法,这里的SendMessage没有指定其sendType的值,因而会应用默认值sms@ApplicationScoped@Named("A")public class SayHelloA implements SayHello { @SendMessage @Override public void hello() { Log.info("hello from A"); }}而后是SayHelloB,拦挡它的时候,业务需要是发送邮件,留神sendType值等于email@ApplicationScoped@Named("B")public class SayHelloB implements SayHello { @SendMessage(sendType = "email") @Override public void hello() { Log.info("hello from B"); }}最初是SayHelloC,拦挡它的时候,也无需要是短信和邮件都要发送,留神这里应用了两次SendMessage@ApplicationScoped@Named("C")public class SayHelloC implements SayHello { @SendMessage @SendMessage(sendType = "email") @Override public void hello() { Log.info("hello from C"); }}拦截器的定义、实现、应用都曾经实现,接下来思考如何验证,还是用单元测试吧,简略不便编码:单元测试单元测试类的逻辑很简略,运行几个bean的hello办法即可@QuarkusTestpublic class SendMessageTest { @Named("A") SayHello sayHelloA; @Named("B") SayHello sayHelloB; @Named("C") SayHello sayHelloC; @Test public void testSendMessage() { sayHelloA.hello(); sayHelloB.hello(); sayHelloC.hello(); }}编码实现,能够运行起来验证后果了运行单元测试单元测试类SendMessageTestd的执行后果如下图,红黄蓝三个框中,别离是SayHelloA、SayHelloB、SayHelloC的拦挡后果,可见全副合乎预期 ...

September 25, 2023 · 2 min · jiezi

关于后端:快速掌握-Go-工作区模式

大家好,我是煎鱼。 在 Go 我的项目的模块治理中,先是 GOPATH,而后到废除。再到强推 Go modules,从被社区抗拒到 rsc 硬上弓。当初最新要理解的,就是工作区模式(workspace mode)。这是一个在 Go1.18 引入的重要个性。 之前始终没提过,明天补全这块的知识点。 背景在 Go1.11 起有了 Go modules 后,看起来 Go 模块治理逐渐按序有了束缚、标准了起来。但也带来了一些应用上的问题。 事实开发时,当咱们须要对多个关联模块进行开发(批改)时,这个事件就麻烦了起来。我见过两种形式。 1、第一种:间接在 go.mod 文件上配置 replace,配置到本地的开发目录。这是最常见的形式。 // go.modreplace example.com/golang/text => "../eddycjy/golang/text"这种做法常常会有人不小心提交到 Git 仓库上。还挺折腾人的,一个不小心就为此 debug 了半天,或者公布部署始终卡着过不去。 2、第二种:间接在依赖模块上编码,编码到肯定的水平。才上传 GitHub/GitLab。再去公布版本标签再援用。这种用法比拟少,只有模块比较简单且对程序比拟自信的会这么干。(不举荐) 总的来讲,就是有了 Go modules 后,多模块间的依赖开发还是挺麻烦的。要常常 replace,有时候又会忘了删。 go work 指令集在大家苦楚了许久后,Go1.18 时终于公布了工作区模式的形式,来优化这个用法和问题。 以下是 go work 的指令集: go work <command> [arguments]edit:从工具或脚本中编辑 go.work。init:初始化工作区文件(go.work)。sync:将工作区构建列表同步到模块。use:将模块增加到工作区文件。疾速应用接下来咱们疾速利用 Go 工作区模式,让大家有个直观的理解。须要留神,该个性须要确保 Go 版本 >= 1.18。 创立工作区首先咱们创立一个工作区,执行如下命令: $ mkdir workspace-main && cd workspace-main $ go work init执行结束后会在该目录下创立一个 go.work 文件,文件内容蕴含: ...

September 25, 2023 · 2 min · jiezi

关于后端:后端服务之应用预热-京东云技术团队

一 背景C端服务利用降级和重启,导致耗时刹时抖动,业务超时,利用监控报警,上游感知显著,导致用户体验变差。 二 利用降级重启导致抖动的起因1 C端服务利用降级和重启的冷启动阶段,它须要从新加载和初始化各种资源,例如数据库连贯、缓存数据等,导致耗时刹时飙升。 2 利用重启后,本地缓存生效,利用须要从新加载数据,导致耗时变长。 3 利用重启后,有大量申请沉积,导致系统负载减少,线程解决不及时,导致系统响应变慢。 三 解决方案1 停服时,先下线JSF接口,再降级利用,待利用启动胜利后,JSF服务接口提早注册到注册核心。 2 JSF开启预热性能,是服务提供者重启后,JSF上线后,消费者与服务者建设链接后,调用方客户端先放设置比例的小局部流量过去到降级重启的实例,在预热周期内,逐渐到100% 3 在利用降级流程编排中,联合流量回放,编排流程,在流量回放后再操作JSF上线,实现略简单,依赖根底运维 计划1,计划2实现简略,预热成果也比拟好,应用的是JSF的预热性能,以下成果比照的实现来自计划2的JSF预热性能。 四 采纳JSF开启预热性能成果比照1 服务提供者配置预热周期 预热初始权重:consumer连贯到provider后,provider的初始权重(provider端权重会在预热周期内会逐步复原到失常权重,个别是100) 2 未开启预热容器实例整体降级重启监控: 利用部署在3个机房,所以看到3次抖动,能够看到TP999最高的机房达到了近25s。 开启预热后整体实例降级重启成果: 利用部署在3个机房,所以看到3次抖动,能够看到TP999最高的机房降到了2.5s,降幅达10倍。 3 未开启预热,单实例利用重启监控 max达到了20s,TP999达到了18s 开启预热后,单实例利用重启监控 max降到了2s,TP999将到了1.5s左右,降幅达10倍,TPS在配置的预热周期内(60s)出现线性增长 五 注意事项依赖服务调用方降级JSF到1.7.6版本及以上,推动所有调用方降级JSF 可依据利用的启动工夫和个性,调整利用匹配的预热周期,达到绝对预热成果最好的状态。至于是否有必要联合流量回放和流程编排实现预热,需联合本人的业务状况和实现老本思考。 作者:京东科技 张石磊 起源:京东云开发者社区 转载请注明起源

September 25, 2023 · 1 min · jiezi

关于后端:随机ID生成工具

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 文章更新打算 package com.nari.common.utils;import java.util.concurrent.atomic.AtomicInteger;public class IdUtilV2 { private static final AtomicInteger ids = new AtomicInteger(1); private IdUtilV2() { } public static String getIdStr() { return getId().toString(); } public static Long getId() { return System.nanoTime() + Thread.currentThread().getId() + (ids.getAndIncrement()); }}<!-- md tj.md --> 本文由mdnice多平台公布

September 25, 2023 · 1 min · jiezi

关于后端:实测Hutool的雪花算法8G内存跑到7600万条OOM

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 文章更新打算 本地跑的,cpu是i9-13代,内存32G 办法是这个: public static void main(String[] args) { int i = 1000000; int i2 = 100; StopWatch watch = new StopWatch(); watch.start(); Set<Long> ids = new HashSet<>(); for (int i21 = i2; i21 > 0; i21--) { for (int i1 = 0; i1 < i; i1++) { ids.add(IdUtil.getSnowflake().nextId()); } System.out.println(ids.size()); } watch.stop(); System.out.println(watch.getLastTaskTimeMillis()); }理论跑了7600万,而后OOM了,内存是8G <!-- md tj.md --> 本文由mdnice多平台公布

September 25, 2023 · 1 min · jiezi

关于后端:BUG循环中重复使用对象一定要注意

有时候博客内容会有变动,首发博客是最新的,其余博客地址可能未同步,请认准https://blog.zysicyj.top首发博客地址 文章更新打算 系列文章地址 报错内容报错信息显示ID反复。 起因剖析在最终增加的办法中,呈现了反复ID的报错。对于为什么ID会反复,我思考了很久也没有想通。我沿着代码往上找到了saveList。 int batchSize = 5000;if (CollUtil.isNotEmpty(saveList)) { List<List<Map<String, Object>>> batchList = ListUtil.partition(saveList, batchSize); for (List<Map<String, Object>> batch : batchList) { if (CollUtil.isNotEmpty(batch)) { firstRecordMapper.insertJghzLdryList(batch.stream().filter(v -> v != null && ObjectUtil.isNotEmpty(v.get("ID"))).collect(Collectors.toList())); } }}代码大抵如上所示。 for (Map<String, Object> item : list) { ... Map<String, Object> oneCellMap = new HashMap<String, Object>(); // 遍历这一类型的10个二级指标,每个指标存成一行数据 for (int i = 0; i < secIndexNameList.size(); i++) { ... oneCellMap.clear(); oneCellMap.put("ID", IdUtilV2.getInstance().getId()); ... saveList.add(oneCellMap); px++; } // 保留这一行数据的 综合得分 oneCellMap.clear(); oneCellMap.put("ID", IdUtilV2.getInstance().getId()); ... saveList.add(oneCellMap);}我也不是很确定,但我狐疑问题出在这里,于是我做了以下批改: ...

September 25, 2023 · 1 min · jiezi

关于后端:JDK21最终版协程实现之虚拟线程

1 全新并发编程模式JDK9 后的版本你感觉没必要折腾,我也认可,然而JDK21有必要关注。因为 JDK21 引入全新的并发编程模式。 始终欺世盗名的GoLang吹得最厉害的就是协程了。JDK21 中就在这方面做了很大的改良,让Java并发编程变得更简略一点,更丝滑一点。 之前写过JDK21 Feature。Virtual Threads、Scoped Values、Structured Concurrency就是针对多线程并发编程的几个性能。。 2 倒退历史虚构线程是轻量级线程,极大地缩小了编写、保护和察看高吞吐量并发利用的工作量。 虚构线程是由JEP 425提出的预览性能,并在JDK 19中公布,JDK 21中最终确定虚构线程,以下是依据开发者反馈从JDK 20中的变动: 当初,虚构线程始终反对线程本地变量。与在预览版本中容许的不同,当初不再可能创立不能具备线程本地变量的虚构线程。对线程本地变量的有保障反对确保了许多现有库能够不经批改地与虚构线程一起应用,并有助于将以工作为导向的代码迁徙到应用虚构线程间接应用Thread.Builder API创立的虚构线程(而不是通过Executors.newVirtualThreadPerTaskExecutor()创立的虚构线程)当初默认状况下也会在其生命周期内进行监控,并且能够通过形容在"察看虚构线程"局部中的新线程转储来察看。 基于协程的线程,与其余语言中的协程有相似之处,也有不同。虚构线程是依附于主线程的,如果主线程销毁了,虚构线程也不复存在。 3 指标使采纳简略的 thread-per-request 模式编写的服务器应用程序,能以靠近最佳的硬件利用率扩大使利用java.lang.Thread API的现有代码能在最小更改下采纳虚构线程通过现有的JDK工具轻松进行虚构线程的故障排除、调试和剖析4 非指标不是删除传统的线程实现,也不是轻轻将现有应用程序迁徙到应用虚构线程不是扭转Java的根本并发模型不是在Java语言或Java库中提供新的数据并行结构。Stream API仍是解决大型数据集的首选形式。5 动机Java开发人员在近30年来始终依赖线程作为并发服务端应用程序的构建块。每个办法中的每个语句都在一个线程内执行,并且因为Java是多线程,多个线程同时执行。 线程是Java的并发单元:它是一段程序代码,与其余这样的单元并发运行,很大水平上是独立的。每个线程提供一个堆栈来存储局部变量和协调办法调用及在呈现问题时的上下文:异样由同一线程中的办法抛出和捕捉,因而开发可应用线程的堆栈跟踪来查找产生了啥。 线程也是工具的外围概念:调试器逐渐执行线程办法中的语句,剖析工具可视化多个线程的行为,以帮忙了解它们的性能。 6 thread-per-request模式服务器应用程序通常解决彼此独立的并发用户申请,因而将一个线程专用于解决整个申请在逻辑上是正当的。这种模式易了解、易编程,且易调试和剖析,因为它应用平台的并发单元来示意应用程序的并发单元。 服务器应用程序的可扩展性受到Little定律束缚,该定律关联提早、并发性和吞吐量:对给定的申请解决持续时间(即提早),应用程序同时解决的申请数量(并发性)必须与达到速率(吞吐量)成比例增长。如一个具备均匀提早为50ms的应用程序,通过同时解决10个申请实现每秒解决200个申请的吞吐量。为使该应用程序扩大到每秒解决2000个申请吞吐量,它要同时解决100个申请。如每个申请在其持续时间内都应用一个线程(因而应用一个os线程),那在其余资源(如CPU或网络连接)耗尽前,线程数量通常成为限度因素。JDK对线程的以后实现将应用程序的吞吐量限度在远低于硬件反对程度的程度。即便线程进行池化,依然产生,因为池化可防止启动新线程的高老本,但并不会减少总线程数。 7 应用异步模式进步可扩展性一些开发人员为了充分利用硬件资源,曾经放弃了采纳"thread-per-request"的编程格调,转而采纳"共享线程"。这种形式,申请解决的代码在期待I/O操作实现时会将其线程返回给一个线程池,以便该线程能够为其余申请提供服务。这种对线程的精密共享,即只有在执行计算时才放弃线程,而在期待I/O时开释线程,容许高并发操作而不耗费大量线程资源。尽管它打消了因为os线程无限而导致的吞吐量限度,但代价高:它须要一种异步编程格调,应用一组专门的I/O办法,这些办法不会期待I/O操作实现,而是稍后通过回调告诉其实现。 在没有专用线程状况下,开发须将申请解决逻辑合成为小阶段,通常编写为lambda表达式,而后应用API(如CompletableFuture或响应式框架)将它们组合成程序管道。因而,他们放弃语言的根本程序组合运算符,如循环和try/catch块。 异步格调中,申请的每个阶段可能在不同线程执行,每个线程交织形式运行属于不同申请的阶段。这对于了解程序行为产生了粗浅的影响:堆栈跟踪提供不了可用的上下文,调试器无奈逐渐执行申请解决逻辑,分析器无奈将操作的老本与其调用者关联起来。应用Java的流API在短管道中解决数据时,组合lambda表达式是可治理的,但当应用程序中的所有申请解决代码都必须以这种形式编写时,会带来问题。这种编程格调与Java平台不符,因为应用程序的并发单位——异步管道——不再是平台的并发单位。 8 通过虚构线程放弃 thread-per-request 编程格调为了在放弃与平台谐和的状况下使应用程序能扩大,应致力通过更高效形式实现线程,以便它们可更丰盛存在。os无奈更高效实现操作系统线程,因为不同编程语言和运行时以不同形式应用线程堆栈。然而,JRE可通过将大量虚构线程映射到大量操作系统线程来实现线程的假装丰富性,就像os通过将大型虚拟地址空间映射到无限的物理内存一样,JRE可通过将大量虚构线程映射到大量操作系统线程来实现线程的假装丰富性。 虚构线程是java.lang.Thread一个实例,不与特定os线程绑定。相同,平台线程是java.lang.Thread的一个实例,以传统形式实现,作为包装在操作系统线程四周的薄包装。 采纳 thread-per-request 编程格调的应用程序,可在整个申请的持续时间外在虚构线程中运行,但虚构线程仅在它在CPU上执行计算时才会耗费os线程。后果与异步格调雷同,只是它是通明实现:当在虚构线程中运行的代码调用java.* API中的阻塞I/O操作时,运行时会执行非阻塞的os调用,并主动暂停虚构线程,直到可稍后复原。对Java开发,虚构线程只是便宜且简直有限丰盛的线程。硬件利用率靠近最佳,容许高并发,因而实现高吞吐量,同时应用程序与Java平台及其工具的多线程设计放弃和谐一致。 9 虚构线程的含意虚构线程成本低且丰盛,因而永远都不应被池化:每个应用程序工作应该创立一个新的虚构线程。因而,大多数虚构线程将是短暂的,且具备浅层次的调用栈,执行的操作可能只有一个HTTP客户端调用或一个JDBC查问。相比之下,平台线程是重量级且代价低廉,因而通常必须池化。它们偏向于具备较长的生命周期,具备深层次调用栈,并在许多工作间共享。 总之,虚构线程保留了与Java平台设计和谐一致的牢靠的 thread-per-request 编程格调,同时最大限度地利用硬件资源。应用虚构线程无需学习新概念,只管可能须要放弃为应答以后线程老本昂扬而养成的习惯。虚构线程不仅将帮忙应用程序开发人员,还将帮忙框架设计人员提供与平台设计兼容且不会就义可伸缩性的易于应用的API。 10 形容现在,JDK 中的每个 java.lang.Thread 实例都是平台线程。平台线程在底层os线程上运行 Java 代码,并在代码的整个生命周期内捕捉os线程。平台线程的数量受限于os线程的数量。 虚构线程是 java.lang.Thread 的一个实例,它在底层os线程上运行 Java 代码,但并不在代码的整个生命周期内捕捉操作系统线程。这意味着许多虚构线程可在同一个os线程上运行其 Java 代码,无效地共享它。而平台线程会独占一个贵重的os线程,虚构线程则不会。虚构线程的数量可 >> os线程的数量。 ...

September 25, 2023 · 4 min · jiezi

关于后端:探索抽象同步队列-AQS

by emanjusaka from https://www.emanjusaka.top/archives/8 彼岸花开可奈何 本文欢送分享与聚合,全文转载请留下原文地址。前言AbstractQueuedSynchronizer形象同步队列简称AQS,它是实现同步器的根底组件,并发包中锁的底层就是应用AQS实现的。大多数开发者可能永远不会间接应用AQS,然而晓得其原理对于架构设计还是很有帮忙的。AQS是Java中的一个抽象类,全称是AbstractQueuedSynchronizer,即形象队列同步器。它定义了两种资源共享模式:独占式和共享式。独占式每次只能有一个线程持有锁,例如ReentrantLock实现的就是独占式的锁资源;共享式容许多个线程同时获取锁,并发访问共享资源,ReentrantReadWriteLock和CountDownLatch等就是实现的这种模式。AQS保护了一个volatile的state变量和一个FIFO(先进先出)的队列。其中state变量代表的是竞争资源标识,而队列代表的是竞争资源失败的线程排队时寄存的容器 。 一、原理AQS的核心思想是通过一个FIFO的队列来治理线程的期待和唤醒,同时保护了一个state变量来示意同步状态,能够通过getState、setState、compareAndSetState函数批改其值。当一个线程想要获取锁时,如果state为0,则示意该线程获取锁胜利,否则示意该线程获取锁失败。它将被放入期待队列中,直到满足特定条件能力再次尝试获取。当一个线程开释锁时,如果state为1,则示意该线程开释锁胜利,否则示意该线程开释锁失败。AQS通过CAS操作来实现加锁和解锁。 1.1 CLH队列 AQS中的CLH队列锁是CLH锁的一种变体,将自旋操作改成了阻塞线程操作。AQS 中的对 CLH 锁数据结构的改良次要包含三方面:扩大每个节点的状态、显式的保护前驱节点和后继节点以及诸如出队节点显式设为 null 等辅助 GC 的优化。 在 AQS(AbstractQueuedSynchronizer)中应用的 CLH 队列,head 指针和 tail 指针别离指向 CLH 队列中的两个要害节点。 head 指针:head 指针指向 CLH 队列中的首个节点,该节点示意以后持有锁的线程。当一个线程胜利地获取到锁时,它就成为了持有锁的线程,并且会将该信息记录在 head 指针所指向的节点中。tail 指针:tail 指针指向 CLH 队列中的最初一个节点,该节点示意队列中最初一个期待获取锁的线程。当一个线程尝试获取锁时,它会生成一个新的节点,并将其插入到 CLH 队列的尾部,而后成为 tail 指针所指向的节点。这样,tail 指针的作用是标记以后 CLH 队列中最初一个期待获取锁的线程。通过 head 指针和 tail 指针,CLH 队列可能保护一种有序的期待队列构造,保障线程获取锁的程序和互斥拜访的正确性。当一个线程开释锁时,它会批改以后节点的状态,并唤醒后继节点上的线程,让后续的线程可能及时感知锁的开释,并抢夺获取锁的机会。 1.2 线程同步对于AQS来说,线程同步的要害是对状态值state进行操作。state为0时示意没有线程持有锁,大于0时示意有线程持有锁。依据state是否属于一个线程,操作state的形式分为独占形式和共享形式。 在独占形式下获取和开释资源应用的办法为: void acquire(int arg)void acquireInterruptibly(int arg)boolean release(int arg)应用独占形式获取的资源是与具体线程绑定的,就是说如果一个线程获取到了资源,就会标记是这个线程获取到了,其余线程再尝试操作state获取资源时会发现以后该资源不是本人持有的,就会在获取失败后被阻塞。 在共享形式下获取和开释资源的办法为: void acquireShared(int arg)voidacquireSharedInterruptibly(int arg)boolean releaseShared(int arg)。对应共享形式的资源与具体线程是不相干的,当多个线程去申请资源时通过CAS形式竞争获取资源,当一个线程获取到了资源后,另外一个线程再次去获取时如果以后资源还能满足它的须要,则以后线程只须要应用CAS形式进行获取即可。 二、资源获取与开释2.1 独占式当一个线程调用acquire(int arg)办法获取独占资源时,会首先应用tryAcquire办法尝试获取资源,具体是设置状态变量state的值,胜利则间接返回,失败则将以后线程封装为类型为Node.EXCLUSIVE的Node节点后插入到AQS阻塞队列的尾部,并调用LockSupport.park(this)办法挂起本人。 public final void acquire(int arg) { if (! tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }<!----> ...

September 25, 2023 · 2 min · jiezi

关于后端:Spring源码解析-IOC默认标签解析下

注释 在上一篇咱们曾经实现了从xml配置文件到BeanDefinition的转换,转换后的实例是GenericBeanDefinition的实例。本文次要来看看标签解析残余局部及BeanDefinition的注册。 默认标签中的自定义标签解析在上篇博文中咱们曾经剖析了对于默认标签的解析,咱们持续看戏之前的代码,如下图片中有一个办法:delegate.decorateBeanDefinitionIfRequired(ele, bdHolder) 这个办法的作用是什么呢?首先咱们看下这种场景,如下配置文件: <bean id="demo" class="com.dabin.spring.MyTestBean"> <property name="beanName" value="bean demo1"/> <meta key="demo" value="demo"/> <mybean:username="mybean"/> </bean>这个配置文件中有个自定义的标签,decorateBeanDefinitionIfRequired办法就是用来解决这种状况的,其中的null是用来传递父级BeanDefinition的,咱们进入到其办法体: public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) { return decorateBeanDefinitionIfRequired(ele, definitionHolder, null);}public BeanDefinitionHolder decorateBeanDefinitionIfRequired( Element ele, BeanDefinitionHolder definitionHolder, @Nullable BeanDefinition containingBd) { BeanDefinitionHolder finalDefinition = definitionHolder; // Decorate based on custom attributes first. NamedNodeMap attributes = ele.getAttributes(); for (int i = 0; i < attributes.getLength(); i++) { Node node = attributes.item(i); finalDefinition = decorateIfRequired(node, finalDefinition, containingBd); } // Decorate based on custom nested elements. NodeList children = ele.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node node = children.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { finalDefinition = decorateIfRequired(node, finalDefinition, containingBd); } } return finalDefinition;}咱们看到下面的代码有两个遍历操作,一个是用于对所有的属性进行遍历解决,另一个是对所有的子节点进行解决,两个遍历操作都用到了decorateIfRequired(node, finalDefinition, containingBd);办法,咱们持续跟踪代码,进入办法体: ...

September 25, 2023 · 7 min · jiezi

关于后端:听GPT-讲Istio源代码pkg12

File: istio/pkg/kube/inject/inject.go在Istio我的项目中,inject.go文件的作用是对Kubernetes资源进行注入Istio sidecar代理。它是Istio注入性能的外围实现。 以下是相干变量和构造体的具体介绍: KnownImageTypes:这是一个蕴含已知镜像类型的映射表,用于确定须要注入的容器类型,如sidecar、init或proxy_init。InjectionPolicy:这个构造体用于示意注入策略,包含是否强制注入、注入的命名空间和是否注入初始化容器。SidecarTemplateData:这个构造体用于贮存模板数据,用于生成sidecar代理的注入配置。Template:这个构造体示意用于注入的模板,蕴含要注入的容器、卷和环境变量。Injector:这个构造体封装了注入逻辑,包含从规范输出读取资源、解析注入配置、生成注入后的资源、输入到规范输入等。Config:这个构造体用于解析和存储注入配置。SidecarInjectionStatus:这个构造体用于示意注入状态,记录注入是否胜利以及失败的起因。以下是相干函数的性能介绍: UnmarshalConfig:将注入配置反序列化为Config构造体。injectRequired:查看给定的资源是否须要进行注入。ProxyImage:依据给定的代理版本和代理镜像类型返回残缺的代理镜像地址。imageURL:从给定的Docker镜像名称解析镜像仓库URL。updateImageTypeIfPresent:更新给定镜像名称的镜像类型为已知类型。RunTemplate:执行模板,生成注入后的资源。knownTemplates:返回已知模板的映射表。selectTemplates:抉择实用于给定资源的模板。resolveAliases:解析注入配置中的别名。stripPod:移除Pod中的注入标记。injectionStatus:返回注入状态。parseDryTemplate:解析用于干运行注入的模板。runTemplate:运行模板,生成注入后的资源。IntoResourceFile:将注入后的资源写入文件。FromRawToObject:将原始的JSON示意转换为Kubernetes对象。IntoObject:将注入后的资源写入Kubernetes对象。applyJSONPatchToPod:利用JSON Patch到Pod对象。potentialPodName:返回Pod对象的名称。overwriteClusterInfo:笼罩集群信息。updateClusterEnvs:更新环境变量中的集群信息。GetProxyIDs:获取代理的ID列表。这些函数的性能在注入过程中起着关键作用,包含解析配置、抉择模板、生成注入后的资源以及更新相干对象。 File: istio/pkg/kube/client_factory.go在Istio我的项目中,client_factory.go文件的作用是提供一个客户端工厂,用于创立与Kubernetes集群通信的客户端对象。 以下是该文件中的变量和构造体的具体介绍: _(匿名变量):该变量用于疏忽某个值,通常用于不须要应用的返回值。overlyCautiousIllegalFileCharacters:这个变量是一个字符串,用于示意文件名中的非法字符,它的作用是用于过滤在创立文件的时候可能存在的非法字符。clientFactory(类型为struct):这个构造体是客户端工厂对象,它用于创立与Kubernetes集群通信的客户端。rESTClientGetter(类型为struct):这个构造体提供用于获取REST客户端的办法。PartialFactory(类型为struct):这个构造体是客户端工厂的局部实现,用于提供一组懒加载的组件。以下是该文件中的函数的具体介绍: newClientFactory:这个函数用于创立一个新的客户端工厂对象,并返回该对象的指针。ToRESTConfig:这个函数用于将给定的Kubernetes配置转换为REST配置对象,并返回该对象。ToDiscoveryClient:这个函数用于将给定的Kubernetes配置转换为发现客户端对象,并返回该对象。computeDiscoverCacheDir:这个函数用于计算用于缓存Kubernetes发现的目录,并返回该目录的门路。ToRESTMapper:这个函数用于将给定的Kubernetes配置转换为REST映射器对象,并返回该对象。ToRawKubeConfigLoader:这个函数用于将给定的Kubernetes配置转换为RAW KubeConfig加载器对象,并返回该对象。DynamicClient:这个函数用于创立一个动静客户端对象,用于与Kubernetes集群通信,并返回该对象。KubernetesClientSet:这个函数用于创立一个Kubernetes客户端集对象,用于与Kubernetes集群通信,并返回该对象。RESTClient:这个函数用于创立一个REST客户端对象,用于与Kubernetes集群通信,并返回该对象。这些函数的作用是为了提供一组工具和办法,用于创立各种与Kubernetes集群通信的客户端对象,以便在Istio我的项目中进行操作和治理。 File: istio/pkg/kube/client_config.go文件istio/pkg/kube/client_config.go是Istio我的项目中与Kubernetes API客户端相干的代码文件之一。它次要定义了与Kubernetes集群通信所需的配置和工具函数。 以下是对各个变量和构造体的具体介绍: _变量是一个用于空标识符的占位符变量,用于示意某些值被抛弃或疏忽。 clientConfig构造体是客户端配置的形象。它封装了与Kubernetes通信所需的认证信息、集群信息等。 ClientConfig是client-go库中定义的ClientConfig接口的实现,它定义了拜访Kubernetes API所需的配置信息,如: RawConfig:原始的kubeconfig文件的配置内容。ClientConfig:client-go库中定义的rest.Config接口的实现,用于配置与Kubernetes API通信的参数。Namespace构造体示意一个Kubernetes命名空间,并提供了与命名空间相干的一些操作方法。ConfigAccess构造体示意kubeconfig文件的拜访形式,能够从文件门路、环境变量或in-cluster配置中获取kubeconfig的配置信息。copyRestConfig函数用于复制和返回一个rest.Config对象的深拷贝。rest.Config对象是与Kubernetes API客户端进行通信的配置对象,用于设置Kubernetes API服务器的地址、认证信息等。newAuthInfo函数用于依据提供的用户名、用户证书和用户密钥创立一个新的client-go库中定义的clientcmdapi.AuthInfo接口实例。AuthInfo示意Kubernetes API的身份验证信息。newCluster函数用于依据提供的Kubernetes集群服务器地址和平安根证书创立一个新的client-go库中定义的clientcmdapi.Cluster对象的实例。Cluster示意Kubernetes集群的配置信息。NewClientConfigForRestConfig函数依据提供的rest.Config对象创立一个clientConfig对象。总的来说,文件istio/pkg/kube/client_config.go实现了与Kubernetes API通信所需的配置构造体和工具函数,不便Istio我的项目在与Kubernetes集群进行交互时进行配置和认证相干操作。 File: istio/pkg/kube/portforwarder.go在istio我的项目中,istio/pkg/kube/portforwarder.go文件的作用是实现Kubernetes端口转发性能。PortForwarder是一个接口,定义了两个办法: Start用于启动端口转发性能。Close用于敞开端口转发性能。forwarder构造体是PortForwarder接口的实现,实现了端口转发性能的具体逻辑。其中,_是一个空标识符,用于疏忽某个返回值。 Start办法用于启动端口转发性能。它会依据传入的参数创立一个Kubernetes的端口转发器,并启动端口转发性能。Address办法用于获取转发的指标地址。 Close办法用于敞开端口转发性能。它会进行端口转发器的运行。 ErrChan是一个用于接管错误信息的通道,用于向调用方传递端口转发过程中的谬误。 WaitForStop办法用于期待端口转发性能的进行。 newPortForwarder函数用于创立一个新的PortForwarder接口实例。 buildK8sPortForwarder函数用于创立一个Kubernetes端口转发器。它会依据传入的参数创立一个Kubernetes的端口转发器实例,并返回。 总体来说,istio/pkg/kube/portforwarder.go文件实现了Kubernetes端口转发性能,包含启动、敞开、创立端口转发器等性能。 File: istio/pkg/kube/labels/labels.go在istio我的项目中,istio/pkg/kube/labels/labels.go文件的作用是定义了与Kubernetes标签相干的性能函数和常量。 该文件中的nameLabels和revisionLabels变量定义了用于标识服务名称和版本的Kubernetes标签键名。这些常量被用于创立Istio对象,以便在Kubernetes中标识服务的名称和版本。 canonicalServiceRevision和canonicalServiceName函数用于从Kubernetes标签中提取服务的标准名称和版本信息。CanonicalService函数将提供的服务名称作为输出并返回标准的服务名称,CanonicalServiceRevision函数用于从标签中提取服务版本。这些函数在Istio中用于规范化服务名称和版本。 lookupLabelValue函数用于从给定的标签映射汇合中查找指定标签的值。HasCanonicalServiceName和HasCanonicalServiceRevision函数别离用于查看标签映射中是否存在特定的服务名称和版本标签。 总之,该文件中的函数和常量用于解决和操作与Kubernetes标签相干的操作,包含获取服务名称和版本信息以及标识服务的标准名称。这对于Istio的服务发现和路由性能十分重要。 File: istio/pkg/kube/namespace/filter.go在Istio我的项目中,filter.go文件位于istio/pkg/kube/namespace/目录下。该文件的作用是实现对Kubernetes namespace(命名空间)的筛选和过滤。 DiscoveryFilter是一个接口,定义了一个筛选器的办法Filter,用于依据指定的条件对命名空间进行筛选。 DiscoveryNamespacesFilter是实现了DiscoveryFilter接口的构造体,它保护了一个命名空间汇合,用于存储符合条件的命名空间。在初始化时,会调用Filter办法对现有的命名空间进行筛选。 discoveryNamespacesFilter是DiscoveryNamespacesFilter的一个实例,它保留了命名空间的信息,并提供了一些操作命名空间的办法。 NewDiscoveryNamespacesFilter是一个工厂函数,用于创立一个新的discoveryNamespacesFilter实例。 SelectorsChanged是一个办法,用于在命名空间的标签选择器产生扭转时,更新相应的命名空间信息。 notifyNamespaceHandlers办法会告诉命名空间处理器(NamespaceHandler)无关命名空间的变动。 namespaceCreated办法会在创立新的命名空间时被调用,它将新创建的命名空间增加到discoveryNamespacesFilter实例中。 namespaceUpdated办法会在命名空间产生更新时被调用,它会更新相应的命名空间信息。 namespaceDeleted办法会在命名空间被删除时被调用,它会将被删除的命名空间从discoveryNamespacesFilter中移除。 GetMembers办法用于获取discoveryNamespacesFilter中的命名空间汇合。 AddHandler办法用于向命名空间处理器列表中增加一个处理器。 addNamespace办法用于向discoveryNamespacesFilter中增加一个命名空间。 hasNamespace办法用于判断指定的命名空间是否存在于discoveryNamespacesFilter中。 removeNamespace办法用于从discoveryNamespacesFilter中移除指定的命名空间。 isSelected办法用于判断指定的命名空间是否被选中。 综上所述,filter.go文件中的这些构造体和函数的目标是实现对Kubernetes命名空间的筛选、过滤和治理。 File: istio/pkg/kube/adapter.go在Istio我的项目中,adapter.go文件位于istio/pkg/kube目录下,其作用是提供了用于与Kubernetes API服务器进行交互的适配器性能。 AdmissionReview、AdmissionRequest和AdmissionResponse是与Kubernetes的Admission控制器相干的几个构造体。 AdmissionReview是一个Kubernetes的Admission控制器申请和响应的包装器,其中蕴含了一个AdmissionRequest和一个AdmissionResponse。AdmissionRequest蕴含了对资源的创立、更新和删除申请的详细信息,如资源的类型、名称、命名空间以及申请的操作类型等。AdmissionResponse蕴含了对申请的响应后果,如是否容许申请、响应的状态码、错误信息等。AdmissionReviewKubeToAdapter和AdmissionReviewAdapterToKube是用于在Istio适配器和Kubernetes之间进行AdmissionReview构造体转换的两个函数。 AdmissionReviewKubeToAdapter函数用于将从Kubernetes API服务器接管到的AdmissionReview构造体转换为适配器中须要的构造体,以便适配器能够解决申请并生成响应。AdmissionReviewAdapterToKube函数则用于将适配器生成的响应构造体转换为适宜发送回Kubernetes API服务器的AdmissionReview构造体。这些函数的作用是将Kubernetes API服务器的申请和响应转换为适配器可能解决的格局,并将适配器解决的后果转回给Kubernetes API服务器。这样做的目标是为了让Istio适配器可能对Kubernetes的Admission控制器进行扩大和定制,以实现对资源创立、更新和删除申请的拦挡和解决。 ...

September 24, 2023 · 2 min · jiezi

关于后端:听GPT-讲Istio源代码pkg11

File: istio/pkg/test/framework/components/echo/config/param/wellknown.go在Istio我的项目中,istio/pkg/test/framework/components/echo/config/param/wellknown.go文件的作用是定义了一些罕用的网络指标配置。 WellKnown和WellKnownList这两个构造体用于示意罕用的网络指标。WellKnown构造体定义了一个蕴含罕用网络指标的列表,如echo、ingressgateway、egressgateway等。而WellKnownList构造体是WellKnown构造体的列表类型,用于示意多个网络指标的列表。 String办法用于将WellKnown构造体转换为字符串模式。ToStringArray办法用于将[]WellKnown转换为[]string模式。 AllWellKnown是一个函数,返回了所有的WellKnown常量列表。这个函数会将所有的WellKnown常量放入一个WellKnownList中,并返回该列表。 总之,wellknown.go文件中的构造体和函数定义了一些罕用的网络指标,并提供了一些办法用于在不同模式之间进行转换。 File: istio/pkg/ptr/pointer.go在Istio我的项目中,istio/pkg/ptr/pointer.go文件的作用是为了提供一些用于操作指针的工具函数。这些函数次要用于解决空指针的状况,帮忙简化代码并进步代码的可读性。 以下是对于istio/pkg/ptr/pointer.go文件中的几个函数的具体介绍: Of(value T) *T Of函数用于将给定的值value转换为一个指向该值的指针,并返回该指针。次要用于简化将非指针值转换为指针的操作。OrEmpty(value *string) string OrEmpty函数用于查看一个字符串指针value是否为nil,如果是则返回一个空字符串,否则返回指针指向的字符串值。次要用于解决可能为空的字符串指针,防止在代码中应用空指针而引发的谬误。OrDefault(value *T, defaultValue T) T OrDefault函数用于查看一个指针value是否为nil,如果是则返回一个默认值defaultValue,否则返回指针指向的值。次要用于解决可能为空的指针,防止在代码中应用空指针而引发的谬误。NonEmptyOrDefault(value *string, defaultValue string) string NonEmptyOrDefault函数用于查看一个字符串指针value是否为nil或指向的字符串是否为空。如果为空,则返回一个默认值defaultValue,否则返回指针指向的字符串值。次要用于解决可能为空的字符串指针,并在为空时提供默认值。Empty(value *string) bool Empty函数用于查看一个字符串指针value是否为nil或指向的字符串是否为空。如果为空,则返回true,否则返回false。次要用于判断字符串指针是否为空。TypeName(value interface{}) string TypeName函数用于获取给定值value的类型名称。次要用于获取类型名称以进行调试和打印日志。这些函数被设计用于解决可能为空的指针或字符串指针,以简化代码中对空指针的解决,进步代码的可读性和健壮性。 File: istio/pkg/collateral/metrics/otel.go在Istio我的项目中,istio/pkg/collateral/metrics/otel.go 文件是与 OpenTelemetry 相干的指标收集逻辑的实现。 OpenTelemetry 是一个用于跟踪、监督和收集分布式系统中运行时数据的工具包。otel.go 文件定义了一些帮忙函数和数据结构,用于将Istio的指标数据转换为OpenTelemetry格局,并将其导出到指定的监控零碎。 当初让咱们具体介绍一下 charReplacer 变量以及 promName 和 ExportedMetrics 函数的作用: charReplacer 是一个 strings.Replacer 类型的变量,用于替换指标名称中的特殊字符。在OpenTelemetry中,一些特殊字符(如.和 -)可能会导致指标名称在存储和查问过程中呈现问题。因而,charReplacer 变量是一个可重用的替换器,用于将这些特殊字符替换为无效的字符。promName 是一个辅助函数,用于将Istio中的指标名称转换为OpenTelemetry可承受的格局。该函数应用 charReplacer 变量和其余逻辑来替换特殊字符并返回无效的指标名称字符串。ExportedMetrics 是一个导出Istio指标数据到OpenTelemetry格局的函数。它承受一个 exporter 参数,用于理论导出指标数据到指定的监控零碎。函数外部定义了一些OpenTelemetry的指标 Marshaller,用于将Istio指标数据转换为OpenTelemetry格局。 这些指标 Marshaller 依据不同的Istio指标类型(如计数器、直方图等)来创立和配置相应的OpenTelemetry指标定义。指标 Marshaller 还应用 promName 函数将Istio指标名称转换为OpenTelemetry可承受的指标名称格局。导出的数据由OpenTelemetry的 BatchObserver 对象收集,并应用提供的 exporter 参数进行理论的导出操作。这些性能和变量的目标是帮忙Istio我的项目将其指标数据转换并导出到适当的监控零碎,从而能够更好地监督和剖析Istio的运行时性能。 ...

September 24, 2023 · 2 min · jiezi

关于后端:听GPT-讲Istio源代码pkg10

File: istio/pkg/security/mock.go在Istio我的项目中,istio/pkg/security/mock.go文件用于提供用于测试目标的模仿实现。此文件定义了一些构造体和函数,用于模仿认证、受权和密钥治理相干的操作。 上面是对文件中的各个局部的具体介绍: _(下划线)是一个空白标识符,用于示意一个没有名称的变量。在该文件中,应用_示意不关怀某个变量的具体值,只关怀函数调用的行为。DirectSecretManager构造体是一个模仿的密钥管理器,实现了SecretManager接口。它提供了一些用于创立、删除和获取加密密钥的办法。FakeAuthenticator构造体是一个模仿的认证器,实现了Authenticator接口。它用于模仿对申请进行认证的过程,并返回模仿的认证后果。NewDirectSecretManager函数用于创立一个新的DirectSecretManager实例。GenerateSecret函数用于生成一个模仿的加密密钥。Set函数用于模仿将加密密钥保留到密钥管理器中。NewFakeAuthenticator函数用于创立一个新的FakeAuthenticator实例。Authenticate函数用于模仿对申请进行认证的过程,并返回模仿的认证后果。authenticateHTTP函数用于模仿对HTTP申请进行认证的过程。authenticateGrpc函数用于模仿对gRPC申请进行认证的过程。AuthenticatorType函数用于返回认证器的类型。checkToken函数用于模仿查看拜访令牌的有效性。checkCert函数用于模仿查看客户端证书的有效性。这些函数和构造体的目标是为了不便在Istio我的项目的单元测试中模仿和测试认证、受权和密钥治理的逻辑。在测试中,能够应用这些模仿实现代替实在的认证、受权和密钥管理器,以便更好地管制测试的环境和后果。 File: istio/pkg/config/schema/collections/collections.agent.gen.go在Istio我的项目中,istio/pkg/config/schema/collections/collections.agent.gen.go文件是通过Go代码生成工具主动生成的,用于定义和生成Istio配置对象的汇合。 该文件的作用是定义了一系列不同类型的配置对象,这些对象代表了Istio中的各种配置资源。它们是通过Protobuf定义的,以便进行序列化和反序列化,并提供方便的API用于操作和治理这些配置资源。 以下是对其中几个变量的作用的具体介绍: AuthorizationPolicy: 用于定义并管制服务之间的拜访策略和权限规定。DestinationRule: 用于定义服务之间的流量规定,例如负载平衡、故障注入等。EnvoyFilter: 用于配置Envoy代理的过滤器,能够在申请和响应期间对流量进行自定义解决。Gateway: 用于定义Istio网格的入口点,能够将内部流量疏导到特定的服务或端口。MeshConfig: 用于配置整个Istio服务网格的全局参数、策略等。MeshNetworks: 用于定义Istio服务网格中的网络配置,例如CIDR范畴和自定义网络拓扑。PeerAuthentication: 用于配置服务之间的身份验证和流量加密。ProxyConfig: 用于配置Envoy代理的选项和参数。RequestAuthentication: 用于配置申请方的身份验证规定。ServiceEntry: 用于在Istio中注册内部服务,以便能够通过服务名进行拜访。Sidecar: 用于配置应用程序容器的Istio代理。Telemetry: 用于配置Istio的遥测个性,例如日志、指标和分布式追踪。VirtualService: 用于定义申请的路由规定、版本策略等。WasmPlugin: 用于配置WebAssembly扩大插件,以对Envoy代理进行自定义扩大。WorkloadEntry: 用于配置Istio中的工作负载,例如虚拟机、Kubernetes Pod等。WorkloadGroup: 用于定义工作负载的分组信息,反对基于标签的路由规定。All: 示意所有的配置对象汇合。Kube: 示意Kubernetes相干的配置对象汇合。Pilot: 示意Pilot服务相干的配置对象汇合。pilotGatewayAPI: 示意Pilot网关API相干的配置对象汇合。pilotStableGatewayAPI: 示意Pilot网关API的稳定版相干的配置对象汇合。这些配置对象组成了Istio的配置模型,能够通过工具或API进行定义、编辑和治理,以实现对Istio服务网格的灵便和动静的配置和管制。 File: istio/pkg/config/resource/serialization.goserialization.go文件是Istio我的项目中的一个文件,其次要作用是提供资源的序列化和反序列化性能。该文件中定义了一系列函数用于将Istio的配置资源(如PilotConfig)转换为实例。 具体来说,PilotConfigToInstance函数是serialization.go文件中的一个重要函数,其作用是将PilotConfig转换为Instance实例。PilotConfig是Istio中用于配置Pilot的一种资源类型,而Instance则是Pilot的运行实例。PilotConfig蕴含了一系列对Pilot的配置,而Instance示意一个正在运行的Pilot实例。 PilotConfigToInstance函数的次要逻辑是将PilotConfig中的各个配置项映射到Instance中的对应字段,并进行一些必要的转换和解决。例如,将PilotConfig中的监听地址转换为Instance中的监听地址,将PilotConfig中的集群配置转换为Instance中的集群配置等。 此外,serialization.go文件中还蕴含其余一些函数,如MergePilotConfig、ToPilotConfig等,它们别离用于合并PilotConfig配置、将其余资源类型转换为PilotConfig等。 总而言之,serialization.go文件是Istio我的项目中负责实现资源序列化和反序列化的文件。其中,PilotConfigToInstance函数是该文件中的一个函数,用于将PilotConfig转换为运行实例Instance,实现配置的映射和解决等操作。 File: istio/pkg/config/xds/deprecated.go在istio我的项目中,istio/pkg/config/xds/deprecated.go文件的作用是存储与Istio配置相干的弃用(filter与资源)名称,并提供了一些用于转换名称的办法。该文件定义了DeprecatedFilterNames和ReverseDeprecatedFilterNames两个变量以及相干的转换函数。 DeprecatedFilterNames变量是一个map,它存储了过期的filter名称与最新的filter名称之间的映射关系。通过这个映射关系,能够在配置降级过程中将旧的filter名称转换为新的filter名称。 ReverseDeprecatedFilterNames变量是DeprecatedFilterNames的反转映射,它存储了最新的filter名称与过期的filter名称之间的映射关系。通过这个映射关系,能够将新的filter名称转换为过期的filter名称。 这些转换函数(ReverseDeprecatedFilterNames中的ReverseLookup和ReverseFilterLookup函数)依据给定的filter名称在ReverseDeprecatedFilterNames中查找对应的过期filter名称。这些函数能够用于将最新版本的配置还原为旧版本的配置。 总之,deprecated.go文件提供了与Istio配置相干的过期(filter与资源)名称的映射关系以及相应的转换函数,不便在配置降级过程中进行名称的转换与回滚。 File: istio/pkg/config/xds/filter_types.go在Istio我的项目中,istio/pkg/config/xds/filter_types.go文件的作用是定义了与Envoy的网络过滤器相干的类型和构造体。 在Istio中,Envoy是一个开源的高性能边缘和服务代理,用于构建服务网格架构。Envoy应用网络过滤器来实现一系列的流量解决逻辑,例如路由、负载平衡、重试等。 这个文件定义了一些要害的类型和构造体,包含: FilterConfig:这是一个接口,代表了一个Envoy网络过滤器的配置。它蕴含了过滤器的类型和配置参数。FilterChainMatch:这是一个构造体,用于匹配Envoy的网络过滤器链。它指定了一个过滤器链匹配的条件,例如IP和端口等。FilterChain:这是一个构造体,代表了一个Envoy网络过滤器链的配置。它蕴含了一个或多个过滤器的配置,以及匹配条件。ListenerFilterConfig:这是一个构造体,用于配置一个Envoy监听器的网络过滤器配置。它蕴含了一个或多个过滤器链以及其余配置参数。NetworkFilterConfig:这是一个构造体,用于配置一个Envoy网络过滤器的配置。它蕴含了一个或多个针对不同端口和协定的过滤器链。这些定义的类型和构造体提供了配置和治理Envoy网络过滤器的能力。通过这些配置,用户能够定义Istio中的流量解决逻辑,并将其利用于侧车代理以实现高级的服务网格性能,例如流量管制、故障注入和安全策略等。 File: istio/pkg/config/xds/filter_types.gen.go在istio我的项目中,istio/pkg/config/xds/filter_types.gen.go文件的作用是定义和生成与XDS协定相干的过滤器类型。该文件存储了在Istio中应用的XDS过滤器的品种和构造体。 Istio中的过滤器用于实现申请和响应的转换、批改和过滤等性能。Istio应用了Envoy作为其数据立体代理,Envoy应用了XDS(Envoy的配置发现服务)协定来获取配置信息。过滤器类型定义了在数据立体中执行的特定性能和转换的逻辑。 在istio/pkg/config/xds/filter_types.gen.go文件中,首先定义了一些常量,如过滤器的名称和用于批示申请和响应方向的标记。接下来,定义了一些根本的过滤器构造体,如HTTP过滤器和TCP过滤器,以及这些过滤器所需的各种字段。 此外,该文件还定义了一些高级过滤器,如连贯管理器过滤器、网络过滤器和HTTP连贯管理器过滤器。这些高级过滤器定义了简单的逻辑和性能,用于解决连贯和网络层的操作和转换。 通过这个文件,能够清晰地理解Istio中各种过滤器的类型和构造,以及它们在XDS协定中的作用和配置。它为Istio的开发人员提供了一个不便的参考,并能帮忙他们更好地了解和扩大Istio的过滤器性能。 File: istio/pkg/test/echo/server/forwarder/xds.go在Istio我的项目中,istio/pkg/test/echo/server/forwarder/xds.go文件是一个实现了XDS(XDS是Istio中负责服务发现和负载平衡的组件)的Echo服务器的客户端库。 变量_在Go编程中被用作占位符,它用于示意一个不会被应用的值,这样能够防止编译器报错。在这个文件中,变量_被用作占位符,示意不会被应用的变量。 xdsProtocol中的构造体是用于解决XDS协定相干的逻辑,其中包含了客户端对服务端的连贯、发送和接管相干的办法。 newXDSProtocol函数用于创立一个新的XDS协定对象,它返回一个实现了EchoProtocol接口的构造体,该构造体用于在Echo服务器中解决XDS协定。ForwardEcho函数用于将申请转发到指标服务,它接管一个EchoProtocol对象、申请音讯和指标地址,并通过该EchoProtocol对象将申请转发到指标地址。Close函数用于敞开与指标服务的连贯,它接管一个EchoProtocol对象,并在该对象上调用敞开连贯的办法。newXDSConnection函数用于创立一个与指标服务的XDS连贯,它接管指标地址和一个回调函数,用于解决XDS连贯建设之后的操作。总之,istio/pkg/test/echo/server/forwarder/xds.go文件中的代码是用于实现XDS协定的Echo服务器的客户端库,它通过连贯并与指标服务通信,实现了申请的转发和连贯的敞开等性能。 File: istio/pkg/config/validation/extensionprovider.go在Istio我的项目中,istio/pkg/config/validation/extensionprovider.go文件的次要作用是验证Istio配置中的扩大提供者的有效性。该文件蕴含了多个函数,每个函数负责验证不同类型的扩大提供者。 validateExtensionProviderService:验证Istio配置中的Service扩大提供者的有效性。它会查看提供者的一些必须属性是否存在,并进行相应的错误处理和日志记录。validateExtensionProviderEnvoyExtAuthzStatusOnError:验证Istio配置中的Envoy ExtAuthz(扩大认证和受权)相干提供者的有效性。其中,该函数会查看提供者配置的StatusOnError属性是否为无效的HTTP状态码,并进行错误处理和日志记录。ValidateExtensionProviderEnvoyExtAuthzHTTP:验证Istio配置中的Envoy HTTP扩大认证和受权提供者的有效性。它会查看提供者的一些必须属性是否存在,并进行相应的错误处理和日志记录。ValidateExtensionProviderEnvoyExtAuthzGRPC:验证Istio配置中的Envoy GRPC扩大认证和受权提供者的有效性。它会查看提供者的一些必须属性是否存在,并进行相应的错误处理和日志记录。validateExtensionProviderTracingZipkin:验证Istio配置中的Zipkin追踪扩大提供者的有效性。它会查看提供者的一些必须属性是否存在,并进行相应的错误处理和日志记录。validateExtensionProviderTracingLightStep:验证Istio配置中的LightStep追踪扩大提供者的有效性。它会查看提供者的一些必须属性是否存在,并进行相应的错误处理和日志记录。validateExtensionProviderTracingDatadog:验证Istio配置中的Datadog追踪扩大提供者的有效性。它会查看提供者的一些必须属性是否存在,并进行相应的错误处理和日志记录。validateExtensionProviderTracingOpenCensusAgent:验证Istio配置中的OpenCensus Agent追踪扩大提供者的有效性。它会查看提供者的一些必须属性是否存在,并进行相应的错误处理和日志记录。validateExtensionProviderTracingSkyWalking:验证Istio配置中的SkyWalking追踪扩大提供者的有效性。它会查看提供者的一些必须属性是否存在,并进行相应的错误处理和日志记录。validateExtensionProviderMetricsPrometheus:验证Istio配置中的Prometheus指标扩大提供者的有效性。它会查看提供者的一些必须属性是否存在,并进行相应的错误处理和日志记录。validateExtensionProviderStackdriver:验证Istio配置中的Stackdriver扩大提供者的有效性。它会查看提供者的一些必须属性是否存在,并进行相应的错误处理和日志记录。validateExtensionProviderEnvoyFileAccessLog:验证Istio配置中的Envoy文件拜访日志扩大提供者的有效性。它会查看提供者的一些必须属性是否存在,并进行相应的错误处理和日志记录。ValidateExtensionProviderEnvoyOtelAls:验证Istio配置中的Envoy OpenTelemetry Access Log Service扩大提供者的有效性。它会查看提供者的一些必须属性是否存在,并进行相应的错误处理和日志记录。ValidateExtensionProviderTracingOpentelemetry:验证Istio配置中的OpenTelemetry追踪扩大提供者的有效性。它会查看提供者的一些必须属性是否存在,并进行相应的错误处理和日志记录。ValidateExtensionProviderEnvoyHTTPAls:验证Istio配置中的Envoy HTTP Access Log Service扩大提供者的有效性。它会查看提供者的一些必须属性是否存在,并进行相应的错误处理和日志记录。ValidateExtensionProviderEnvoyTCPAls:验证Istio配置中的Envoy TCP Access Log Service扩大提供者的有效性。它会查看提供者的一些必须属性是否存在,并进行相应的错误处理和日志记录。validateExtensionProvider:验证Istio配置中扩大提供者的有效性。它会依据提供者的类型调用相应的验证函数,以确保提供者配置的完整性和正确性。File: istio/pkg/config/validation/validation_agent.govalidation_agent.go文件位于istio我的项目的pkg/config/validation目录下,其作用是对Istio配置文件进行验证和校验。 ...

September 24, 2023 · 2 min · jiezi

关于后端:听GPT-讲Istio源代码pkg9

File: istio/pkg/config/analysis/msg/messages.gen.go在Istio我的项目中,istio/pkg/config/analysis/msg/messages.gen.go文件是主动生成的音讯定义文件。该文件定义了一系列的常量和函数,用于生成和治理Istio配置剖析的谬误和正告音讯。 以下是这些常量的作用: InternalError:示意外部谬误。Deprecated:示意被弃用的配置。ReferencedResourceNotFound:示意援用的资源未找到。NamespaceNotInjected:示意命名空间未注入代理。PodMissingProxy:示意短少代理的Pod。GatewayPortNotOnWorkload:示意网关端口未绑定到Workload。SchemaValidationError:示意模式验证谬误。MisplacedAnnotation:示意搁置谬误的注解。UnknownAnnotation:示意未知的注解。ConflictingMeshGatewayVirtualServiceHosts:示意网格网关和虚构服务的主机发生冲突。ConflictingSidecarWorkloadSelectors:示意多个Sidecar工作负载选择器发生冲突。MultipleSidecarsWithoutWorkloadSelectors:示意多个Sidecar没有工作负载选择器。VirtualServiceDestinationPortSelectorRequired:示意须要虚构服务指标端口选择器。MTLSPolicyConflict:示意MTLS策略抵触。DeploymentAssociatedToMultipleServices:示意部署关联到多个服务。PortNameIsNotUnderNamingConvention:示意端口名称不合乎命名约定。JwtFailureDueToInvalidServicePortPrefix:示意因为有效的服务端口前缀而导致JWT失败。InvalidRegexp:示意有效的正则表达式。NamespaceMultipleInjectionLabels:示意命名空间存在多个注入标签。InvalidAnnotation:示意有效的注解。UnknownMeshNetworksServiceRegistry:示意未知的网格网络服务注册表。NoMatchingWorkloadsFound:示意未找到匹配的工作负载。NoServerCertificateVerificationDestinationLevel:示意指标级别短少服务器证书验证。NoServerCertificateVerificationPortLevel:示意端口级别短少服务器证书验证。VirtualServiceUnreachableRule:示意无奈达到的虚构服务规定。VirtualServiceIneffectiveMatch:示意虚构服务匹配有效。VirtualServiceHostNotFoundInGateway:示意在网关中找不到虚构服务主机。SchemaWarning:示意模式正告。ServiceEntryAddressesRequired:示意Service Entry须要地址。DeprecatedAnnotation:示意被弃用的注解。AlphaAnnotation:示意alpha版本的注解。DeploymentConflictingPorts:示意部署存在抵触的端口。GatewayDuplicateCertificate:示意网关存在反复的证书。InvalidWebhook:示意有效的Webhook。IngressRouteRulesNotAffected:示意Ingress Route规定未受影响。InsufficientPermissions:示意权限有余。UnsupportedKubernetesVersion:示意不反对的Kubernetes版本。LocalhostListener:示意本地主机监听器。InvalidApplicationUID:示意有效的应用程序UID。ConflictingGateways:示意存在抵触的网关。ImageAutoWithoutInjectionWarning:示意主动注入正告的镜像。ImageAutoWithoutInjectionError:示意主动注入谬误的镜像。NamespaceInjectionEnabledByDefault:示意命名空间默认启用注入。JwtClaimBasedRoutingWithoutRequestAuthN:示意无申请身份验证的JWT基于申明的路由。ExternalNameServiceTypeInvalidPortName:示意ExternalName服务类型的有效端口名称。EnvoyFilterUsesRelativeOperation:示意EnvoyFilter应用绝对操作。EnvoyFilterUsesReplaceOperationIncorrectly:示意EnvoyFilter谬误地应用替换操作。EnvoyFilterUsesAddOperationIncorrectly:示意EnvoyFilter谬误地应用增加操作。EnvoyFilterUsesRemoveOperationIncorrectly:示意EnvoyFilter谬误地应用删除操作。EnvoyFilterUsesRelativeOperationWithProxyVersion:示意EnvoyFilter应用代理版本的绝对操作。UnsupportedGatewayAPIVersion:示意不反对的Gateway API版本。InvalidTelemetryProvider:示意有效的遥测提供商。PodsIstioProxyImageMismatchInNamespace:示意命名空间中Istio代理镜像不匹配的Pod。ConflictingTelemetryWorkloadSelectors:示意存在抵触的遥测工作负载选择器。MultipleTelemetriesWithoutWorkloadSelectors:示意多个遥测没有工作负载选择器。InvalidGatewayCredential:示意有效的网关凭据。而这些函数(例如NewInternalError、NewDeprecated、NewReferencedResourceNotFound等)是用于生成对应音讯的构造函数,通过这些函数能够创立特定的音讯对象,以便在Istio配置剖析过程中返回或应用这些音讯。这些函数接管参数并返回相应的音讯对象,从而提供了一种不便的形式来创立和治理不同类型的音讯。 File: istio/pkg/log/scope.go在istio我的项目中,istio/pkg/log/scope.go文件定义了日志作用域(Scope)。它提供了一种机制来治理和配置日志输入,以及定义日志级别和格局。 scopes变量是保留曾经注册的日志作用域的全局映射。该映射以字符串作为键,对应着各个不同的日志作用域。lock变量是一个用于爱护scopes变量的互斥锁。它确保对scopes变量的并发拜访是平安的。 Scope构造体是一个日志作用域实例。它定义了一个特定的日志输入范畴,能够通过名称和标签来标识。Scope构造体中有以下几个重要字段和办法: Name字段示意作用域的名称。Description字段是作用域的形容信息。SetOutputLevel办法用于设置输入日志的级别。SetStackTraceLevel办法用于设置输入日志时的堆栈跟踪级别。SetLogCallers办法用于设置是否在日志音讯中显示调用者的信息。WithLabels办法用于创立一个带有额定标签的新的日志作用域。以下是Scope构造体中定义的函数和变量的作用: RegisterScope函数用于注册一个新的日志作用域。registerScope函数是RegisterScope函数的外部实现,它注册一个新的日志作用域到scopes变量中。FindScope函数依据作用域名称查找对应的Scope对象。Scopes函数返回所有已注册的作用域。Fatal函数输入一个致命谬误级别的日志音讯。Fatalf函数输入一个带格式化字符串的致命谬误级别的日志音讯。FatalEnabled函数用于查看致命谬误级别的日志音讯是否启用。Error函数输入一个谬误级别的日志音讯。Errorf函数输入一个带格式化字符串的谬误级别的日志音讯。ErrorEnabled函数用于查看谬误级别的日志音讯是否启用。Warn函数输入一个正告级别的日志音讯。Warnf函数输入一个带格式化字符串的正告级别的日志音讯。WarnEnabled函数用于查看正告级别的日志音讯是否启用。Info函数输入一个信息级别的日志音讯。Infof函数输入一个带格式化字符串的信息级别的日志音讯。InfoEnabled函数用于查看信息级别的日志音讯是否启用。Debug函数输入一个调试级别的日志音讯。Debugf函数输入一个带格式化字符串的调试级别的日志音讯。DebugEnabled函数用于查看调试级别的日志音讯是否启用。Name办法返回作用域的名称。Description办法返回作用域的形容信息。GetOutputLevel办法获取作用域的输入日志级别。GetStackTraceLevel办法获取作用域输入日志时的堆栈跟踪级别。GetLogCallers办法获取作用域是否显示调用者的信息。copy函数用于复制一个键值对类型的映射。emit函数用于输入日志音讯。copyStringInterfaceMap函数用于复制一个字符串与接口类型值的映射。maybeSprintf函数依据给定的参数生成格式化字符串。综上所述,istio/pkg/log/scope.go文件中的Scope构造体和相干函数提供了在Istio我的项目中治理和配置日志输入的性能。它们能够依据不同的作用域设置日志级别、格式化字符串和堆栈跟踪级别等。 File: istio/pkg/config/analysis/local/defaults.go在Istio我的项目中,defaults.go文件位于istio/pkg/config/analysis/local/目录下。它的次要作用是提供默认配置和生成配置的性能。 getDefaultIstioIngressGateway()函数的作用是获取默认的Istio入口网关配置。在Istio中,入口网关用于将内部流量导入到服务网格中。该函数返回一个默认的Istio入口网关配置对象。generate()函数的作用是生成默认配置。该函数通过调用不同的子函数来生成不同局部的默认配置。上面是generate()函数中调用的子函数及其作用: generateDefaultsForAuthn():生成默认的认证配置。generateDefaultsForAuthz():生成默认的受权配置。generateDefaultsForDiscovery():生成默认的服务发现配置。generateDefaultsForNetworking():生成默认的网络配置。generateDefaultsForKubernetes():生成默认的Kubernetes配置。generateDefaultsForExtensions():生成默认的扩大配置。这些子函数通过设置不同的默认值和选项来生成相应的配置对象,以满足Istio的要求。 总体而言,defaults.go文件在Istio我的项目中扮演着提供默认配置和生成配置的角色,以便用户能够疾速开始应用和配置Istio。 File: istio/pkg/config/analysis/local/local.go在Istio我的项目中,local.go文件位于istio/pkg/config/analysis目录下,它的次要作用是提供本地配置剖析的性能。更具体地说,local.go文件定义了一些针对Istio配置对象进行本地剖析的办法和构造体。 在该文件中,有如下几个构造体: AnalysisResult: 该构造体示意一个配置剖析后果,蕴含了一组与配置相干的问题和正告。它的定义如下:type AnalysisResult struct { // In one analysis the config can emit warnings or problems. Warnings []*AnalyzerWarning `json:"warnings,omitempty"` Problems []*AnalyzerProblem `json:"problems,omitempty"` Config interface{} `json:"config"`}其中,Warnings和Problems别离是AnalyzerWarning和AnalyzerProblem构造体的切片,示意配置剖析过程中发现的正告和问题。Config字段则示意进行剖析的配置对象。 AnalyzerWarning: 该构造体示意一个配置剖析的正告,蕴含了正告的级别、分类和具体的形容信息。定义如下:type AnalyzerWarning struct { Id string `json:"id"` Severity Level `json:"severity"` Category Category `json:"category"` Message string `json:"message"` Keys []*Key `json:"keys"` Suggestions []string `json:"suggestions,omitempty"`}该构造体蕴含了以下字段: ...

September 24, 2023 · 2 min · jiezi

关于后端:12张图一次性搞懂高性能并发容器ConcurrentLinkedQueue

12张图一次性搞懂高性能并发容器ConcurrentLinkedQueue前言上篇文章聊到并发汇合CopyOnWeiteArrayList的实现与特点,其不足之处是不适宜写多的场景也不适宜并发量大的场景 本篇文章来聊聊并发场景下高性能的ConcurrentLinkedQueue 浏览本文大略须要10分钟 在浏览本文前,须要了解CAS、volatile等常识 如果不了解CAS能够查看这篇文章15000字、6个代码案例、5个原理图让你彻底搞懂Synchronized 的第二大节 如果不了解volatile能够查看这篇文章5个案例和流程图让你从0到1搞懂volatile关键字 数据结构ConcurrentLinkedQueue从名称上来看就可能晓得,它反对并发、由链表实现的队列 通过源码,咱们能够看到ConcurrentLinkedQueue应用字段记录首尾节点、并且节点的实现是单向链表 并且这些关键字段都被volatile润饰,在读场景下应用volatile保障可见性,不必“加锁” 还有一些其余字段,比方应用CAS的Unsafe和一些偏移量信息等,这里就不一一列举 public class ConcurrentLinkedQueue<E> extends AbstractQueue<E> implements Queue<E>, java.io.Serializable { private static class Node<E> { //记录数据 volatile E item; //后继节点 volatile Node<E> next; } //首节点 private transient volatile Node<E> head; //尾节点 private transient volatile Node<E> tail; } 在初始化时,首尾节点会同时指向一个存储数据为空的节点 public ConcurrentLinkedQueue() { head = tail = new Node<E>(null); }设计思维提早更新首尾节点在查看实现原理前,咱们先来说说ConcurrentLinkedQueue的设计思维,否则实现原理可能会看不懂 ConcurrentLinkedQueue写场景中采纳乐观锁的思维,应用CAS+失败重试来保障操作的原子性 为了防止CAS开销过大,ConcurrentLinkedQueue采纳提早更新首尾节点的思维,来缩小CAS次数 也就是说ConcurrentLinkedQueue中的首尾节点并不一定是最新的首尾节点 哨兵节点ConcurrentLinkedQueue的设计中应用哨兵节点 什么是哨兵节点? 哨兵节点又称虚构节点,哨兵节点常应用在链表这种数据结构中 单向链表中如果要增加或者删除某个节点时,肯定要取得这个节点的前驱节点再去进行操作 当操作的是第一个节点时,如果在第一个节点后面加个虚构节点(哨兵节点),那么就不必非凡解决 ...

September 24, 2023 · 2 min · jiezi

关于后端:工作五年多idea插件推荐一

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 原本打算一次更新完的。。感觉还是太多了,前面再分享吧,先分享一部分 Easy JavadocEasy Javadoc 是一个 IntelliJ IDEA 的插件,它可能帮忙 Java 和 Kotlin 开发者主动生成 Javadoc 和 Kdoc 文档正文。该插件反对多种翻译服务,能够依据办法名主动翻译正文内容,并反对自定义映射。同时,EasyJavadoc 还反对选中中文进行翻译,无需切换到其余工具。 装置 Easy Javadoc 插件非常简单,只须要在 IntelliJ IDEA 的插件页面搜寻"Easy Javadoc",而后点击装置并重启 IDEA 即可。 应用 Easy Javadoc 插件也十分不便。你能够将光标搁置在想要生成正文的类、办法或属性上,而后按下快捷键"ctrl \"(Windows)或"command\"(Mac)即可生成正文。插件会依据办法名主动生成正文,你只须要补充具体的形容即可。此外,你还能够选中中文进行翻译,或者自定义映射来进步翻译的准确性。 Easy Javadoc 插件还反对批量生成文档正文和自定义模板,方便快捷地生成多个类的正文。你能够在插件的配置页面进行相干设置,包含抉择翻译服务、自定义映射、配置快捷键等。 TransactionTranslation 是一个 IntelliJ IDEA 的插件,它能够帮忙开发者进行翻译和替换文本。该插件反对多种翻译引擎,包含 MicrosoftTranslator、Google Translate、DeepL Translator 等。你能够抉择要翻译的文本,而后应用快捷键或右键菜单进行翻译。此外,插件还反对翻译文档、自动识别单词和主动断词等性能。 要装置 Translation 插件,你能够在 IntelliJ IDEA 的插件页面搜寻"Translation"并进行装置。装置实现后,你能够在 IDEA 的工具栏或右键菜单中找到 Translation 插件的性能。 应用 Translation 插件非常简单。你能够选中要翻译的文本,而后应用快捷键或右键菜单进行翻译。插件会依据你的设置抉择适合的翻译引擎,并显示翻译后果。你还能够应用插件的其余性能,如替换文本、翻译文档等。 .ignore.ignore 插件是一个用于生成.gitignore 文件的 IntelliJ IDEA 插件。.gitignore 文件用于指定要疏忽的文件和文件夹,这些文件和文件夹在应用 Git 进行版本控制时不会被跟踪和提交。 ...

September 24, 2023 · 2 min · jiezi

关于后端:CSIT121系统设计实践

CSIT121 Assignment 2: Dietary Recommendation System for Australian Dairy IndustryDue Date: Week 9, 24th September 2023, 11.30 pm Marks: 10 1. ObjectiveThe objective of Assignment 2 is to apply the object-oriented design and programming knowledge gained from Week 1 to Week 8 lectures. In this assignment, students will design a Python program using UMLclass diagrams to aid the Australian dairy industry in providing daily dairy and nutrient intake recommendations tailored toindividuals of different genders, ages, and special requirements (refer to Fig. 1).Fig 1. People in different categories and/orwithdifferentrequirementsFig 2. Five healthy food groupsThe proposed Python program should facilitate collecting user information and preferences through user inputs and generate comprehensive diet recommendations, including five food groups, i.e., vegetables, grain foods, meat products, dairy products, and fruits (refer to Fig.2), based on different user categories, e.g., children (Appendix B), adults (Appendix C), and pregnant women (Appendix D) (refer to Fig. 3).Fig 3. Recommended healthy food intake for ChildrenAdditional reference materials is provided in the appendix. The program must gracefully handle unexpected and inappropriate user inputs by utilising Python's exception-handling mechanisms (i.e., try and except). Furthermore, the program should allow users to import/export recommended diets for printing, reuse, and documentation using file I/O methods. Students are also required to design program tests using the Python unittest module, analyse the test results, and evaluate the code coverage achieved by their tests. ...

September 24, 2023 · 4 min · jiezi

关于后端:面试题精讲Mysql的rownumber函数

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 系列文章地址 1. 什么是 MySQL 的 ROW_NUMBER()函数?ROW_NUMBER()是 MySQL 中的一个窗口函数,用于为查问后果集中的每一行调配一个惟一的间断整数值。它能够依据指定的排序规定对后果进行排序,并为每一行调配一个序号。 2. 为什么须要应用 MySQL 的 ROW_NUMBER()函数?在某些状况下,咱们可能须要对查问后果进行编号或者依照特定的程序进行排序。ROW_NUMBER()函数提供了一种简略而无效的办法来实现这个指标。通过应用 ROW_NUMBER()函数,咱们能够轻松地为后果集中的每一行调配一个惟一的序号,并且能够依据须要对后果进行排序。 3. MySQL ROW_NUMBER()函数的实现原理MySQL 并没有内置的 ROW_NUMBER()函数,但咱们能够应用变量和子查问来模仿实现该性能。具体步骤如下: 首先,在查问语句中增加一个变量,并初始化为 0。而后,应用子查问将后果集依照指定的排序规定排序。接下来,应用 SELECT 语句从子查问中抉择所有列,并在每一行上递增变量的值。最初,返回带有行号的后果集。以下是一个示例代码,演示了如何应用 ROW_NUMBER()函数: SET @row_number = 0;SELECT (@row_number:=@row_number + 1) AS row_number, column1, column2FROM tableORDER BY column1;在下面的代码中,咱们首先将变量@row_number初始化为 0。而后,在 SELECT 语句中应用子查问对后果集进行排序,并通过递增@row_number的值来为每一行调配一个惟一的序号。 4. MySQL ROW_NUMBER()函数的应用示例假如咱们有一个名为employees的表,蕴含员工的姓名和薪水信息。当初咱们想要依照薪水从高到低的程序对员工进行排名,并为每个员工调配一个惟一的序号。 以下是一个应用 ROW_NUMBER()函数的示例: SET @row_number = 0;SELECT (@row_number:=@row_number + 1) AS rank, name, salaryFROM employeesORDER BY salary DESC;在下面的示例中,咱们首先将变量@row_number初始化为 0。而后,应用 ROW_NUMBER()函数为每个员工调配一个惟一的序号,并依据薪水字段进行降序排序。 5. MySQL ROW_NUMBER()函数的长处简略易用:ROW_NUMBER()函数提供了一种简略而直观的办法来为查问后果集中的每一行调配一个惟一的序号。灵活性:能够依据须要指定不同的排序规定,并且能够与其余窗口函数联合应用。6. MySQL ROW_NUMBER()函数的毛病须要应用变量和子查问:因为 MySQL 没有内置的 ROW_NUMBER()函数,咱们须要应用变量和子查问来模仿实现该性能。这可能会减少代码的复杂性。性能影响:在解决大型数据集时,应用 ROW_NUMBER()函数可能会对性能产生肯定的影响。7. MySQL ROW_NUMBER()函数的应用注意事项变量初始化:在应用 ROW_NUMBER()函数之前,务必将变量初始化为 0 或其余适当的值。排序规定:依据须要指定正确的排序规定,以确保后果依照预期进行排序。数据类型:请留神,ROW_NUMBER()函数返回的是一个整数值。8. 总结MySQL 的 ROW_NUMBER()函数是一个弱小而灵便的窗口函数,用于为查问后果集中的每一行调配一个惟一的间断整数值,并能够依据指定的排序规定对后果进行排序。只管 MySQL 并没有内置的 ROW_NUMBER()函数,但咱们能够应用变量和子查问来模仿实现该性能。通过应用 ROW_NUMBER()函数,咱们能够轻松地对查问后果进行编号和排序,进步查问的灵活性和可读性。然而,在应用 ROW_NUMBER()函数时须要留神变量的初始化、排序规定的设置以及潜在的性能影响。 ...

September 24, 2023 · 1 min · jiezi

关于后端:掌握-Go-的计时器

简介定时器是任何编程语言的重要工具,它容许开发人员在特定工夫距离安顿工作或执行代码。在 Go 中,定时器是通过 time 包实现的,该包提供了一系列性能来创立、启动、进行和无效解决定时器。咱们将摸索 Go 中定时器的弱小性能,并通过代码示例演示如何在应用程序中应用定时器。 创立计时器要在 Go 中创立一个定时器,咱们能够应用 time.NewTimer() 函数,该函数将持续时间作为参数。上面是一个示例: func CreateTimer() { timer := time.NewTimer(2 * time.Second) fmt.Println("Timer created.") <-timer.C // 阻塞 fmt.Println("Timer expired.")}在上述代码片段中,咱们应用 time.NewTimer() 创立了一个持续时间为 2 秒的新定时器。<-timer.C 语句会阻塞执行,直到定时器过期。定时器到期后,"Timer expired."(定时器已过期)信息将打印到控制台。 进行计时器在某些状况下,您可能想在定时器到期前进行它。为此,您能够应用定时器对象的 Stop() 办法。让咱们批改之前的示例,退出定时器进行性能: func StopTimer() { timer := time.NewTimer(2 * time.Second) fmt.Println("Timer created.") go func() { <-timer.C fmt.Println("Timer expired.") }() time.Sleep(1 * time.Second) stopped := timer.Stop() if stopped { fmt.Println("Timer stopped.") } else { fmt.Println("Timer has already expired.") }}在更新后的代码中,咱们创立了一个 goroutine 来解决定时器过期,这样就能够在定时器过期前进行它。咱们应用 time.Sleep() 函数来模仿在尝试进行计时器之前正在进行的一些工作。最初,咱们调用 timer.Stop() 进行定时器。如果定时器已过期,timer.Stop() 返回 false,并打印 "定时器已过期"。否则,咱们将打印 "定时器已进行"。 ...

September 24, 2023 · 2 min · jiezi

关于后端:代码整洁之道程序员的职业素养十四

团队与我的项目组建团队是一个须要工夫和急躁的过程。团队成员须要建设关系,学习如何相互协作,并理解彼此的劣势和劣势。只有通过一段时间的相处和磨合,团队能力造成真正的凝聚力。 当团队克服个体差异,造成默契配合和相互信任的关系时,就会产生一种神奇的魔力。这个团队可能一起制订打算、解决问题,并独特面对和实现各种工作。这种团队凝聚力的造成须要工夫,但一旦造成,团队的效率和成绩将会大大晋升。 业余的开发组织会将我的项目调配给曾经造成凝聚力的团队,而不是围绕我的项目来组建团队。这样的团队能够同时承接多个我的项目,并依据成员的技能和能力来调配工作,从而顺利完成我的项目。 作为我的项目承包人,如果领有一个团队专一于本人的我的项目,就可能分明地计算团队的投入。他们晓得组建和遣散团队都是一项代价昂扬的工作,因而公司也不会轻易调走团队。这样的团队能够为公司节省时间和资源,并进步我的项目的成功率。 然而,组建和遣散团队只是人为的艰难,并不应该限度公司的决策。如果公司认为某个我的项目的优先级更高,应该迅速重新分配资源。我的项目承包人的职责就是清晰地定义和论述我的项目的价值和意义,以取得公司管理层的认可和反对。 团队的构建比我的项目自身更具挑战性。因而,建设稳固的团队,让他们在不同我的项目中继续单干,成为一个弱小的合作引擎,是更好的做法。团队也能够同时承接多个我的项目,进步整体效率。在组建团队时,给予他们短缺的工夫,让他们造成凝聚力,并继续独特工作,这样能力一直交付出优良的我的项目成绩。 总结起来,组建团队须要工夫和急躁。团队的凝聚力是一个神奇的魔力,可能让团队成员独特合作、解决问题,并获得优良的成绩。业余的开发组织会将我的项目调配给已有凝聚力的团队,以进步工作效率和成功率。团队的构建比我的项目自身更具挑战性,但只有通过继续单干和独特工作,团队能力成为一个弱小的合作引擎。

September 24, 2023 · 1 min · jiezi

关于后端:JDK21更新内容结构化并发编程

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 文章更新打算 | 453: | Structured Concurrency (Preview) |什么是结构化并发(Structured Concurrency)?结构化并发是一种用于简化并发编程的API。它将在不同线程中运行的相干工作组视为一个独自的工作单元,从而简化错误处理和勾销操作,进步可靠性,并加强可察看性。 为什么须要结构化并发?传统的并发编程模型,如ExecutorServiceAPI,因为其无限度的并发模式,引入了复杂性和危险。这些模型没有强制执行或跟踪工作和子工作之间的关系,使得治理和察看并发工作变得艰难。结构化并发模型认为工作构造应该反映代码构造,在单线程代码中,执行总是强制施行工作和子工作的层次结构,每个子工作的生命周期绝对于其余子工作受到代码的语法块构造的管制。 结构化并发旨在打消与并发编程相干的常见危险,例如线程透露和勾销提早,并加强并发代码的可察看性。 结构化并发的实现原理结构化并发通过引入新的API来实现,其中最重要的类是StructuredTaskScope。StructuredTaskScope封装了一组相干的工作,这些工作应该一起实现,如果任何子工作失败,则会勾销残余的子工作。 在结构化并发中,应用StructuredTaskScope创立一个作用域,在该作用域内能够派生出多个子工作。这些子工作将被视为整体,并且它们之间存在依赖关系。当所有子工作实现后,能够对它们进行解决,例如获取后果或抛出异样。 结构化并发的长处简化并发编程:结构化并发提供了一种更简略、更直观的形式来解决并发工作。错误处理和勾销操作:通过将相干工作组合成一个单元,结构化并发使错误处理和勾销操作更加容易和牢靠。进步可靠性:结构化并发模型打消了常见的危险,如线程透露和勾销提早,从而进步了并发代码的可靠性。加强可察看性:结构化并发模型使得察看并发工作的执行状态变得更加不便。结构化并发的毛病预览性能:目前,结构化并发仍处于预览阶段,须要启用预览性能能力应用。结构化并发的应用示例上面是一个应用结构化并发的示例代码: Response handle() throws ExecutionException, InterruptedException { try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { Supplier<String> user = scope.fork(() -> findUser()); Supplier<Integer> order = scope.fork(() -> fetchOrder()); scope.join() .throwIfFailed(); return new Response(user.get(), order.get()); } }在这个示例中,咱们创立了一个新的StructuredTaskScope作用域,并应用它派生了两个子工作:一个执行findUser()办法,另一个执行fetchOrder()办法。一旦两个子工作都实现,就能够应用它们的后果创立一个新的Response对象。 结构化并发的应用注意事项结构化并发是一个预览性能,默认状况下被禁用。要应用StructuredTaskScope API,开发人员必须启用预览性能来编译代码。应用结构化并发时,通常不间接应用StructuredTaskScope类,而是应用实现敞开策略的两个子类之一。这些子类别离是ShutdownOnFailure和ShutdownOnSuccess,反对当第一个子工作失败或胜利时敞开作用域的模式。运行结构化并发程序时,须要应用--enable-preview选项启用预览性能。总结结构化并发是一种用于简化并发编程的API,它将相干工作组合成一个单元,从而简化错误处理和勾销操作,进步可靠性,并加强可察看性。通过引入StructuredTaskScope类和相干的子类,结构化并发提供了一种更简略、更直观的形式来解决并发工作。然而,须要留神的是,结构化并发目前仍处于预览阶段,并且须要启用预览性能能力应用。 JDK 21 将是大多数供应商的长期反对 (LTS) 版本。无关自上一个 LTS 版本 JDK 17 以来集成的 JEP的残缺列表,请参阅 here.<!-- md tj.md --> 本文由mdnice多平台公布

September 24, 2023 · 1 min · jiezi

关于后端:JDK21更新内容新的密钥封装机制

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 文章更新打算 | 452: | Key Encapsulation Mechanism API |1. 什么是Key Encapsulation Mechanism API?Key Encapsulation Mechanism (KEM) API 是一个 JavaAPI,用于反对密钥封装机制。密钥封装是一种加密技术,它将一个对称密钥(也称为会话密钥)与公钥联合应用,以便在不间接裸露私钥的状况下平安地传输密钥。 KEM API 提供了一组办法和类,用于生成、封装和解封装密钥。它能够与现有的密码学算法和协定集成,提供更高级别的密钥治理性能。 2. 为什么须要Key Encapsulation Mechanism API?在传统的密钥替换过程中,通常须要当时共享或散发密钥。这可能存在许多平安危险,例如密钥泄露、中间人攻打等。而密钥封装机制通过应用公钥进行密钥替换,防止了这些问题。 Key Encapsulation Mechanism API 的呈现使得开发者可能更不便地实现密钥封装机制,并提供了更高级别的密钥治理性能。它简化了密钥生成、封装和解封装的过程,同时保障了安全性和可靠性。 3. Key Encapsulation Mechanism API的实现原理Key Encapsulation Mechanism API 的实现原理基于非对称加密算法和密钥封装机制。它应用公钥进行密钥替换,并通过将会话密钥封装在一个平安的密文中,以确保密钥的平安传输。 具体实现过程如下: 生成一对公私钥对。应用公钥进行密钥封装,生成一个密文。将密文发送给接管方。接管方应用私钥解封装密文,失去会话密钥。单方能够应用会话密钥进行加密通信。4. Key Encapsulation Mechanism API的长处安全性高:Key Encapsulation Mechanism API 应用了非对称加密算法和密钥封装机制,可能提供较高的安全性,防止了密钥泄露和中间人攻打等问题。易于应用:API 提供了简略易用的办法和类,开发者能够轻松地生成、封装和解封装密钥,无需深刻理解底层算法和协定。灵活性强:API 能够与现有的密码学算法和协定集成,提供更高级别的密钥治理性能,满足不同场景的需要。5. Key Encapsulation Mechanism API的毛病依赖于非对称加密算法:Key Encapsulation Mechanism API 的实现依赖于非对称加密算法,这些算法可能存在性能上的瓶颈和限度。须要爱护私钥的平安:因为应用了非对称加密算法,私钥的平安至关重要。开发者须要采取措施来爱护私钥的机密性和完整性。6. Key Encapsulation Mechanism API的应用示例上面是一个简略的应用示例,演示了如何应用 Key Encapsulation Mechanism API 进行密钥封装和解封装: ...

September 24, 2023 · 1 min · jiezi

关于后端:JDK21更新内容舍弃对x86架构32位系统支持

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 文章更新打算 | 449: | Deprecate the Windows 32-bit x86 Port for Removal |名字太长了。。前面简称 449 1. 什么是JEP 449?JEP 449(Java Enhancement Proposal 449)是一个针对OpenJDK的提案,旨在废除并最终移除Windows 32位x86平台上的Java反对。 2. 为什么须要废除Windows 32位x86平台上的Java反对?次要有以下几个起因: 过期的硬件和操作系统:Windows 32位x86平台曾经逐步被淘汰,古代计算机广泛采纳64位架构。同时,大多数新版本的Windows操作系统也只提供了64位版本。性能限度:32位架构限度了可寻址内存空间的大小,导致无奈充分利用古代计算机的资源。而64位架构能够提供更大的内存地址空间,从而进步应用程序的性能和扩展性。平安问题:32位架构存在一些安全漏洞和限度,例如缓冲区溢出等。而64位架构通过引入更多的爱护机制来减少应用程序的安全性。基于以上起因,废除Windows 32位x86平台上的Java反对是正当且必要的。 3. JEP 449的实现原理JEP 449的实现原理波及到编译器、虚拟机和库等多个方面的改变。 编译器层面:废除32位x86平台上的Java反对须要对编译器进行批改,禁止生成32位x86架构的指标代码。虚拟机层面:虚拟机须要对内存治理、垃圾回收等进行调整,以适应64位架构的个性。同时,还须要更新与操作系统交互的局部代码,确保在64位环境下失常运行。库层面:一些与硬件相干的库可能须要从新编写或者替换为64位版本,以充分利用64位架构的劣势。具体实现细节能够参考JEP 449提案中的具体阐明。 4. JEP 449的长处性能晋升:64位架构能够提供更大的内存地址空间,从而进步应用程序的性能和扩展性。平安加强:64位架构引入了更多的爱护机制,进步了应用程序的安全性。与古代计算机趋势相符:Windows 32位x86平台曾经逐步被淘汰,废除该平台上的Java反对是与时俱进的动作。5. JEP 449的毛病向后兼容性问题:废除Windows 32位x86平台上的Java反对可能导致一些现有的应用程序无奈在该平台上运行。这须要开发人员进行相应的迁徙和调整。**对于依然应用32位硬件和操作系统的用户而言,将无奈持续取得新版本的Java更新和性能改良。6. JEP 449的应用示例JEP 449是一个OpenJDK的提案,它次要影响到OpenJDK的开发者和Windows 32位x86平台上的Java用户。对于开发者来说,他们须要依据JEP449的施行状况,适时地迁徙和调整本人的利用程序代码。对于Windows32位x86平台上的Java用户来说,他们须要思考降级到64位架构的计算机和操作系统,以持续取得最新的Java更新和性能改良。 7. JEP 449的应用注意事项开发者须要及时关注JEP 449的施行状况,并依据须要进行相应的迁徙和调整。Windows 32位x86平台上的Java用户须要思考降级到64位架构的计算机和操作系统,以持续取得最新的Java更新和性能改良。8. 总结JEP 449旨在废除并最终移除Windows32位x86平台上的Java反对。这是基于该平台曾经逐步被淘汰、性能限度和平安问题等起因做出的正当动作。废除该平台上的Java反对能够进步应用程序的性能和安全性,并与古代计算机趋势相符。开发者须要及时关注JEP449的施行状况,并依据须要进行相应的迁徙和调整。Windows 32位x86平台上的Java用户须要思考降级到64位架构的计算机和操作系统,以持续取得最新的Java更新和性能改良。<!-- md tj.md --> 本文由mdnice多平台公布

September 24, 2023 · 1 min · jiezi

关于后端:JDK21更新内容向量计算

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 文章更新打算 | 448: | Vector API (Sixth Incubator) |1. 什么是Vector API (Sixth Incubator)?Vector API (Sixth Incubator) 是 Java 平台的一个我的项目,旨在提供一种简略且高效的形式来执行向量化计算。它引入了新的类和接口,以反对应用SIMD(Single Instruction, Multiple Data)指令集进行并行计算。 2. 为什么须要Vector API (Sixth Incubator)?在许多应用程序中,存在大量的数据并行计算工作,例如图像处理、科学计算和机器学习等畛域。传统的 Java编程模型无奈充分利用古代硬件的并行计算能力,导致性能低下。而 Vector API (Sixth Incubator) 的指标就是通过向量化计算来进步这些应用程序的性能。 3. Vector API (Sixth Incubator) 的实现原理?Vector API (Sixth Incubator) 基于 SIMD 指令集,即单指令多数据流指令集。SIMD 指令集能够同时对多个数据元素执行雷同的操作,从而实现并行计算。VectorAPI (Sixth Incubator) 提供了一组新的类和接口,使开发人员可能间接编写基于 SIMD 指令集的代码。 具体来说,Vector API (Sixth Incubator) 引入了 java.util.vector 包,其中蕴含了一些新的类和接口,如 Vector、FloatVector和 IntVector 等。这些类提供了一组向量化操作方法,例如加法、减法、乘法等,以及对应的掩码操作。 在底层实现上,Vector API (Sixth Incubator) 应用了特定硬件平台的 SIMD 指令集来执行向量化计算。具体实现细节会依赖于不同的硬件架构和操作系统。 ...

September 24, 2023 · 1 min · jiezi

关于后端:JDK21更新内容匿名类和实例主方法

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 文章更新打算 | 445: | Unnamed Classes and Instance Main Methods (Preview) |1. 什么是Unnamed Classes and Instance Main Methods (Preview)?"Unnamed Classes and Instance Main Methods" 是一个 Java 编程语言的新个性,它在 JDK 14 中引入,并在 JDK 15中成为预览性能。该个性容许咱们在类中定义匿名类和实例主办法。 在传统的 Java 编程中,咱们只能在顶级类或动态外部类中定义 main 办法作为程序的入口点。而应用 "Unnamed Classes and InstanceMain Methods" 个性后,咱们能够在任何类的实例中定义 main 办法,从而使得程序的入口点更加灵便。 2. 为什么须要Unnamed Classes and Instance Main Methods?传统的 Java 程序必须将 main办法定义在顶级类或动态外部类中,这限度了程序的构造和组织形式。有时候,咱们可能心愿将多个相干的逻辑封装在同一个类的实例中,以进步代码的可读性和可维护性。而 "Unnamed Classes and Instance Main Methods" 个性正是为了满足这种需要而引入的。 通过在类的实例中定义 main 办法,咱们能够更好地组织和管理程序的逻辑,缩小顶级类和动态外部类的数量,使代码更加清晰和易于了解。 3. Unnamed Classes and Instance Main Methods 的实现原理"Unnamed Classes and Instance Main Methods" 个性的实现原理波及到两个方面:匿名类和实例主办法。 ...

September 24, 2023 · 1 min · jiezi

关于后端:quarkus依赖注入之十学习和改变bean懒加载规则

欢送拜访我的GitHub这里分类和汇总了欣宸的全副原创(含配套源码):https://github.com/zq2599/blog_demos本篇概览本篇是《quarkus依赖注入》系列的第十篇,来看一个容易被疏忽的知识点:bean的懒加载,咱们先去理解quarkus框架下的懒加载规定,而后更重要的是把握如何扭转规定,以达到提前实例化的指标总的来说本篇由以下内容形成对于懒加载编码体验懒加载扭转懒加载规定的第一种伎俩扭转懒加载规定的第二种伎俩(竟然和官网材料有出入)小结对于懒加载(Lazy Instantiation)CDI标准下的懒加载规定:惯例作用域的bean(例如ApplicationScoped、RequestScoped),在注入时,实例化的是其代理类,而实在类的实例化产生在bean办法被首次调用的时候伪作用域的bean(Dependent和Singleton),在注入时就会实例化quarkus也遵循此规定,接下来编码验证编码验证懒加载为了验证bean的懒加载,接下来会写这样一些代码NormalApplicationScoped.java:作用域是ApplicationScoped的bean,其构造方法中打印日志,带有本人的类名NormalSingleton.java:作用域是Singleton的bean,其构造方法中打印日志,带有本人的类名ChangeLazyLogicTest.java:这是个单元测试类,外面注入了NormalApplicationScoped和NormalSingleton的bean,在其ping办法中顺次调用下面两个bean的办法以上就是稍后要写的代码,咱们依据刚刚提到的懒加载规定预测一下要输入的内容和程序:首先,在ChangeLazyLogicTest的注入点,NormalSingleton会实例化,NormalApplicationScoped的代理类会实例化而后,在ChangeLazyLogicTest#ping办法中,因为调用了NormalApplicationScoped的办法,会导致NormalApplicationScoped的实例化接下来开始写代码,第一个bean,NormalApplicationScoped.javapackage com.bolingcavalry;import com.bolingcavalry.service.impl.NormalApplicationScoped;import com.bolingcavalry.service.impl.NormalSingleton;import io.quarkus.logging.Log;import io.quarkus.test.junit.QuarkusTest;import org.junit.jupiter.api.Test;import javax.inject.Inject;@QuarkusTestclass ChangeLazyLogicTest { @Inject NormalSingleton normalSingleton; @Inject NormalApplicationScoped normalApplicationScoped; @Test void ping() { Log.info("start invoke normalSingleton.ping"); normalSingleton.ping(); Log.info("start invoke normalApplicationScoped.ping"); normalApplicationScoped.ping(); }}第二个bean,NormalSingleton.javapackage com.bolingcavalry.service.impl;import io.quarkus.logging.Log;import javax.inject.Singleton;@Singletonpublic class NormalSingleton { public NormalSingleton() { Log.info("Construction from " + this.getClass().getSimpleName()); } public String ping() { return "ping from NormalSingleton"; }}而后是单元测试类ChangeLazyLogicTest,可见NormalApplicationScoped构造方法的日志应该在start invoke normalApplicationScoped.ping这一段之后package com.bolingcavalry;import com.bolingcavalry.service.impl.NormalApplicationScoped;import com.bolingcavalry.service.impl.NormalSingleton;import io.quarkus.logging.Log;import io.quarkus.test.junit.QuarkusTest;import org.junit.jupiter.api.Test;import javax.inject.Inject;@QuarkusTestclass ChangeLazyLogicTest { @Inject NormalSingleton normalSingleton; @Inject NormalApplicationScoped normalApplicationScoped; @Test void ping() { Log.info("start invoke normalSingleton.ping"); normalSingleton.ping(); Log.info("start invoke normalApplicationScoped.ping"); normalApplicationScoped.ping(); }}编码实现,运行单元测试类,验证咱们之前的预测,控制台输入后果如下图所示,合乎预期 ...

September 24, 2023 · 1 min · jiezi

关于后端:JDK21更新内容匿名模式和内容

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 文章更新打算 | 443: | Unnamed Patterns and Variables (Preview) |1. 什么是Unnamed Patterns and Variables (Preview)?Unnamed Patterns and Variables 是 Java 编程语言的一个新个性,它在 JDK 14 中引入,并在 JDK 15中作为预览性能持续存在。该个性容许咱们应用匿名模式和变量来简化代码并进步可读性。 2. 为什么须要Unnamed Patterns and Variables?在传统的 Java 代码中,当咱们须要对某个对象进行模式匹配时,通常须要创立一个长期变量来存储匹配后果。这样会导致代码简短、可读性差,并且减少了不必要的命名累赘。 而 Unnamed Patterns and Variables 的呈现正是为了解决这个问题。通过应用匿名模式和变量,咱们能够间接在模式匹配表达式中应用,防止了创立长期变量的麻烦,使得代码更加简洁和易于了解。 3. Unnamed Patterns and Variables 的实现原理Unnamed Patterns and Variables 的实现原理次要波及两个方面:匿名模式和匿名变量。 匿名模式匿名模式是一种非凡的模式,用于示意咱们只关怀某个值是否满足某个条件,而不关怀具体的值是什么。在匿名模式中,咱们应用下划线 _来代替具体的变量名。 例如,咱们能够应用匿名模式来判断一个对象是否为 null: if (obj instanceof String _) { System.out.println("obj is a non-null string");}匿名变量匿名变量是一种非凡的变量,用于示意咱们不须要应用该变量的值。在匿名变量中,咱们同样应用下划线 _ 来代替具体的变量名。 例如,在 switch 语句中,咱们能够应用匿名变量来疏忽某些分支的返回值: ...

September 24, 2023 · 1 min · jiezi

关于后端:JDK21更新内容ForeignFunctionAndMemoryApi

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 文章更新打算 | 442: | Foreign Function & Memory API (Third Preview) |1. 什么是Foreign Function & Memory API (Third Preview)?Foreign Function & Memory API 是 Java 平台的一个性能,它容许开发者间接与本地代码进行交互,并且能够在 Java 中操作本地内存。这个性能最后在JDK 14 的时候以 JEP 383 的模式引入了第一次预览版,而后在 JDK 15 中进一步改良并公布了第二次预览版(JEP 393),当初在 JDK 21中公布了第三次预览版(JEP 442)。 2. 为什么须要Foreign Function & Memory API?Foreign Function & Memory API 的呈现次要是为了解决以下几个问题: 与本地代码的无缝集成:有些场景下,咱们可能须要调用本地库或者零碎级别的函数,例如应用硬件加速、调用底层操作系统的特定性能等。而Foreign Function & Memory API 能够使得 Java 程序可能间接调用本地函数,从而实现与本地代码的无缝集成。进步性能:通过间接操作本地内存,能够防止数据拷贝和类型转换带来的性能损耗,从而进步程序的执行效率。扩大现有 Java 库的性能:Foreign Function & Memory API 提供了一种机制,能够将本地库中的函数包装成 Java 接口,从而不便地扩大现有的Java 库的性能。3. Foreign Function & Memory API 的实现原理Foreign Function & Memory API 的实现次要依赖于以下几个关键技术: ...

September 24, 2023 · 2 min · jiezi

关于后端:JDK21更新内容增强模式匹配

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 文章更新打算 | 441: | Pattern Matching for switch |1. 什么是 Pattern Matching for switch?Pattern Matching for switch 是 Java 14 中引入的一个新个性,它容许在 switch 语句中应用模式匹配。通过这个个性,咱们能够更不便地对变量进行类型判断和提取。 2. 为什么须要 Pattern Matching for switch?在之前的 Java 版本中,如果咱们想要依据不同的类型执行不同的逻辑,通常须要应用多个 if-else 或者 switch-case来进行判断。这样的代码构造比拟简短,并且容易出错。而 Pattern Matching for switch 的引入,使得咱们可能更简洁、清晰地解决这种状况。 3. Pattern Matching for switch 的实现原理Pattern Matching for switch 的实现原理次要波及两个方面:模式匹配和类型推断。 模式匹配模式匹配是指将某个值与一系列模式进行比拟,以确定是否匹配。在 Pattern Matching for switch 中,咱们能够应用关键字 case后跟上模式来进行匹配。例如: int result = switch (obj) { case String s -> s.length(); case Integer i -> i * 2; default -> -1;};在上述代码中,case String s 和 case Integer i 就是模式,它们别离用于匹配字符串和整数类型的对象。 ...

September 24, 2023 · 1 min · jiezi

关于后端:JDK21更新内容RedordPatterns

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 文章更新打算 1. 什么是Record Patterns?Record Patterns 是 Java 16 中引入的一个新个性,它容许咱们在模式匹配中应用记录类型(record types)。记录类型是一种新的类申明模式,用于定义不可变的数据对象。而 Record Patterns 则提供了一种简洁的形式来进行模式匹配,并且能够不便地从记录类型中提取字段值。 2. 为什么须要Record Patterns?在传统的 Java 编程中,当咱们须要对某个对象的属性进行判断和提取时,通常须要手动编写大量的代码来实现这些操作。而引入 Record Patterns 能够极大地简化这个过程,使得代码更加清晰、简洁,并且缩小了出错的可能性。 3. Record Patterns 的实现原理Record Patterns 的实现原理次要波及两个方面:记录类型和模式匹配。 记录类型记录类型是一种新的类申明模式,通过 record 关键字来定义。它主动提供了以下性能: 主动生成公有 final 字段,并依据结构函数参数初始化这些字段。主动生成 equals()、hashCode() 和 toString() 办法。提供了一种紧凑的语法来定义字段和构造函数。模式匹配模式匹配是指依据给定的模式来匹配某个对象,并执行相应的操作。在 Record Patterns 中,咱们能够应用 instanceof关键字和模式变量来进行模式匹配。 具体地说,当咱们应用 Record Patterns进行模式匹配时,编译器会主动为记录类型生成一个模式匹配办法。这个办法承受一个对象作为参数,并依据给定的模式进行匹配。如果匹配胜利,则将字段值绑定到相应的模式变量中,从而能够在后续代码中应用。 4. Record Patterns 的长处Record Patterns 带来了以下几个长处: 简洁性:应用 Record Patterns 能够大大简化对记录类型的模式匹配操作,缩小冗余代码。可读性:Record Patterns 提供了一种直观、清晰的语法,使得代码更易于了解和保护。安全性:因为 Record Patterns 主动生成了 equals() 和 hashCode() 办法,能够防止手动实现这些办法时可能呈现的谬误。进步开发效率:Record Patterns 能够缩小重复劳动,进步开发效率。5. Record Patterns 的毛病只管 Record Patterns 带来了很多益处,但也存在一些限度和毛病: ...

September 24, 2023 · 1 min · jiezi

关于后端:JDK21更新内容SequenceCollection

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 文章更新打算 | 431: | Sequenced Collections |Sequenced Collections1. 什么是Sequenced Collections?Sequenced Collections是Java中的一个新个性,它是通过JEP 431引入的。SequencedCollections是一种新的汇合类型,它提供了一种有序的、线程平安的汇合实现。它的指标是提供一种高效的、可扩大的有序汇合,以满足在多线程环境下解决大量数据的需要。 2. 为什么须要Sequenced Collections?在并发编程中,解决大量数据时,有序汇合是十分常见的需要。然而,Java规范库中的汇合类(如ArrayList、LinkedList等)并不是线程平安的,因而在多线程环境下应用它们可能会导致数据不统一的问题。为了解决这个问题,开发人员通常须要应用同步机制(如synchronized关键字或Lock对象)来保障汇合的线程安全性,但这会带来额定的开销和复杂性。 Sequenced Collections的指标就是提供一种高效的、可扩大的有序汇合,以解决在多线程环境下解决大量数据时的线程平安问题。 3. Sequenced Collections的实现原理Sequenced Collections的实现基于一种称为"Sequenced Locks"的机制。SequencedLocks是一种非凡的锁机制,它容许多个线程同时读取汇合中的数据,但只容许一个线程进行写操作。这种机制能够进步并发性能,同时保证数据的一致性。 在SequencedCollections中,每个元素都有一个惟一的序列号,用于标识元素的程序。读操作能够并发进行,而写操作则须要获取锁来保障原子性。当一个线程进行写操作时,其余线程能够持续读取汇合中的数据,但不能进行写操作,直到写操作实现。 4. Sequenced Collections的长处线程平安:Sequenced Collections提供了线程平安的汇合实现,能够在多线程环境下平安地拜访和批改汇合中的数据。高效性能:Sequenced Collections应用了Sequenced Locks机制,能够进步并发性能,同时保证数据的一致性。可扩展性:Sequenced Collections的设计思考了可扩展性,能够解决大量数据的并发拜访。5. Sequenced Collections的毛病额定开销:Sequenced Collections的实现须要保护元素的序列号和锁机制,这会带来肯定的额定开销。写操作的提早:因为写操作须要获取锁来保障原子性,可能会导致其余线程在写操作实现之前无奈进行写操作。6. Sequenced Collections的应用示例上面是一个应用Sequenced Collections的简略示例: import java.util.concurrent.SequencedHashMap;public class SequencedCollectionsExample { public static void main(String[] args) { SequencedHashMap<Integer, String> map = new SequencedHashMap<>(); // 增加元素 map.put(1, "Apple"); map.put(2, "Banana"); map.put(3, "Orange"); // 获取元素 String fruit = map.get(2); System.out.println(fruit); // 输入: Banana // 遍历元素 map.forEach((key, value) -> System.out.println(key + ": " + value)); // 输入: // 1: Apple // 2: Banana // 3: Orange }}在下面的示例中,咱们应用了SequencedHashMap来创立一个有序的、线程平安的汇合。咱们能够应用put办法增加元素,应用get办法获取元素,应用forEach办法遍历元素。 ...

September 24, 2023 · 1 min · jiezi

关于后端:JDK21更新内容字符串模板

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 文章更新打算 | 430: | String Templates (Preview) |1. 什么是String Templates?String Templates是Java 15中引入的一个新个性,它容许咱们在字符串中应用占位符来动静替换变量的值。它提供了一种更简洁、更直观的形式来构建字符串,而不须要应用传统的字符串拼接或格式化办法。 2. 为什么须要String Templates?在传统的Java中,咱们通常应用字符串拼接或格式化办法来构建动静字符串。这种形式须要手动解决变量的值,并且容易出错。而且,当字符串中蕴含大量变量时,代码会变得简短且难以保护。 String Templates的引入解决了这个问题,它提供了一种更简洁、更易读的形式来构建动静字符串。通过应用占位符,咱们能够将变量的值间接嵌入到字符串中,而不须要手动解决。 3. String Templates的实现原理?String Templates的实现原理是通过在字符串中应用占位符${}来示意变量。在运行时,Java编译器会将这些占位符替换为理论的变量值。 具体来说,当咱们应用String Templates时,编译器会将字符串中的占位符${}解析为一个非凡的表达式,并将其转换为对应的变量值。这个过程是在编译时实现的,所以在运行时不会有额定的性能开销。 4. String Templates的长处简洁易读:应用占位符${}来示意变量,使得代码更加简洁、易读。类型平安:String Templates在编译时会进行类型查看,确保变量的类型与占位符的类型匹配,防止了运行时的类型谬误。性能优化:String Templates的解析过程是在编译时实现的,所以在运行时不会有额定的性能开销。可扩展性:String Templates反对自定义的格式化函数,能够依据需要进行扩大。5. String Templates的毛病兼容性:String Templates是Java 15中引入的新个性,须要应用Java 15或更高版本的JDK能力应用。语法限度:String Templates的占位符${}只能用于示意变量,不能用于执行任意的表达式。可读性:当字符串中蕴含大量的占位符时,可能会升高代码的可读性。6. String Templates的应用示例上面是一个应用String Templates的简略示例: String name = "Alice";int age = 25;String message = "My name is ${name} and I'm ${age} years old.";System.out.println(message);输入后果为: My name is Alice and I'm 25 years old.7. String Templates的应用注意事项占位符${}中的变量名必须是无效的Java标识符。占位符${}中的变量值能够是任意类型,编译器会主动进行类型转换。如果变量值为null,占位符${}会被替换为字符串"null"。String Templates反对嵌套应用,能够在占位符${}中应用其余占位符。特地容易卡住。。而后就喊我。。 ...

September 24, 2023 · 1 min · jiezi

关于后端:面试题精讲SpringTemplate使用

uuid: 4eff9000-5a7c-11ee-94b3-d3a2e5c31360title: tags: [SpringTemplate, 数据库操作, JDBC, JdbcTemplate, 开发效率, 事务管理, 学习老本, 灵活性, 配置数据源, 查问数据, 注意事项, 总结]categories: [] date: 2023-09-24 09:47:24有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 系列文章地址 1. 什么是SpringTemplate?SpringTemplate是Spring框架提供的一个用于简化数据库操作的工具类。它封装了JDBC的底层细节,提供了一种更加不便和易用的形式来执行SQL语句,并处理结果集。 2. 为什么须要SpringTemplate?在传统的JDBC开发中,咱们须要手动编写大量的反复代码来实现数据库的连贯、敞开、事务管理等操作。而且,应用原生的JDBC API进行数据库操作也比拟繁琐,容易出错。SpringTemplate的呈现就是为了解决这些问题,它能够帮忙咱们简化数据库操作的流程,进步开发效率。 3. SpringTemplate的实现原理?SpringTemplate基于JdbcTemplate实现,它通过封装JdbcTemplate的API,提供了更加简洁的办法来执行SQL语句。SpringTemplate外部应用了回调函数机制,将数据库操作的细节交给用户自定义的回调函数来解决,从而达到解耦的目标。 4. SpringTemplate的长处简化数据库操作:SpringTemplate封装了JDBC的底层细节,提供了一种更加简略和易用的形式来执行SQL语句。进步开发效率:应用SpringTemplate能够缩小编写反复代码的工作量,同时还可能升高出错的概率。反对事务管理:SpringTemplate提供了对事务的反对,能够不便地进行事务管制。5. SpringTemplate的毛病学习老本较高:应用SpringTemplate须要相熟Spring框架的相干常识,对于初学者来说可能须要肯定的学习老本。灵活性绝对较低:因为SpringTemplate是基于JdbcTemplate实现的,因而在某些非凡场景下可能无奈满足需要,须要本人编写原生的JDBC代码。6. SpringTemplate的应用示例首先,在Spring配置文件中配置数据源和SpringTemplate: <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test"/> <property name="username" value="root"/> <property name="password" value="123456"/></bean><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/></bean>而后,在Java代码中应用SpringTemplate执行SQL语句: @Autowiredprivate JdbcTemplate jdbcTemplate;public void queryData() { String sql = "SELECT * FROM user"; List<Map<String, Object>> result = jdbcTemplate.queryForList(sql); for (Map<String, Object> row : result) { System.out.println(row.get("name")); }}上述代码中,咱们通过注入JdbcTemplate对象来应用SpringTemplate执行SQL查问操作。queryForList()办法能够执行查问语句,并将后果封装为一个List<Map<String, Object>>,每个Map示意一行数据。 7. SpringTemplate的应用注意事项在应用SpringTemplate之前,须要先配置好数据源和SpringTemplate对象。应用SpringTemplate执行数据库操作时,应该遵循良好的编程习惯,比方正当地解决异样、敞开资源等。如果须要进行事务管理,能够通过在办法上增加@Transactional注解来实现。8. 总结SpringTemplate是Spring框架提供的一个简化数据库操作的工具类,它封装了JDBC的底层细节,提供了一种更加不便和易用的形式来执行SQL语句。应用SpringTemplate能够缩小反复代码的编写,进步开发效率。同时,它还反对事务管理,可能帮忙咱们更好地管制事务。然而,应用SpringTemplate也有一些毛病,比方学习老本较高,灵活性绝对较低。因而,在抉择是否应用SpringTemplate时,须要依据具体的我的项目需要来决定。 ...

September 24, 2023 · 1 min · jiezi

关于后端:面试题精讲Springboot应用异常处理

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 系列文章地址 1. 什么是Spring Boot利用异样解决?Spring Boot利用异样解决是指在Spring Boot利用中对异样进行捕捉和解决的机制。当利用产生异样时,能够通过异样解决机制来捕捉异样并进行相应的解决,例如返回敌对的错误信息给用户,记录异样日志等。 2. 为什么须要Spring Boot利用异样解决?异样是在利用运行过程中不可避免的状况,可能是因为程序谬误、内部依赖故障或者其余不可预知的起因导致。如果不进行异样解决,利用可能会间接解体或者给用户展现不敌对的错误信息,影响用户体验和利用的稳定性。 通过Spring Boot利用异样解决,能够对异样进行对立的解决,提供更好的用户体验和利用的稳定性。同时,异样解决还能够帮忙开发人员疾速定位和解决问题,进步开发效率。 3. Spring Boot利用异样解决的实现原理?Spring Boot利用异样解决的实现原理次要依赖于Spring框架提供的异样解决机制。在Spring Boot利用中,能够通过自定义异样处理器来捕捉和解决异样。 具体实现步骤如下: 创立一个自定义的异样类,继承自Exception或RuntimeException,用于示意利用中的特定异常情况。创立一个全局异样处理器,应用@ControllerAdvice注解标记,并在类中定义异样解决办法,应用@ExceptionHandler注解标记该办法能够解决的异样类型。在异样解决办法中,能够依据具体的异样类型进行相应的解决,例如返回敌对的错误信息给用户、记录异样日志等。在Spring Boot利用中,能够通过配置文件或者注解的形式将自定义的异样处理器注册到利用中。4. Spring Boot利用异样解决的长处对立异样解决:通过自定义异样处理器,能够对立解决利用中的异样,提供对立的错误信息给用户,进步用户体验。异样日志记录:能够在异样处理器中记录异样日志,不便开发人员定位和解决问题。可扩展性:能够依据具体的业务需要,自定义异样处理器,实现特定的异样解决逻辑。5. Spring Boot利用异样解决的毛病异样解决逻辑可能会减少代码复杂性,须要审慎设计和实现。如果异样处理不当,可能会导致利用呈现安全漏洞或者信息泄露的危险。6. Spring Boot利用异样解决的应用示例上面是一个简略的Spring Boot利用异样解决的示例: @ControllerAdvicepublic class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public ResponseEntity<String> handleException(Exception e) { // 解决异样逻辑 return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal Server Error"); } @ExceptionHandler(UserNotFoundException.class) public ResponseEntity<String> handleUserNotFoundException(UserNotFoundException e) { // 解决用户不存在异样逻辑 return ResponseEntity.status(HttpStatus.NOT_FOUND).body("User Not Found"); }}@RestControllerpublic class UserController { @Autowired private UserService userService; @GetMapping("/users/{id}") public ResponseEntity<User> getUser(@PathVariable Long id) { User user = userService.getUserById(id); if (user == null) { throw new UserNotFoundException(); } return ResponseEntity.ok(user); }}public class UserNotFoundException extends RuntimeException { // 自定义用户不存在异样类}在下面的示例中,GlobalExceptionHandler是全局异样处理器,通过@ExceptionHandler注解标记了两个异样解决办法,别离解决Exception和UserNotFoundException异样。在UserController中,当用户不存在时,抛出UserNotFoundException异样,全局异样处理器会捕捉该异样并进行解决。 ...

September 24, 2023 · 1 min · jiezi

关于后端:quarkus依赖注入之九bean读写锁

欢送拜访我的GitHub这里分类和汇总了欣宸的全副原创(含配套源码):https://github.com/zq2599/blog_demos本篇概览本篇是《quarkus依赖注入》的第九篇,指标是在轻松的氛围中学习一个小技能:bean锁quarkus的bean锁自身很简略:用两个注解润饰bean和办法即可,但波及到多线程同步问题,欣宸违心花更多篇幅与各位Java程序员一起畅谈多线程,聊个痛快,本篇由以下内容组成对于多线程同步问题代码复现多线程同步问题quarkus的bean读写锁对于读写锁java的并发包中有读写锁ReadWriteLock:在多线程场景中,如果某个对象处于扭转状态,能够用写锁加锁,这样所有做读操作对象的线程,在获取读锁时就会block住,直到写锁开释为了演示bean锁的成果,咱们先来看一个经典的多线程同步问题,如下图,余额100,充值10块,扣费5块,失常状况下最终余额应该是105,但如果充值和扣费是在两个线程同时进行,而且各算各的,再别离用本人的计算结果去笼罩余额,最终会导致计算不精确 代码复现多线程同步问题咱们用代码来复现上图中的问题,AccountBalanceService是个账号服务类,其成员变量accountBalance示意余额,另外有三个办法,性能别离是:get:返回余额,相当于查问余额服务deposit:充值,入参是充值金额,办法内将余额放入长期变量,而后期待100毫秒模仿耗时操作,再将长期变量与入参的和写入成员变量accountBalancededuct:扣费,入参是扣费金额,办法内将余额放入长期变量,而后期待100毫秒模仿耗时操作,再将长期变量与入参的差写入成员变量accountBalanceAccountBalanceService.java源码如下,deposit和deduct这两个办法各算各的,丝毫没有思考过后其余线程对accountBalance的影响package com.bolingcavalry.service.impl;import io.quarkus.logging.Log;import javax.enterprise.context.ApplicationScoped;@ApplicationScopedpublic class AccountBalanceService { // 账户余额,假如初始值为100 int accountBalance = 100; /** * 查问余额 * @return */ public int get() { // 模仿耗时的操作 try { Thread.sleep(80); } catch (InterruptedException e) { e.printStackTrace(); } return accountBalance; } /** * 模仿了一次充值操作, * 将账号余额读取到本地变量, * 通过一秒钟的计算后,将计算结果写入账号余额, * 这一秒内,如果账号余额产生了变动,就会被此办法的本地变量笼罩, * 因而,多线程的时候,如果其余线程批改了余额,那么这里就会笼罩掉,导致多线程同步问题, * AccountBalanceService类应用了Lock注解后,执行此办法时,其余线程执行AccountBalanceService的办法时就会block住,防止了多线程同步问题 * @param value * @throws InterruptedException */ public void deposit(int value) { // 先将accountBalance的值存入tempValue变量 int tempValue = accountBalance; Log.infov("start deposit, balance [{0}], deposit value [{1}]", tempValue, value); // 模仿耗时的操作 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } tempValue += value; // 用tempValue的值笼罩accountBalance, // 这个tempValue的值是基于100毫秒前的accountBalance计算出来的, // 如果这100毫秒期间其余线程批改了accountBalance,就会导致accountBalance不精确的问题 // 例如最后有100块,这里存了10块,所以余额变成了110, // 然而这期间如果另一线程取了5块,那余额应该是100-5+10=105,然而这里并没有聚拢100-5,而是很暴力的将110写入到accountBalance accountBalance = tempValue; Log.infov("end deposit, balance [{0}]", tempValue); } /** * 模仿了一次扣费操作, * 将账号余额读取到本地变量, * 通过一秒钟的计算后,将计算结果写入账号余额, * 这一秒内,如果账号余额产生了变动,就会被此办法的本地变量笼罩, * 因而,多线程的时候,如果其余线程批改了余额,那么这里就会笼罩掉,导致多线程同步问题, * AccountBalanceService类应用了Lock注解后,执行此办法时,其余线程执行AccountBalanceService的办法时就会block住,防止了多线程同步问题 * @param value * @throws InterruptedException */ public void deduct(int value) { // 先将accountBalance的值存入tempValue变量 int tempValue = accountBalance; Log.infov("start deduct, balance [{0}], deposit value [{1}]", tempValue, value); // 模仿耗时的操作 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } tempValue -= value; // 用tempValue的值笼罩accountBalance, // 这个tempValue的值是基于100毫秒前的accountBalance计算出来的, // 如果这100毫秒期间其余线程批改了accountBalance,就会导致accountBalance不精确的问题 // 例如最后有100块,这里存了10块,所以余额变成了110, // 然而这期间如果另一线程取了5块,那余额应该是100-5+10=105,然而这里并没有聚拢100-5,而是很暴力的将110写入到accountBalance accountBalance = tempValue; Log.infov("end deduct, balance [{0}]", tempValue); }}接下来是单元测试类LockTest.java,有几处须要留神的中央稍后会阐明package com.bolingcavalry;import com.bolingcavalry.service.impl.AccountBalanceService;import io.quarkus.logging.Log;import io.quarkus.test.junit.QuarkusTest;import org.junit.jupiter.api.Assertions;import org.junit.jupiter.api.Test;import javax.inject.Inject;import java.util.concurrent.CountDownLatch;@QuarkusTestpublic class LockTest { @Inject AccountBalanceService account; @Test public void test() throws InterruptedException { CountDownLatch latch = new CountDownLatch(3); int initValue = account.get(); final int COUNT = 10; // 这是个只负责读取的线程,循环读10次,每读一次就期待50毫秒 new Thread(() -> { for (int i=0;i<COUNT;i++) { // 读取账号余额 Log.infov("current balance {0}", account.get()); } latch.countDown(); }).start(); // 这是个充值的线程,循环充10次,每次存2元 new Thread(() -> { for (int i=0;i<COUNT;i++) { account.deposit(2); } latch.countDown(); }).start(); // 这是个扣费的线程,循环扣10次,每取1元 new Thread(() -> { for (int i=0;i<COUNT;i++) { account.deduct(1); } latch.countDown(); }).start(); latch.await(); int finalValue = account.get(); Log.infov("finally, current balance {0}", finalValue); Assertions.assertEquals(initValue + COUNT, finalValue); }}上述代码中,有以下几点须要留神在主线程中新增了三个子线程,别离执行查问、充值、扣费的操作,可见deposit和deduct办法是并行执行的初始余额100,充值一共20元,扣费一共10元,因而最终正确后果应该是110元为了确保三个子线程全副执行结束后主线程才退出,这里用了CountDownLatch,在执行latch.await()的时候主线程就开始期待了,等到三个子线程把各自的latch.await()都执行后,主线程才会继续执行最终会查看余额是否等于110,如果不是则单元测试不通过执行单元测试,后果如下图,果然失败了 ...

September 23, 2023 · 2 min · jiezi

关于后端:LeetCode-mysql-刷题四餐馆营业额变化增长用自连和窗口函数-4-种-sql-实现过去-7-天的营业额

题目题目链接:餐馆营业额变动增长 你是餐馆的老板,当初你想剖析一下可能的营业额变动增长(每天至多有一位顾客)。 计算以 7 天(某日期 + 该日期前的 6 天)为一个时间段的顾客生产平均值。average_amount 要 保留两位小数。 后果按 visited_on 升序排序。 返回后果格局的例子如下。 Create table If Not Exists Customer (customer_id int, name varchar(20), visited_on date, amount int);Truncate table Customer;insert into Customer (customer_id, name, visited_on, amount) values ('1', 'Jhon', '2019-01-01', '100');insert into Customer (customer_id, name, visited_on, amount) values ('2', 'Daniel', '2019-01-02', '110');insert into Customer (customer_id, name, visited_on, amount) values ('3', 'Jade', '2019-01-03', '120');insert into Customer (customer_id, name, visited_on, amount) values ('4', 'Khaled', '2019-01-04', '130');insert into Customer (customer_id, name, visited_on, amount) values ('5', 'Winston', '2019-01-05', '110');insert into Customer (customer_id, name, visited_on, amount) values ('6', 'Elvis', '2019-01-06', '140');insert into Customer (customer_id, name, visited_on, amount) values ('7', 'Anna', '2019-01-07', '150');insert into Customer (customer_id, name, visited_on, amount) values ('8', 'Maria', '2019-01-08', '80');insert into Customer (customer_id, name, visited_on, amount) values ('9', 'Jaze', '2019-01-09', '110');insert into Customer (customer_id, name, visited_on, amount) values ('1', 'Jhon', '2019-01-10', '130');insert into Customer (customer_id, name, visited_on, amount) values ('3', 'Jade', '2019-01-10', '150');-- 工夫不间断的例子insert into Customer (customer_id, name, visited_on, amount) values ('1', 'Jhon', '2019-01-01', '100');insert into Customer (customer_id, name, visited_on, amount) values ('4', 'Khaled', '2019-01-04', '130');insert into Customer (customer_id, name, visited_on, amount) values ('5', 'Winston', '2019-01-05', '110');insert into Customer (customer_id, name, visited_on, amount) values ('6', 'Elvis', '2019-01-06', '140');insert into Customer (customer_id, name, visited_on, amount) values ('7', 'Anna', '2019-01-07', '150');insert into Customer (customer_id, name, visited_on, amount) values ('8', 'Maria', '2019-01-08', '80');insert into Customer (customer_id, name, visited_on, amount) values ('9', 'Jaze', '2019-01-09', '110');insert into Customer (customer_id, name, visited_on, amount) values ('1', 'Jhon', '2019-01-10', '130');insert into Customer (customer_id, name, visited_on, amount) values ('3', 'Jade', '2019-01-10', '150');Customer 表:+-------------+--------------+--------------+-------------+| customer_id | name | visited_on | amount |+-------------+--------------+--------------+-------------+| 1 | Jhon | 2019-01-01 | 100 || 2 | Daniel | 2019-01-02 | 110 || 3 | Jade | 2019-01-03 | 120 || 4 | Khaled | 2019-01-04 | 130 || 5 | Winston | 2019-01-05 | 110 || 6 | Elvis | 2019-01-06 | 140 || 7 | Anna | 2019-01-07 | 150 || 8 | Maria | 2019-01-08 | 80 || 9 | Jaze | 2019-01-09 | 110 || 1 | Jhon | 2019-01-10 | 130 || 3 | Jade | 2019-01-10 | 150 |+-------------+--------------+--------------+-------------+在 SQL 中,(customer_id, visited_on) 是该表的主键。该表蕴含一家餐馆的顾客交易数据。visited_on 示意 (customer_id) 的顾客在 visited_on 那天拜访了餐馆。amount 是一个顾客某一天的生产总额。输入:+--------------+--------------+----------------+| visited_on | amount | average_amount |+--------------+--------------+----------------+| 2019-01-07 | 860 | 122.86 || 2019-01-08 | 840 | 120 || 2019-01-09 | 840 | 120 || 2019-01-10 | 1000 | 142.86 |+--------------+--------------+----------------+解释:第一个七天生产平均值从 2019-01-01 到 2019-01-07 是restaurant-growth/restaurant-growth/ (100 + 110 + 120 + 130 + 110 + 140 + 150)/7 = 122.86第二个七天生产平均值从 2019-01-02 到 2019-01-08 是 (110 + 120 + 130 + 110 + 140 + 150 + 80)/7 = 120第三个七天生产平均值从 2019-01-03 到 2019-01-09 是 (120 + 130 + 110 + 140 + 150 + 80 + 110)/7 = 120第四个七天生产平均值从 2019-01-04 到 2019-01-10 是 (130 + 110 + 140 + 150 + 80 + 110 + 130 + 150)/7 = 142.86本题考查的常识是如何累加一段时间区间内的值 ...

September 23, 2023 · 5 min · jiezi

关于后端:从钱塘江边到余杭塘河

把两个月前 钱江边的团聚小酌 胜利移到余杭塘河。三巡五味后,一行三人在偌大的校园走着聊着。在滨江某出名领取公司的测试经理,感叹管理层间人浮于事站队排位;在阿里的前端程序员,窘迫于往年未能升P竞争压力山大。而我,定位为服务端却在走全栈路线,也在纠结更换技术栈,看不清寻不到一个更称心充斥想象力的将来。 仿佛吐槽和患得患失,多过幸福和豪气干云。而回忆这所有刚开始时的局促不安踌躇满志,绝没想到,会在一个雨过方晴的深夜,有这样一番对话。 4年前的明天,我来到他乡,从济南坐上一节南下的橙皮车。当慢慢悠悠走过十余个小时,从微山湖夕阳落下到寒山寺晨钟响彻,我来到了曾一见倾心风云际会的魔都,一只怯怯什么也不会的菜鸟,正式开启了必将色彩斑斓的职业生涯。 此前几天,第一次用58找房,还不知有那么多套路。我发了100多条短信,大多如泥牛入海不见回声。偶有的几条,也是中介回答:“便宜的前几天租出去了,还有套价格贵一些的”。我终在豆瓣小组,在车来到济宁时收到了这条回复。满是欣慰关上,充斥悲观敞开。 此前几个月,我放弃割舍许多,未曾随我的相当少数同学,去那几家中字头央企,也未曾青眼相向,能够一辈子安稳无虞的公务员事业编,而抉择了一家未曾听闻的“互联网”公司。我晓得,当我听到这三个字,郁结于胸口怏怏不乐的大石顿被粉碎,我晓得,我的第一家公司,不会再有其余。然而回宿舍后我做的第一件事,是查证这家公司是否为欺骗组织皮包公司。我也在暗暗忧心,空有一腔酷爱,就真能做得好吗?趣味真的能够战胜科班忽视业余? 我在仙霞路工程技术大学的国家级创业园,度过了终生难忘的两年,也完满答复了下面的纳闷。又在两年前魔都落户安家周折太巨,抉择如留鸟,随潮离沪来杭。 四年里,我以均匀一年一家的频率,换过四家公司,薪资较最后翻转500%。四年前,翻新守业之风荡涤全国,o2o风波乍起,p2p方兴未艾。而今,内外部趋势交错,猪从风口跌落,独角沦为毒角。我也面临职业和薪资门卡:我是否还能心平静气在一家单位多呆几年,积淀而不颓丧?我如何还能放弃在基数较大的状况下,使薪资以较高速率增长?我有哪些要学哪些要放,我要走哪条职业路线?… 切实有太多要学,我给本人的指标是:除去工作所用,还要试图从数学和物理角度,了解背地机理;要紧跟潮流,对新呈现的技术和事物保有热切好奇;要外语足够优良,能无障碍浏览英语文档。… 从没想过,有一天“学习”也会成为苦涩累赘。但我分明,并不是所有的职业,所有的从业者,都有咱们这样能够一直学习一直进步,如果违心能够练就一身本事的机会。我会在无际学海中偶然迷失,但却分明,一样技能能够一陈不变从生到死,那会让我因无成就感和进步的满足而生不如死。 我的感触是,从毕业到30岁,真的太短太短了。只有披星戴月只有目不见睫。几年里,太多的熬夜让我皮肤不复当年紧致滑腻,太多的久坐让我发福增重,或者还有双眼疲劳颈椎酸痛。…我会留神珍重,但当解决一个问题,当当搞懂一样货色,那种感觉,像一个木匠做出一件工艺品,抖落浑身木屑站起时的满足。所有的困乏,所有的周折操劳,都将云消雾散。 回瞰这几年,我总会在他们看不见的中央,感激B哥L哥H哥,但我还想感激并告诫本人:我很怯懦,也因此侥幸,在一个几百年不遇的信息时代,如果我还旧调重弹患得患失,畏葸不前混吃等死,那既是对本人得辜负,也是对时代得辜负。 本文由mdnice多平台公布

September 23, 2023 · 1 min · jiezi

关于后端:听GPT-讲Istio源代码pkg8

File: istio/pkg/config/analysis/analyzers/deprecation/deprecation.go文件 deprecation.go 存在于 Istio 我的项目中的 "istio/pkg/config/analysis/analyzers/deprecation" 门路中。这个文件的作用是实现对于过期的配置资源进行剖析,以便于 Istio 我的项目向前兼容。 首先,文件中定义的 "deprecatedCRDs" 一组变量是为了存储所有已废除的自定义资源定义 (CRD)。每个变量代表一个已废除的 CRD。 接着,文件中定义了一系列 FieldAnalyzer 构造体。这些构造体别离对应不同类型的 CRD 字段(例如 Metadata、Annotations、Labels等),并提供了剖析这些字段的办法,以确定是否存在过期的用法。 文件中的 Metadata 函数是一个辅助函数,用于返回 CRD 对象的元数据。 接下来是 Analyze 函数,该函数接管一个 CRD 的 Kubernetes 元数据作为参数,并利用 FieldAnalyzers 对该 CRD 进行剖析。该函数遍历每个 FieldAnalyzer 并将 CRD 的相干字段传递给它们进行进一步剖析。剖析的后果将被收集并返回。 analyzeCRD 函数是 Analyze 函数的理论执行函数,它调用 Analyze 函数来剖析给定的 CRD 对象。 analyzeSidecar 函数是 Analyze 函数的一部分,用于剖析 Sidecar 配置中的特定字段。它应用正文、标签和字段值进行剖析。 analyzeVirtualService 函数也是 Analyze 函数的一部分,用于剖析 VirtualService 配置中的特定字段。它应用正文、标签和字段值进行剖析。 replacedMessage 函数是一个辅助函数,用于生成提示信息,批示给定字段已被替换。 ignoredMessage 函数是一个辅助函数,用于生成提示信息,批示给定字段已被疏忽。 crRemovedMessage 函数是一个辅助函数,用于生成提示信息,批示给定 CRD 已被删除。 ...

September 23, 2023 · 2 min · jiezi

关于后端:听GPT-讲Istio源代码pkg7

File: istio/pkg/test/csrctrl/controllers/csr_controller.go在Istio我的项目中,csr_controller.go文件的作用是实现了Certificate Signing Request (CSR) 控制器,负责解决和管制 CSR 的主动签名和证书治理。 首先,让咱们来理解一下文件中的Signer构造体及其相干的元素。 Signer构造体是一个接口,定义了用于签订证书申请的办法。它有两个实现构造体: CertManagerSigner:应用Cert-Manager签订证书申请的实现。KubernetesSigner:应用Kubernetes的CSR签订证书申请的实现。上面是每个函数的具体介绍: NewSigner函数:依据指定的配置创立一个新的CSR签订者实例(Signer)。它依据配置文件中的certManagerMode来抉择签订者的类型(CertManagerSigner或KubernetesSigner)。Reconcile函数:CSR的调谐函数,负责解决CSR的创立、更新和删除。它将读取CSR创立事件,依据事件类型执行相应的操作。Run函数:控制器的主运行循环。它应用了Kubernetes的cache.WaitForCacheSync办法来期待CSR资源和证书资源都被正确的缓存,而后调用Reconcile函数解决CSR的调谐。HasSynced函数:用于在控制器启动和筹备好处理事件之后,告知控制器曾经同步CSR和证书的缓存。isCertificateRequestApproved函数:用于判断给定的证书申请是否被批准。它会查看证书申请的条件中是否存在“Approved”状态,如果存在并且状态是True,则示意证书申请已批准。getCertApprovalCondition函数:用于获取给定证书申请的批准条件。它会查看证书申请的条件列表,找到“Approved”条件,并返回该条件的详细信息。通过以上介绍,心愿您对csr_controller.go文件的作用和其中的构造体和函数有了更具体的理解。 File: istio/pkg/test/kube/dump.go在Istio我的项目中,istio/pkg/test/kube/dump.go文件的次要作用是用于执行一些与Kubernetes集群相干的操作,如获取集群中的Pod信息、容器信息、日志信息等。此文件中的函数和构造体用于执行这些操作。 coreDumpedPods是一个存储曾经转储外围的Pod的名称的字符串切片。它次要用于跟踪曾经转储外围的Pod。 dumpClient是kubernetes.Interface类型的对象,用于与Kubernetes API进行交互,执行获取集群信息等操作。 wellKnownContainer是一个字符串变量,用于存储要转储外围的容器的名称。个别状况下,默认是"istio-proxy"。 PodDumper是实现了PodDumperInterface接口的构造体。它次要用于执行Pod的转储操作。 IsContainer是一个性能函数,用于判断一个容器是否合乎转储外围的条件。 Name是一个蕴含Pod名称和命名空间的构造体,用于标识一个Pod。 podOutputPath是一个存储Pod转储输入门路的字符串。 outputPath是一个存储转储输入门路的字符串。 DumpDeployments是一个布尔值,用于示意是否转储部署资源。 DumpWebhooks是一个布尔值,用于示意是否转储Webhook配置。 DumpPods是一个布尔值,用于示意是否转储Pod资源。 DumpCoreDumps是一个布尔值,用于示意是否转储外围转储。 podsOrFetch是一个函数,用于获取Pods信息。 DumpPodState是一个函数,用于转储Pod的状态。 DumpPodEvents是一个函数,用于转储Pod的事件。 containerRestarts是一个函数,用于统计容器重启的次数。 containerCrashed是一个函数,用于查看容器是否曾经解体。 DumpPodLogs是一个函数,用于转储Pod的日志。 DumpPodProxies是一个函数,用于转储Pod的代理。 newPortForward是一个函数,用于创立端口转发。 portForwardRequest是一个函数,用于执行端口转发申请。 dumpProxyCommand是一个函数,用于转储代理的命令。 isWarming是一个函数,用于查看是否正在进行预热。 hasEnvoy是一个函数,用于查看是否存在Envoy代理。 checkIfVM是一个函数,用于查看是否是虚拟机。 DumpDebug是一个函数,用于转储调试信息。 DumpNdsz是一个函数,用于转储ndsz信息。 这些函数和构造体的作用是为了实现对Kubernetes集群中各种资源的转储和操作,以便在测试中进行剖析和调试。 File: istio/pkg/test/failer.go在istio我的项目中,istio/pkg/test/failer.go文件是用于测试时模仿失败状况的辅助工具。它提供了一些工具函数和构造体,用于在测试代码中模仿谬误和失败的状况。 _这几个变量在Go语言中示意一个匿名变量,示意疏忽该变量的值。 上面是各个构造体的作用: Failer构造体是次要的工具,用于模仿失败状况和记录测试后果。Fuzzer构造体用于进行随机含糊测试,通过生成随机输出数据以测试代码的健壮性。errorWrapper构造体包装了一个error,并提供了一些辅助办法用于模仿谬误状况。上面是各个函数的作用: Wrap函数用于包装一个谬误,并将其返回。这个谬误将在测试过程中被Failer捕捉和记录。ToErrorCleanup函数用于将函数调用转换为Cleanup函数,以在测试完结时进行清理操作。Fail和FailNow函数用于标记以后的测试用例失败,并能够附加一些错误信息。Fatal和Fatalf函数用于标记以后的测试用例失败,并立刻终止以后测试。Helper函数是一个空函数,用于和testing包中的辅助函数配合应用。Skip函数用于跳过以后的测试用例。Cleanup函数用于指定测试完结时须要执行的清理操作。Log和Logf函数用于记录一些日志信息。TempDir函数用于创立一个长期目录,并返回其门路。总的来说,istio/pkg/test/failer.go文件提供了一套用于模仿失败状况和记录测试后果的工具函数和构造体,以便于编写更强壮、全面的测试用例。它能够帮忙测试人员更好地定位和调试问题,进步程序的品质和可靠性。 File: istio/pkg/util/grpc/codes.go在istio/pkg/util/grpc/codes.go文件中,定义了一些与gRPC状态码相干的常量和函数,用于解决和转换gRPC状态码。 该文件的次要作用是提供一种对立的形式来解决gRPC状态码,并且将其转换为Istio零碎所应用的状态码。 其中,SupportedGRPCStatus是一个定义了多个gRPC状态码的切片,包含了一些罕用的状态码,如OK(状态码0)、Canceled(状态码1)、Unknown(状态码2)等等。 这些状态码在gRPC中用于示意申请的解决状况,在不同的状况下会返回不同的状态码,例如失常解决实现、申请被勾销、呈现未知谬误等等。SupportedGRPCStatus能够作为一个全局变量,不便其余代码应用。 此外,该文件还定义了一些函数,用于实现不同状态码之间的互相转换。其中包含: GRPCStatusToHTTPCode:用于将gRPC状态码转换成对应的HTTP状态码。例如,将gRPC的状态码1(Canceled)转换成HTTP状态码499(Client Closed Request)。HTTPCodeToGRPCStatus:用于将HTTP状态码转换成对应的gRPC状态码。例如,将HTTP状态码404(Not Found)转换成gRPC状态码5(NotFound)。IsOK:判断给定的gRPC状态码是否为OK状态。即是否为状态码0。这些函数的目标是为了在Istio零碎中将gRPC状态码转换成与Istio零碎相匹配的状态码,以便于零碎内其余组件的解决。同时,它们也提供了一种不便的形式来进行gRPC状态码和HTTP状态码之间的转换,以满足不同层级或协定之间的需要。 File: istio/pkg/util/hash/hash.go在Istio我的项目中,istio/pkg/util/hash/hash.go文件的作用是提供哈希函数的实现。 _ 变量通常被用作一个匿名变量,示意疏忽该值或占位符。Hash 构造体是一个哈希函数的接口定义,它申明了 Write 和 Sum64 办法。具体实现该接口的构造体是 instance。instance 构造体实现了 Hash 接口,它蕴含了一个哈希对象和一个 bool 值(标记是否曾经被写入)。instance 构造体的作用是提供对哈希对象的封装,并提供了一些办法来进行哈希计算。以下是该文件中的几个重要办法的介绍: ...

September 23, 2023 · 3 min · jiezi

关于后端:听GPT-讲Istio源代码pkg6

File: istio/pkg/test/framework/components/namespace/kube.go在Istio我的项目中,istio/pkg/test/framework/components/namespace/kube.go文件的作用是定义了用于创立和治理Kubernetes命名空间的框架组件。 上面是对文件中次要的变量和构造体的介绍: idctr:用于生成惟一的命名空间ID的计数器。rnd:用于生成随机字符串的随机数生成器。mu:用于对共享资源进行互斥拜访的互斥锁。_:匿名变量,用于疏忽某些返回值。kubeNamespace构造体定义了一组办法来创立和治理Kubernetes命名空间。以下是其办法的作用: Dump:返回命名空间的字符串示意模式。Name:返回命名空间的名称。Prefix:返回前缀和随机后缀组成的命名空间名称。Labels:返回命名空间的标签。SetLabel:为命名空间设置标签。RemoveLabel:从命名空间中删除标签。ID:返回命名空间的惟一ID。Close:在测试实现后删除命名空间。claimKube:检索Kubernetes API客户端。setNamespaceLabel:为命名空间设置标签。removeNamespaceLabel:从命名空间中删除标签。newKube:创立一个新的Kubernetes客户端实例。createInCluster:在集群上创立命名空间。forEachCluster:对集群中的每个命名空间执行操作。addCleanup:将命名空间增加到清理列表中。IsAmbient:查看命名空间是否为环境命名空间。IsInjected:查看命名空间是否被注入了Istio代理。createNamespaceLabels:创立一个带有命名空间标签的标签汇合。这些函数提供了创立和治理Kubernetes命名空间的性能,不便在测试中应用。 File: istio/pkg/test/framework/components/authz/headers.go在Istio我的项目中,"istio/pkg/test/framework/components/authz/headers.go"文件的作用是为受权测试提供HTTP申请和响应的头部组件。 在受权测试中,"headers.go"文件定义了一些常见的HTTP申请和响应头部,以便进行受权策略的测试。这些头部包含: "Authorization"头部:该头部用于在申请中提供受权信息,比方Bearer令牌或根本身份验证凭据。"X-Forwarded-For"头部:该头部用于在申请中模仿客户端IP地址,以测试基于IP地址的访问控制。"Referer"头部:该头部用于模仿申请中的起源页面,以测试基于推荐者的访问控制。"User-Agent"头部:该头部用于在申请中指定用户代理信息,以测试基于用户代理的访问控制。这些头部组件能够在受权测试中应用,以验证Istio的受权性能是否按预期工作。通过应用这些头部,测试能够模仿各种不同的HTTP申请和响应场景,验证受权策略的正确性和一致性。 总而言之,"headers.go"文件在Istio我的项目中扮演着受权测试中HTTP申请和响应头部的定义和创立角色,为测试人员提供了一些不便的工具和组件,用于验证Istio的受权性能。 File: istio/pkg/test/framework/components/authz/provider.go在Istio我的项目中,istio/pkg/test/framework/components/authz/provider.go文件的作用是为测试框架提供受权相干的组件。它定义了一些构造体和函数,用于进行受权的验证和查看。 以下是每个构造体的作用: _:这些变量通常是示意无用的返回值,以疏忽相干后果。API 构造体:用于示意受权服务的接口。Provider 构造体:示意受权服务提供者。providerImpl 构造体:用于实现受权服务。以下是每个函数的作用: Name():返回提供者的名称,用于标识受权服务。API():返回受权服务的API接口。IsProtocolSupported(protocol string):查看受权服务是否反对给定的协定。IsTargetSupported(target string):查看受权服务是否反对给定的指标。MatchSupportedTargets(authorizationPolicies []*networkingv1beta1.AuthorizationPolicy, service, namespace, source, target string):查看受权策略是否匹配给定的指标。Check(target, namespace, user, method, path string, code int, headers map[string]string):应用给定的参数查看是否通过受权。checkHTTP(method, path string, code int, headers map[string]string):查看通过HTTP协定的受权申请是否通过。checkGRPC(method, service, namespace, source, target string, code int):查看通过GRPC协定的受权申请是否通过。checkRequest(service, namespace, version, source, target, user string, expectedCode int):查看受权申请是否通过。headerContains(header http.Header, key, value string):查看HTTP申请头中是否蕴含给定的键值对。headerNotContains(header http.Header, key, value string):查看HTTP申请头中是否不蕴含给定的键值对。sortKeys(m map[string]string):对键进行排序,以便进行比拟和断言。这些函数一起提供了对受权服务的验证和查看,以确保受权机制按预期工作。 File: istio/pkg/test/framework/logging.go在Istio我的项目中,logging.go文件位于istio/pkg/test/framework目录中,负责实现Istio测试框架的日志记录性能。以下是对该文件中各局部性能的具体介绍: logOptionsFromCommandline变量:该变量用于存储从命令行解析的日志选项。它蕴含以下字段: ...

September 23, 2023 · 2 min · jiezi

关于后端:159302-人工智能算法

159.302 Artificial IntelligenceAssignment #2Fuzzy Controller for the Inverted Pendulum ProblemMaximum number of members per group: 3 studentsDeadline for submission: October 10 ## 1. InstructionsYour task is mainly to design and implement a fuzzy controller(Zero-order Sugeno Fuzzy Inference System) for balancing aninvertedpendulum system.  A written report detailing your system design andcharacterisation of its performance must accompany your program submission.A start-up program using second-order derivative physics equations and simple graphics library are provided, simulating the complete dynamics of the cart-pendulum system.  In addition, italso includes a function for collecting data points for plotting a control surface, and a fuzzy logic engine that you can utilise to implement a complete fuzzy controller.  A tutorial on how to use the engine is provided in the lecture slides (Lecture - Fuzzy Logic Engine.pptx – we discussed this in the lectures).   Details of the requirements: ...

September 23, 2023 · 4 min · jiezi

关于后端:代码整洁之道程序员的职业素养十三

合作在软件开发畛域,团队合作是获得高效成绩的要害。业余的开发团队通过相互协作和单干,实现我的项目指标。然而,集体的独立工作也有其价值,让开发人员能够专一于解决乏味的问题。 团队合作是软件开发中不可或缺的一部分。当团队成员可能高度业余地相互合作时,整个团队将变得高效。与此相反,单打独斗或与团队脱节都是不业余的体现。尽管人际关系可能会简单且难以解决,但编程则是整洁且可预感的。对于许多开发人员来说,可能单独待在房间里数个小时,沉迷在乏味的问题中,是一种最高兴的时光。 然而,只管咱们对本人的工作充满热情,但最好将注意力集中在咱们的老板所谋求的指标上。他们关注的是与业务的协同倒退。一个不失常的团队最蹩脚的体现是,每个程序员都在本人的代码四周筑起一道高墙,回绝让其他人接触到这些代码。 业余的开发人员不会阻止他人批改代码。他们不会在代码上建设所有权的壁垒,而是尽可能多地互相合作。通过单干,他们实现了学习的目标。然而,最好还是要进行沟通,代码的所有者更分明其中的潜在问题。 专业人士抉择结对编程的起因是,结对编程是最好的代码复查形式。零碎中不应该蕴含未经其余开发人员复查过的代码。只管代码复查的办法有很多,但大多数办法效率都很低下。而以相互合作的形式实现代码编写,是最高效且最有成果的代码复查办法。 当然,有时候独立工作是正确的抉择。当咱们须要长时间思考一个问题时,单独工作是适合的。当工作琐碎且举足轻重,与另一个人一起工作可能会浪费时间。然而,总的来说,与其他人严密合作,进行结对编程,是最佳实际。 通过团队合作,开发人员可能独特攻克挑战并获得更好的后果。单干不仅进步了代码品质,还可能促成常识共享和技能晋升。同时,集体独立工作也有其价值,容许开发人员专一于解决简单问题。在软件开发中,均衡团队合作和集体工作是取得成功的要害。 总结起来,团队合作和集体工作在程序开发中都是重要的。通过单干和相互合作,开发人员可能获得更好的成绩。然而,在某些状况下,集体独立工作也是必要的。重要的是要找到平衡点,以确保团队的高效运作和集体的倒退。

September 23, 2023 · 1 min · jiezi

关于后端:CS3214可定制的Shell

CS3214 Fall 2023 Project 1 - “Customizable Shell”Due Date: See website for due date (Late days may be used.)This project must be done in groups of 2 students. Self-selected groups must have regis-tered using the grouper app (URL). Otherwise, a partner will beassigned to you. 1 IntroductionThis assignment introduces you to the principles of processmanagement and job control in a Unix-like operating system. In thisproject, you will develop a simple job control shell.This is an open-endedassignment. In addition to implementing the required functional- ity, we encourage you to define the scope of this project yourself. ...

September 23, 2023 · 11 min · jiezi

关于后端:根据条件关闭软件

应用下载工具时,经常出现磁盘空间已满,无奈下载的状况。 应用shell写一个监控,每2分钟执行一次。判断以后磁盘的空间,低于2G时,敞开下载软件。 获取空间大小 ➜ ~ df -h Filesystem Size Used Avail Capacity iused ifree %iused Mounted on/dev/disk1s5s1 233Gi 14Gi 9.0Gi 62% 553757 2447547563 0% /devfs 196Ki 196Ki 0Bi 100% 678 0 100% /dev/dev/disk1s4 233Gi 1.0Gi 9.0Gi 10% 1 2448101319 0% /System/Volumes/VM/dev/disk1s2 233Gi 300Mi 9.0Gi 4% 1209 2448100111 0% /System/Volumes/Preboot/dev/disk1s6 233Gi 920Ki 9.0Gi 1% 17 2448101303 0% /System/Volumes/Update/dev/disk1s1 233Gi 208Gi 9.0Gi 96% 1517128 2446584192 0% /System/Volumes/Datamap auto_home 0Bi 0Bi 0Bi 100% 0 0 100% /System/Volumes/Data/home ...

September 22, 2023 · 1 min · jiezi

关于后端:探究Vcenter虚拟化方案中VirtualMachine庞大结构体中各字段的含义

SDK中mo.VirtualMachine构造体定义如下: type VirtualMachine struct { ManagedEntity Capability types.VirtualMachineCapability `mo:"capability"` Config *types.VirtualMachineConfigInfo `mo:"config"` Layout *types.VirtualMachineFileLayout `mo:"layout"` LayoutEx *types.VirtualMachineFileLayoutEx `mo:"layoutEx"` Storage *types.VirtualMachineStorageInfo `mo:"storage"` EnvironmentBrowser types.ManagedObjectReference `mo:"environmentBrowser"` ResourcePool *types.ManagedObjectReference `mo:"resourcePool"` ParentVApp *types.ManagedObjectReference `mo:"parentVApp"` ResourceConfig *types.ResourceConfigSpec `mo:"resourceConfig"` Runtime types.VirtualMachineRuntimeInfo `mo:"runtime"` Guest *types.GuestInfo `mo:"guest"` Summary types.VirtualMachineSummary `mo:"summary"` Datastore []types.ManagedObjectReference `mo:"datastore"` Network []types.ManagedObjectReference `mo:"network"` Snapshot *types.VirtualMachineSnapshotInfo `mo:"snapshot"` RootSnapshot []types.ManagedObjectReference `mo:"rootSnapshot"` GuestHeartbeatStatus types.ManagedEntityStatus `mo:"guestHeartbeatStatus"`}应用fmt.Printf("%#v",该构造体的实例),返回值如下: mo.VirtualMachine{ManagedEntity:mo.ManagedEntity{ExtensibleManagedObject:mo.ExtensibleManagedObject{Self:types.ManagedObjectReference{Type:"VirtualMachine", Value:"vm-60"}, Value:[]types.BaseCustomFieldValue(nil), AvailableField:[]types.CustomFieldDef(nil)}, Parent:(*types.ManagedObjectReference)(0xc0002cd240), CustomValue:[]types.BaseCustomFieldValue(nil), OverallStatus:"green", ConfigStatus:"green", ConfigIssue:[]types.BaseEvent(nil), EffectiveRole:[]int32{-2}, Permission:[]types.Permission(nil), Name:"IDCOMD.192.168.111.207.JumpServer", DisabledMethod:[]string{"MakePrimaryVM_Task", "TerminateFaultTolerantVM_Task", "ResetVM_Task", "UnmountToolsInstaller", "MountToolsInstaller", "MountToolsInstallerImage", "RebootGuest", "StandbyGuest", "ShutdownGuest", "PowerOffVM_Task", "ExtractOvfEnvironment", "SuspendVM_Task", "AcquireMksTicket", "AnswerVM", "UpgradeVM_Task", "UpgradeTools_Task", "UpgradeToolsFromImage_Task", "StartRecording_Task", "StopRecording_Task", "StartReplaying_Task", "StopReplaying_Task", "TurnOffFaultToleranceForVM_Task", "MakePrimaryVM_Task", "TerminateFaultTolerantVM_Task", "DisableSecondaryVM_Task", "EnableSecondaryVM_Task", "CreateSecondaryVM_Task", "CreateSecondaryVMEx_Task", "StopRecording_Task", "StopReplaying_Task", "MarkAsVirtualMachine"}, RecentTask:[]types.ManagedObjectReference(nil), DeclaredAlarmState:[]types.AlarmState{types.AlarmState{DynamicData:types.DynamicData{}, Key:"alarm-10.vm-60", Entity:types.ManagedObjectReference{Type:"VirtualMachine", Value:"vm-60"}, Alarm:types.ManagedObjectReference{Type:"Alarm", Value:"alarm-10"}, OverallStatus:"gray", Time:time.Time{wall:0x20a77770, ext:63700308213, loc:(*time.Location)(nil)}, Acknowledged:(*bool)(0xc0003de040), AcknowledgedByUser:"", AcknowledgedTime:(*time.Time)(nil), EventKey:0}, types.AlarmState{DynamicData:types.DynamicData{}, Key:"alarm-11.vm-60", Entity:types.ManagedObjectReference{Type:"VirtualMachine", Value:"vm-60"}, Alarm:types.ManagedObjectReference{Type:"Alarm", Value:"alarm-11"}, OverallStatus:"gray", Time:time.Time{wall:0x21124b18, ext:63700308213, loc:(*time.Location)(nil)}, Acknowledged:(*bool)(0xc0003de190), AcknowledgedByUser:"", AcknowledgedTime:(*time.Time)(nil), EventKey:0}, types.AlarmState{DynamicData:types.DynamicData{}, Key:"alarm-2.vm-60", Entity:types.ManagedObjectReference{Type:"VirtualMachine", Value:"vm-60"}, Alarm:types.ManagedObjectReference{Type:"Alarm", Value:"alarm-2"}, OverallStatus:"gray", Time:time.Time{wall:0x23562868, ext:63700308213, loc:(*time.Location)(nil)}, Acknowledged:(*bool)(0xc0003de2e0), AcknowledgedByUser:"", AcknowledgedTime:(*time.Time)(nil), EventKey:0}, types.AlarmState{DynamicData:types.DynamicData{}, Key:"alarm-23.vm-60", Entity:types.ManagedObjectReference{Type:"VirtualMachine", Value:"vm-60"}, Alarm:types.ManagedObjectReference{Type:"Alarm", Value:"alarm-23"}, OverallStatus:"gray", Time:time.Time{wall:0x23a273a8, ext:63700308213, loc:(*time.Location)(nil)}, Acknowledged:(*bool)(0xc0003de430), AcknowledgedByUser:"", AcknowledgedTime:(*time.Time)(nil), EventKey:0}, types.AlarmState{DynamicData:types.DynamicData{}, Key:"alarm-26.vm-60", Entity:types.ManagedObjectReference{Type:"VirtualMachine", Value:"vm-60"}, Alarm:types.ManagedObjectReference{Type:"Alarm", Value:"alarm-26"}, OverallStatus:"gray", Time:time.Time{wall:0x23eebee8, ext:63700308213, loc:(*time.Location)(nil)}, Acknowledged:(*bool)(0xc0003de580), AcknowledgedByUser:"", AcknowledgedTime:(*time.Time)(nil), EventKey:0}, types.AlarmState{DynamicData:types.DynamicData{}, Key:"alarm-30.vm-60", Entity:types.ManagedObjectReference{Type:"VirtualMachine", Value:"vm-60"}, Alarm:types.ManagedObjectReference{Type:"Alarm", Value:"alarm-30"}, OverallStatus:"gray", Time:time.Time{wall:0x243b0e10, ext:63700308213, loc:(*time.Location)(nil)}, Acknowledged:(*bool)(0xc0003de6d0), AcknowledgedByUser:"", AcknowledgedTime:(*time.Time)(nil), EventKey:0}, types.AlarmState{DynamicData:types.DynamicData{}, Key:"alarm-49.vm-60", Entity:types.ManagedObjectReference{Type:"VirtualMachine", Value:"vm-60"}, Alarm:types.ManagedObjectReference{Type:"Alarm", Value:"alarm-49"}, OverallStatus:"gray", Time:time.Time{wall:0x251fefd0, ext:63700308213, loc:(*time.Location)(nil)}, Acknowledged:(*bool)(0xc0003de820), AcknowledgedByUser:"", AcknowledgedTime:(*time.Time)(nil), EventKey:0}, types.AlarmState{DynamicData:types.DynamicData{}, Key:"alarm-50.vm-60", Entity:types.ManagedObjectReference{Type:"VirtualMachine", Value:"vm-60"}, Alarm:types.ManagedObjectReference{Type:"Alarm", Value:"alarm-50"}, OverallStatus:"gray", Time:time.Time{wall:0x254dba78, ext:63700308213, loc:(*time.Location)(nil)}, Acknowledged:(*bool)(0xc0003de970), AcknowledgedByUser:"", AcknowledgedTime:(*time.Time)(nil), EventKey:0}, types.AlarmState{DynamicData:types.DynamicData{}, Key:"alarm-51.vm-60", Entity:types.ManagedObjectReference{Type:"VirtualMachine", Value:"vm-60"}, Alarm:types.ManagedObjectReference{Type:"Alarm", Value:"alarm-51"}, OverallStatus:"gray", Time:time.Time{wall:0x257b8138, ext:63700308213, loc:(*time.Location)(nil)}, Acknowledged:(*bool)(0xc0003deac0), AcknowledgedByUser:"", AcknowledgedTime:(*time.Time)(nil), EventKey:0}, types.AlarmState{DynamicData:types.DynamicData{}, Key:"alarm-59.vm-60", Entity:types.ManagedObjectReference{Type:"VirtualMachine", Value:"vm-60"}, Alarm:types.ManagedObjectReference{Type:"Alarm", Value:"alarm-59"}, OverallStatus:"gray", Time:time.Time{wall:0x25d70eb8, ext:63700308213, loc:(*time.Location)(nil)}, Acknowledged:(*bool)(0xc0003dec10), AcknowledgedByUser:"", AcknowledgedTime:(*time.Time)(nil), EventKey:0}, types.AlarmState{DynamicData:types.DynamicData{}, Key:"alarm-6.vm-60", Entity:types.ManagedObjectReference{Type:"VirtualMachine", Value:"vm-60"}, Alarm:types.ManagedObjectReference{Type:"Alarm", Value:"alarm-6"}, OverallStatus:"gray", Time:time.Time{wall:0x2604d578, ext:63700308213, loc:(*time.Location)(nil)}, Acknowledged:(*bool)(0xc0003ded60), AcknowledgedByUser:"", AcknowledgedTime:(*time.Time)(nil), EventKey:0}, types.AlarmState{DynamicData:types.DynamicData{}, Key:"alarm-65.vm-60", Entity:types.ManagedObjectReference{Type:"VirtualMachine", Value:"vm-60"}, Alarm:types.ManagedObjectReference{Type:"Alarm", Value:"alarm-65"}, OverallStatus:"gray", Time:time.Time{wall:0x266066e0, ext:63700308213, loc:(*time.Location)(nil)}, Acknowledged:(*bool)(0xc0003deeb0), AcknowledgedByUser:"", AcknowledgedTime:(*time.Time)(nil), EventKey:0}, types.AlarmState{DynamicData:types.DynamicData{}, Key:"alarm-67.vm-60", Entity:types.ManagedObjectReference{Type:"VirtualMachine", Value:"vm-60"}, Alarm:types.ManagedObjectReference{Type:"Alarm", Value:"alarm-67"}, OverallStatus:"gray", Time:time.Time{wall:0x268e2da0, ext:63700308213, loc:(*time.Location)(nil)}, Acknowledged:(*bool)(0xc0003df000), AcknowledgedByUser:"", AcknowledgedTime:(*time.Time)(nil), EventKey:0}, types.AlarmState{DynamicData:types.DynamicData{}, Key:"alarm-7.vm-60", Entity:types.ManagedObjectReference{Type:"VirtualMachine", Value:"vm-60"}, Alarm:types.ManagedObjectReference{Type:"Alarm", Value:"alarm-7"}, OverallStatus:"gray", Time:time.Time{wall:0x26bbf460, ext:63700308213, loc:(*time.Location)(nil)}, Acknowledged:(*bool)(0xc0003df150), AcknowledgedByUser:"", AcknowledgedTime:(*time.Time)(nil), EventKey:0}, types.AlarmState{DynamicData:types.DynamicData{}, Key:"alarm-95.vm-60", Entity:types.ManagedObjectReference{Type:"VirtualMachine", Value:"vm-60"}, Alarm:types.ManagedObjectReference{Type:"Alarm", Value:"alarm-95"}, OverallStatus:"gray", Time:time.Time{wall:0x27bf5e88, ext:63700308213, loc:(*time.Location)(nil)}, Acknowledged:(*bool)(0xc0003df2a0), AcknowledgedByUser:"", AcknowledgedTime:(*time.Time)(nil), EventKey:0}}, TriggeredAlarmState:[]types.AlarmState(nil), AlarmActionsEnabled:(*bool)(0xc000544dd8), Tag:[]types.Tag(nil)}, Capability:types.VirtualMachineCapability{DynamicData:types.DynamicData{}, SnapshotOperationsSupported:true, MultipleSnapshotsSupported:true, SnapshotConfigSupported:true, PoweredOffSnapshotsSupported:true, MemorySnapshotsSupported:true, RevertToSnapshotSupported:true, QuiescedSnapshotsSupported:true, DisableSnapshotsSupported:false, LockSnapshotsSupported:true, ConsolePreferencesSupported:false, CpuFeatureMaskSupported:true, S1AcpiManagementSupported:true, SettingScreenResolutionSupported:false, ToolsAutoUpdateSupported:false, VmNpivWwnSupported:true, NpivWwnOnNonRdmVmSupported:true, VmNpivWwnDisableSupported:(*bool)(0xc000026e5c), VmNpivWwnUpdateSupported:(*bool)(0xc000026e6c), SwapPlacementSupported:true, ToolsSyncTimeSupported:true, VirtualMmuUsageSupported:true, DiskSharesSupported:true, BootOptionsSupported:true, BootRetryOptionsSupported:(*bool)(0xc000026ecc), SettingVideoRamSizeSupported:true, SettingDisplayTopologySupported:(*bool)(0xc000026eec), RecordReplaySupported:(*bool)(0xc000026efd), ChangeTrackingSupported:(*bool)(0xc000026f0c), MultipleCoresPerSocketSupported:(*bool)(0xc000026f1c), HostBasedReplicationSupported:(*bool)(0xc000026f2c), GuestAutoLockSupported:(*bool)(0xc000026f3c), MemoryReservationLockSupported:(*bool)(0xc000026f4c), FeatureRequirementSupported:(*bool)(0xc000026f5c), PoweredOnMonitorTypeChangeSupported:(*bool)(0xc000026f6c), SeSparseDiskSupported:(*bool)(0xc000026f7c), NestedHVSupported:(*bool)(0xc000026f8c), VPMCSupported:(*bool)(0xc000026f9c), SecureBootSupported:(*bool)(nil), PerVmEvcSupported:(*bool)(nil), VirtualMmuUsageIgnored:(*bool)(nil), VirtualExecUsageIgnored:(*bool)(nil), DiskOnlySnapshotOnSuspendedVMSupported:(*bool)(nil)}, Config:(*types.VirtualMachineConfigInfo)(0xc0005d4000), Layout:(*types.VirtualMachineFileLayout)(0xc00044b260), LayoutEx:(*types.VirtualMachineFileLayoutEx)(0xc0003b6960), Storage:(*types.VirtualMachineStorageInfo)(0xc0005d8000), EnvironmentBrowser:types.ManagedObjectReference{Type:"EnvironmentBrowser", Value:"envbrowser-60"}, ResourcePool:(*types.ManagedObjectReference)(0xc000534020), ParentVApp:(*types.ManagedObjectReference)(nil), ResourceConfig:(*types.ResourceConfigSpec)(0xc0001120e0), Runtime:types.VirtualMachineRuntimeInfo{DynamicData:types.DynamicData{}, Device:[]types.VirtualMachineDeviceRuntimeInfo{types.VirtualMachineDeviceRuntimeInfo{DynamicData:types.DynamicData{}, RuntimeState:(*types.VirtualMachineDeviceRuntimeInfoVirtualEthernetCardRuntimeState)(0xc000208c80), Key:4000}, types.VirtualMachineDeviceRuntimeInfo{DynamicData:types.DynamicData{}, RuntimeState:(*types.VirtualMachineDeviceRuntimeInfoVirtualEthernetCardRuntimeState)(0xc000208d00), Key:4001}}, Host:(*types.ManagedObjectReference)(0xc0004059a0), ConnectionState:"connected", PowerState:"poweredOff", FaultToleranceState:"notConfigured", DasVmProtection:(*types.VirtualMachineRuntimeInfoDasProtectionState)(nil), ToolsInstallerMounted:false, SuspendTime:(*time.Time)(nil), BootTime:(*time.Time)(nil), SuspendInterval:0, Question:(*types.VirtualMachineQuestionInfo)(nil), MemoryOverhead:0, MaxCpuUsage:0, MaxMemoryUsage:0, NumMksConnections:0, RecordReplayState:"inactive", CleanPowerOff:(*bool)(nil), NeedSecondaryReason:"", OnlineStandby:(*bool)(0xc0003ff04d), MinRequiredEVCModeKey:"", ConsolidationNeeded:(*bool)(0xc0003ff05d), OfflineFeatureRequirement:[]types.VirtualMachineFeatureRequirement{types.VirtualMachineFeatureRequirement{DynamicData:types.DynamicData{}, Key:"cpuid.lm", FeatureName:"cpuid.lm", Value:"Bool:Min:1"}}, FeatureRequirement:[]types.VirtualMachineFeatureRequirement(nil), FeatureMask:[]types.HostFeatureMask(nil), VFlashCacheAllocation:0, Paused:(*bool)(0xc0003ff120), SnapshotInBackground:(*bool)(0xc0003ff13b), QuiescedForkParent:(*bool)(nil), InstantCloneFrozen:(*bool)(nil), CryptoState:""}, Guest:(*types.GuestInfo)(0xc000192f00), Summary:types.VirtualMachineSummary{DynamicData:types.DynamicData{}, Vm:(*types.ManagedObjectReference)(0xc000416500), Runtime:types.VirtualMachineRuntimeInfo{DynamicData:types.DynamicData{}, Device:[]types.VirtualMachineDeviceRuntimeInfo{types.VirtualMachineDeviceRuntimeInfo{DynamicData:types.DynamicData{}, RuntimeState:(*types.VirtualMachineDeviceRuntimeInfoVirtualEthernetCardRuntimeState)(0xc000208d80), Key:4000}, types.VirtualMachineDeviceRuntimeInfo{DynamicData:types.DynamicData{}, RuntimeState:(*types.VirtualMachineDeviceRuntimeInfoVirtualEthernetCardRuntimeState)(0xc000208e00), Key:4001}}, Host:(*types.ManagedObjectReference)(0xc000416b60), ConnectionState:"connected", PowerState:"poweredOff", FaultToleranceState:"notConfigured", DasVmProtection:(*types.VirtualMachineRuntimeInfoDasProtectionState)(nil), ToolsInstallerMounted:false, SuspendTime:(*time.Time)(nil), BootTime:(*time.Time)(nil), SuspendInterval:0, Question:(*types.VirtualMachineQuestionInfo)(nil), MemoryOverhead:0, MaxCpuUsage:0, MaxMemoryUsage:0, NumMksConnections:0, RecordReplayState:"inactive", CleanPowerOff:(*bool)(nil), NeedSecondaryReason:"", OnlineStandby:(*bool)(0xc0003ff8bd), MinRequiredEVCModeKey:"", ConsolidationNeeded:(*bool)(0xc0003ff8cd), OfflineFeatureRequirement:[]types.VirtualMachineFeatureRequirement{types.VirtualMachineFeatureRequirement{DynamicData:types.DynamicData{}, Key:"cpuid.lm", FeatureName:"cpuid.lm", Value:"Bool:Min:1"}}, FeatureRequirement:[]types.VirtualMachineFeatureRequirement(nil), FeatureMask:[]types.HostFeatureMask(nil), VFlashCacheAllocation:0, Paused:(*bool)(0xc0003ff966), SnapshotInBackground:(*bool)(0xc0003ff97b), QuiescedForkParent:(*bool)(nil), InstantCloneFrozen:(*bool)(nil), CryptoState:""}, Guest:(*types.VirtualMachineGuestSummary)(0xc000208e80), Config:types.VirtualMachineConfigSummary{DynamicData:types.DynamicData{}, Name:"IDCOMD.192.168.111.207.JumpServer", Template:false, VmPathName:"[VOL02] IDCOMD.192.168.111.207.JumpServer/IDCOMD.192.168.111.207.JumpServer.vmx", MemorySizeMB:8192, CpuReservation:0, MemoryReservation:0, NumCpu:12, NumEthernetCards:2, NumVirtualDisks:1, Uuid:"420ecd79-a338-89a5-0eb8-977dd843814d", InstanceUuid:"500e347d-daeb-8379-9b85-af1b18d6bb2f", GuestId:"centos64Guest", GuestFullName:"CentOS 4/5/6/7 (64-bit)", Annotation:"", Product:(*types.VAppProductInfo)(nil), InstallBootRequired:(*bool)(0xc0003ffcba), FtInfo:types.BaseFaultToleranceConfigInfo(nil), ManagedBy:(*types.ManagedByInfo)(nil), TpmPresent:(*bool)(nil), NumVmiopBackings:0}, Storage:(*types.VirtualMachineStorageSummary)(0xc000091740), QuickStats:types.VirtualMachineQuickStats{DynamicData:types.DynamicData{}, OverallCpuUsage:0, OverallCpuDemand:0, GuestMemoryUsage:0, HostMemoryUsage:0, GuestHeartbeatStatus:"gray", DistributedCpuEntitlement:0, DistributedMemoryEntitlement:0, StaticCpuEntitlement:0, StaticMemoryEntitlement:0, PrivateMemory:0, SharedMemory:0, SwappedMemory:0, BalloonedMemory:0, ConsumedOverheadMemory:0, FtLogBandwidth:-1, FtSecondaryLatency:-1, FtLatencyStatus:"gray", CompressedMemory:0, UptimeSeconds:0, SsdSwappedMemory:0}, OverallStatus:"green", CustomValue:[]types.BaseCustomFieldValue(nil)}, Datastore:[]types.ManagedObjectReference{types.ManagedObjectReference{Type:"Datastore", Value:"datastore-211"}}, Network:[]types.ManagedObjectReference{types.ManagedObjectReference{Type:"Network", Value:"network-16"}}, Snapshot:(*types.VirtualMachineSnapshotInfo)(nil), RootSnapshot:[]types.ManagedObjectReference(nil), GuestHeartbeatStatus:"gray"}这段返回值,纯字符串长度15636;如果再思考到其中嵌套的层层构造体,齐全能够堪称'宏大'. ...

September 22, 2023 · 4 min · jiezi

关于后端:听GPT-讲Istio源代码pkg5

File: istio/pkg/test/framework/components/echo/workloadclass.go文件workloadclass.go是Istio我的项目中测试框架的一部分,用于定义对应的负载类型和行为。以下是对于该文件的具体介绍: 该文件定义了WorkloadClass构造体和其余相干构造体,这些构造体示意不同负载类型以及它们的属性和行为。 WorkloadClass构造体代表一个负载类型,它蕴含以下字段: Kind:负载类型的品种,如Deployment、Pod等。Spec:对于负载类型的具体标准。Features:该负载类型反对的个性列表。Deployment构造体示意负载类型为Deployment的负载,蕴含以下字段: WorkloadClass:援用的负载类型。Template:Deployment模板的定义,如容器镜像、端口等。Pod构造体示意负载类型为Pod的负载,蕴含以下字段: WorkloadClass:援用的负载类型。Template:Pod模板的定义,如容器镜像、端口等。Service构造体示意负载类型为Service的负载,蕴含以下字段: WorkloadClass:援用的负载类型。Ports:Service的端口定义。Gateway构造体示意负载类型为Gateway的负载,蕴含以下字段: WorkloadClass:援用的负载类型。Servers:Gateway服务器的定义,包含监听地址、协定等。通过这些构造体的定义,能够应用WorkloadClass来形容和配置不同类型的负载,以及它们的行为和个性。这对于Istio我的项目中的负载测试和性能测试十分有用。 File: istio/pkg/test/framework/components/echo/kube/pod_controller.goistio/pkg/test/framework/components/echo/kube/pod_controller.go文件的作用是定义了一个用于管制和治理Kubernetes Pod的控制器。 _变量是一个用于占位的匿名变量,通常用于示意不须要应用的返回值。podHandler构造体是Pod处理器的接口,用于解决Pod的事件和谬误。podHandlers构造体是一个蕴含多个podHandler的切片,用于并行处理多个Pod事件和谬误。podController构造体是Pod控制器,用于治理Kubernetes Pod的生命周期和事件。以下是这些函数的作用: newPodController用于创立一个新的Pod控制器实例,并返回指针。Run用于启动Pod控制器,开始监听和解决Pod事件。HasSynced用于判断Pod控制器是否曾经实现了与Kubernetes API Server的同步。WaitForSync用于期待Pod控制器与Kubernetes API Server的同步实现。LastSyncResourceVersion用于获取最初一次与Kubernetes API Server同步的资源版本号。File: istio/pkg/test/framework/components/echo/kube/deployment.goistio/pkg/test/framework/components/echo/kube/deployment.go是istio我的项目中的一个文件,它次要用于定义和治理Kubernetes上的echo组件的部署。 上面对文件中的各个变量和函数进行介绍: echoKubeTemplatesDir:echo组件的Kubernetes模板文件目录门路。VMImages:用于Virtual Machine (VM)的镜像列表。ArmVMImages:用于ARM架构的VM的镜像列表。RevVMImages:用于应用Revision VM的镜像列表。这些变量的作用是在部署echo组件时指定所需的镜像。 接下来是几个重要的构造体: deployment:定义了一个Kubernetes deployment的参数和选项,用于形容和管制echo组件在Kubernetes上的部署。deploymentParams:deployment参数的汇合,包含要应用的镜像、资源配置、环境变量等。serviceParams:定义了echo组件的Kubernetes service的参数和选项,用于将申请从集群内部路由到echo组件。这些构造体的作用是为echo组件的部署提供配置和参数。 上面是一些重要的函数的介绍: getTemplate:依据模板文件门路获取Kubernetes的Deployment或Service的YAML文件内容。newDeployment:依据deploymentParams创立一个新的Deployment对象。Restart:重启一个Deployment。WorkloadReady:期待Deployment中所有pod变为就绪状态。WorkloadNotReady:期待Deployment中所有pod变为非就绪状态。workloadEntryYAML:生成Kubernetes的workload entry的YAML文件内容。GenerateDeployment:生成Deployment的YAML文件内容。GenerateService:生成Service的YAML文件内容。getVMOverrideForIstiodDNS:为Istiod的DNS名称获取VM重写。patchProxyConfigFile:修补代理配置文件。readMeshConfig:读取Mesh配置。createServiceAccount:创立ServiceAccount对象。getContainerPorts:获取Deployment中容器的端口列表。customizeVMEnvironment:自定义VM的环境。canCreateIstioProxy:查看是否能够创立Istio代理。getIstioRevision:获取Istio的订正版本。statefulsetComplete:查看StatefulSet是否实现。deploymentComplete:查看Deployment是否实现。这些函数的作用包含生成Kubernetes资源的YAML文件内容、期待资源的就绪状态、修补配置文件等。 总之,istio/pkg/test/framework/components/echo/kube/deployment.go文件是用于治理和操作istio中的echo组件在Kubernetes上的部署的文件,它定义了一些配置变量和函数,用于创立、批改和验证echo组件的部署状态。 File: istio/pkg/test/framework/components/echo/kube/workload_manager.go在Istio我的项目中,istio/pkg/test/framework/components/echo/kube/workload_manager.go文件的作用是定义了用于治理Kubernetes工作负载的辅助函数和构造。 首先,_变量在Go语言中用来占位,示意不关怀这个变量的值或者不应用该变量。 workloadHandler是一个接口类型,用于解决工作负载的不同操作(例如创立、更新、删除等)。该接口是由pkg/test/framework/components/echo/kube/handler.Handler接口定义的。 workloadManager是一个构造体类型,蕴含了对工作负载的治理操作。它具备以下性能: newWorkloadManager函数用于创立一个新的workloadManager对象。WaitForReadyWorkloads函数会期待指定的工作负载准备就绪。readyWorkloads函数会返回所有已准备就绪的工作负载。ReadyWorkloads函数会返回一个通道,用于接管准备就绪的工作负载信息。Start函数用于启动工作负载管理器。onPodAddOrUpdate函数用于在Pod被增加或更新时调用工作负载处理器。onPodDeleted函数用于在Pod被删除时调用工作负载处理器。Close函数用于敞开工作负载管理器。总的来说,workload_manager.go文件定义了一个用于治理Kubernetes工作负载的工具,提供了创立、更新、删除等操作的辅助函数和构造体。 File: istio/pkg/test/framework/components/echo/check/checkers.go在istio我的项目中,checkers.go文件是istio/pkg/test/framework/components/echo/check包中的一个文件,它定义了用于在回声组件测试中进行断言查看的函数。 以下是文件中提供的性能函数及其作用: Each(...Checker):将多个查看器链在一起,并顺次对每个查看器进行查看。And(...Checker):将多个查看器链在一起,并同时对所有查看器进行查看。Or(...Checker):将多个查看器链在一起,并只有至多一个查看器通过就返回胜利。filterNil(... Checker) Checker:过滤掉所有空查看器并返回非空查看器的汇合。NoError:查看HTTP或gRPC响应是否没有谬误。Error:查看HTTP或gRPC响应是否蕴含谬误。ErrorContains(string):查看HTTP或gRPC响应中的谬误音讯是否蕴含指定的字符串。ErrorOrStatus(uint32):查看HTTP或gRPC响应是否蕴含谬误,或者HTTP状态码等于指定的值。ErrorOrNotStatus(uint32):查看HTTP或gRPC响应是否蕴含谬误,或者HTTP状态码不等于指定的值。OK:查看HTTP或gRPC响应的状态码是否等于200。NotOK:查看HTTP或gRPC响应的状态码是否不等于200。NoErrorAndStatus(uint32):查看HTTP或gRPC响应是否没有谬误,并且状态码等于指定的值。Status(uint32):查看HTTP或gRPC响应的状态码是否等于指定的值。NotStatus(uint32):查看HTTP或gRPC响应的状态码是否不等于指定的值。VStatus(string):查看HTTP或gRPC响应的状态码是否蕴含指定的字符串。VNotStatus(string):查看HTTP或gRPC响应的状态码是否不蕴含指定的字符串。GRPCStatus(uint32):查看gRPC响应的状态码是否等于指定的值。BodyContains(string):查看HTTP或gRPC响应的主体是否蕴含指定的字符串。Forbidden:查看HTTP或gRPC响应的状态码是否等于403。TooManyRequests:查看HTTP或gRPC响应的状态码是否等于429。Host(string):查看HTTP或gRPC申请的主机是否等于指定的值。Hostname(string):查看HTTP或gRPC申请的主机名是否等于指定的值。Protocol(string):查看HTTP或gRPC申请的协定是否等于指定的值。Alpn(string):查看HTTP或gRPC连贯的ALPN值是否等于指定的值。isHTTPProtocol:查看HTTP或gRPC申请是否应用HTTP协定。isMTLS:查看HTTP或gRPC申请是否应用MTLS协定。MTLSForHTTP:查看HTTP申请是否应用MTLS协定。PlaintextForHTTP:查看HTTP申请是否应用明文协定。Port(int32):查看HTTP或gRPC申请的端口是否等于指定的值。requestHeader(string, string):查看HTTP或gRPC申请中指定名称的头是否存在且值与指定值匹配。responseHeader(string, string):查看HTTP或gRPC响应中指定名称的头是否存在且值与指定值匹配。RequestHeader(...HeaderMatcher):查看HTTP或gRPC申请的头是否匹配定义的HeaderMatcher列表。ResponseHeader(...HeaderMatcher):查看HTTP或gRPC响应的头是否匹配定义的HeaderMatcher列表。RequestHeaders(...HeaderMatcher):查看HTTP或gRPC申请的头是否至多匹配列表中的一个HeaderMatcher。ResponseHeaders(...HeaderMatcher):查看HTTP或gRPC响应的头是否至多匹配列表中的一个HeaderMatcher。Cluster(... string):查看申请是否已达到指定的集群。URL(... string):查看HTTP或gRPC申请的URL是否与指定的URL匹配。IsDNSCaptureEnabled:查看是否启用了DNS捕捉。ReachedTargetClusters:查看是否已达到指标集群。ReachedClusters(... string):查看申请是否已达到给定的集群之一。ReachedSourceCluster:查看申请是否已达到源集群。checkReachedSourceClusterOnly:查看申请是否仅已达到源集群。checkReachedSourceNetworkOnly:查看申请是否仅已达到源网络。checkReachedClusters(... string):查看申请是否已达到给定的集群。checkReachedNetworks(... string):查看申请是否已达到给定的网络。isNaked:查看是否为"naked"域名。clusterFor(string, string) string:查看指定的域名和端口是否关联到了标识的集群。checkReachedClustersInNetwork(string, ...string) bool:查看申请是否已达到给定网络中的给定集群。以上是checkers.go文件中提供的一些性能函数及其作用的简要介绍。这些函数用于在istio我的项目的回声组件测试中对HTTP和gRPC申请/响应进行断言查看,以确保预期的行为和后果。 File: istio/pkg/test/framework/components/echo/check/visitor.go在Istio我的项目中,visitor.go 文件位于 istio/pkg/test/framework/components/echo/check 目录下,它是用于定义拜访和查看 Echo 组件的访问者模式的实现。 Visitor 构造体: Visitor:定义了拜访 Echo 组件的接口,蕴含了多个拜访 Echo 组件的办法,即对组件执行不同的操作。And:将多个 Visitor 构造体组合成一个,并且所有 Visitor 都必须返回 true 能力通过。Or:将多个 Visitor 构造体组合成一个,并且任一 Visitor 返回 true 就能够通过。Checker 构造体: ...

September 22, 2023 · 2 min · jiezi

关于后端:听GPT-讲Istio源代码pkg4

File: istio/pkg/test/framework/components/cluster/topology.goistio/pkg/test/framework/components/cluster/topology.go文件是Istio我的项目中的一个测试框架组件,用于定义和治理测试环境中的集群拓扑构造。 其中,knownClusterNames是一个全局变量,用于保留已知的集群名称。它容许测试框架在不同的测试场景中援用这些已知的集群名称。 Map构造体是用于存储集群拓扑构造的映射,其键是集群名称,值是该集群的配置信息。Topology构造体示意一个集群拓扑,蕴含了该集群的名称、域名、代理配置等信息。 NewTopology函数用于创立一个新的集群拓扑对象。MetadataValue函数用于创立一个用于存储元数据的对象。NetworkName函数用于定义集群的网络名称。Name函数用于设置集群的名称。HTTPProxy函数用于设置集群的HTTP代理配置。ProxyKubectlOnly函数用于设置集群是否仅反对通过kubectl进行代理。StableName函数用于设置集群的稳固名称。Kind函数用于设置集群的类型。IsPrimary函数用于查看集群是否为主集群。IsConfig函数用于查看集群是否为配置集群。IsRemote函数用于查看集群是否为近程集群。IsExternalControlPlane函数用于查看集群是否有内部管制立体。Primary函数获取主集群。PrimaryName函数获取主集群的名称。Config函数获取配置集群。ConfigName函数获取配置集群的名称。WithPrimary函数用于设置主集群。WithConfig函数用于设置配置集群。MinKubeVersion函数用于设置集群的最小Kubernetes版本。MaxKubeVersion函数用于设置集群的最大Kubernetes版本。String函数用于将集群拓扑对象转换为字符串示意模式。 总的来说,这个文件定义了一个集群拓扑构造和相干的操作方法,用于在Istio我的项目中治理测试环境中的集群配置。 File: istio/pkg/test/framework/components/cluster/staticvm/staticvm.go在Istio我的项目中,istio/pkg/test/framework/components/cluster/staticvm/staticvm.go文件是一个蕴含动态虚拟机的测试框架组件。它提供了一种在单个或多个虚拟机上运行测试的形式。 上面是对其中的变量和构造体的介绍: _ 变量:在golang中,未应用的变量须要通过_来接管,以防止编译谬误。vmcluster 构造体:示意一个动态虚拟机群集。它蕴含了虚拟机组件的相干信息和配置。 VMInstances:示意虚拟机实例的列表。VMCount:指定要创立的虚拟机数量。SSHKeyPath:示意SSH密钥的门路。BaseName:示意虚拟机的根本名称。BaseIP:示意虚拟机的根本IP地址。ClusterIP:示意虚拟机群集的IP地址。接下来是对一些函数的介绍: init 函数:用于初始化动态虚拟机群集的配置和状态。build 函数:依据给定的配置信息创立动态虚拟机群集。readInstances 函数:从虚拟机的元数据中读取虚拟机实例的信息。instanceFromMeta 函数:依据元数据创立虚拟机实例。CanDeploy 函数:查看是否能够在虚拟机群集上部署给定的服务。GetKubernetesVersion 函数:获取虚拟机群集上运行的Kubernetes版本。matchConfig 函数:将给定的配置信息与虚拟机群集中的理论配置进行匹配并验证。这些函数的具体作用是依据需要对虚拟机群集进行配置、创立、治理以及验证配置的正确性。 File: istio/pkg/test/framework/components/echo/cmd/echogen/echogen.goechogen.go文件的作用是生成用于测试的echo服务代码。该文件是Istio我的项目中的测试框架组件之一,用于疾速生成具备指定性能的echo服务,不便对Istio进行测试和验证。 以下是echogen.go文件中各个局部的具体介绍: outputPath变量:示意生成的echo服务代码的输入门路。dirOutput变量:示意是否将生成的代码输入到指定门路。generator构造体:用于定义生成器相干的信息,包含要生成的服务数量、服务命名、监听地址和端口等。init函数:初始化生成器的相干参数,例如设置默认的输入门路、解析命令行参数等。main函数:入口函数,解析命令行参数并调用generate函数生成echo服务代码。generate函数:依据生成器的配置信息调用newGenerator函数创立指定数量的生成器,并调用load函数加载模板文件和插件。newGenerator函数:创立一个生成器实例,依据配置信息初始化生成器的参数,并返回该实例。load函数:加载模板文件和插件,行将模板文件和插件转换为生成器可用的格局。joinManifests函数:将多个模板文件合并成一个manifest文件。writeOutputFile函数:将生成的代码写入到输入文件中。总体来说,echogen.go文件是Istio我的项目中的一个测试框架组件,用于疾速生成用于测试的echo服务代码。它通过生成器配置和模板文件,能够依据需要疾速生成指定数量的echo服务,不便进行Istio的测试和验证工作。 File: istio/pkg/test/framework/components/echo/caller.go在istio我的项目的目录构造中,istio/pkg/test/framework/components/echo/caller.go文件的作用是定义了用于向Echo服务器发动调用申请的组件Caller。具体来说,该文件定义了Caller接口和Callers构造体。 CallResult:用于存储单个调用操作的后果,蕴含响应状态码、响应体以及错误信息。Caller:是一个接口定义,用于封装对Echo服务器的调用操作。Caller接口定义了一些办法,如Do、Get、Post等,用于发动HTTP申请,并返回响应后果。Callers:是一个构造体,代表一组Caller实例,提供了不便的调用操作。Callers构造体外部蕴含一个map,其中键为Caller的名称,值为Caller实例。文件中还定义了几个与echo调用相干的函数,用于创立和治理Caller实例: NewCaller:用于创立一个Caller实例。该函数承受一个Echo服务器的URL作为参数,并返回一个实现了Caller接口的对象。MustCreateCallers:创立一组Caller实例。该函数承受一个map参数,其中键为Caller的名称,值为对应的Echo服务器URL。该函数会遍历map,创立对应的Caller实例,并存储在Callers构造体的实例中。Instances:返回已创立的Caller实例Map。该函数用于获取Callers构造体中存储的所有Caller实例。总之,caller.go文件定义了用于向Echo服务器发动调用申请的Caller组件,以及封装了不便的Caller操作的Callers构造体和相干函数。 File: istio/pkg/test/framework/components/echo/echotest/setup.go在Istio我的项目中,istio/pkg/test/framework/components/echo/echotest/setup.go文件的作用是提供了用于设置Echo组件的测试环境的性能。 该文件中定义了几个重要的构造体和函数。 srcSetupFn构造体:该构造体用于定义Echo的源组件的设置函数,包含设置源组件的Pod、Service和Endpoint等。Setup函数:该函数用于设置Echo组件的测试环境,它会调用setupSource和setupDestination两个函数来设置源组件和指标组件的测试环境。setup函数:该函数用于设置组件的测试环境,它接管一个srcSetupFn函数作为参数,用于设置测试环境中的源组件。同时,它还负责创立和初始化一些必要的资源,例如Pod、Service和Endpoint。最初,它会返回一个用于设置指标组件的函数。hasSourceSetup函数:该函数用于判断在给定的测试环境中是否设置了源组件。SetupForPair函数:该函数用于设置一个源组件和一个指标组件之间的测试环境。它接管两个srcSetupFn函数作为参数,别离用于设置源组件和指标组件的测试环境。SetupForServicePair函数:该函数用于设置一个源组件和一个指标服务之间的测试环境。它接管一个srcSetupFn函数用于设置源组件的测试环境,并为指标服务创立和初始化一个虚构Service。SetupForDestination函数:该函数用于设置一个指标组件的测试环境。它接管一个srcSetupFn函数用于设置指标组件的测试环境。hasDestinationSetup函数:该函数用于判断在给定的测试环境中是否设置了指标组件。setupPair函数:该函数用于设置一个源组件和一个指标组件之间的测试环境,并为它们创立和初始化一些必要的资源,例如Pod、Service和Endpoint。这些函数的作用是依据给定的测试需要,创立和配置Istio组件的测试环境,以便进行Echo组件的测试和性能验证。这些函数会解决底层的资源和组件,确保它们正确地设置和初始化,并可能互相通信和交互。 File: istio/pkg/test/framework/components/echo/echotest/run.go在istio我的项目中,istio/pkg/test/framework/components/echo/echotest/run.go文件的作用是定义了一系列用于运行echotest的函数。echotest是一个用于测试istio中Echo服务的测试组件。 perDeploymentTest这几个构造体定义了一系列用于运行测试的配置,每个构造体都蕴含一些字段和办法,用于指定测试的指标Deployment、服务端口、申请超时、测试后果等。 Run函数用于运行测试,它会依照指定的配置参数创立一个或多个client连贯到指标服务,并发送申请进行测试,并返回测试后果。RunFromClusters函数应用指定的集群连贯信息,从每个集群发送申请进行测试,并返回测试后果。fromEachCluster函数会为每个指定的集群连贯信息创立一个client连贯,并发送申请进行测试,并返回测试后果。RunToN函数用于向指标服务发送指定数量的申请进行测试,并返回测试后果。RunViaIngress函数应用指定的Ingress进行申请转发,向指标服务发送申请进行测试,并返回测试后果。isMultipleNamespaces函数用于查看测试是否波及到多个命名空间。fromEachDeployment函数会为每个指定的Deployment创立一个client连贯,并发送申请进行测试,并返回测试后果。toEachDeployment函数会将申请发送到每个指定的Deployment进行测试,并返回测试后果。fromEachWorkloadCluster函数会为每个指定的工作负载集群创立一个client连贯,并发送申请进行测试,并返回测试后果。toNDeployments函数会将申请发送到指定的一组Deployment中的随机N个进行测试,并返回测试后果。nDestinations函数用于指定测试的指标服务数量,用于进行多指标服务的测试。这些函数提供了灵便的配置选项,能够依据测试需要,抉择不同的形式来执行echotest,并返回相应的测试后果。 File: istio/pkg/test/framework/components/echo/util/traffic/result.go在Istio我的项目中,result.go文件的作用是定义用于记录和计算流量后果的构造体和函数。 该文件中定义了以下几个构造体: Result:Result构造体用于示意流量后果。它蕴含两个字段:Successes和Total。Successes示意胜利的流量数,Total示意总共的流量数。String:String构造体用于将后果以字符串的模式进行展现。它实现了fmt.Stringer接口,能够通过调用String()办法将后果转换为字符串模式。CheckSuccessRate:CheckSuccessRate构造体用于查看流量的成功率。它蕴含两个字段:Successes和Total,代表胜利的流量数和总共的流量数。CheckSuccessRate构造体实现了Check办法,该办法用于查看流量的成功率是否达到指定的阈值。此外,result.go文件还蕴含以下几个函数: add:add函数用于向后果中减少流量统计信息。它接管一个布尔值作为参数,如果该参数为true,则示意流量胜利,将后果中的Successes字段加1,否则将Total字段加1。PercentSuccess:PercentSuccess函数用于计算流量的成功率。它接管一个Result构造体作为参数,通过计算该构造体中的Successes和Total字段,返回成功率的百分比值。这些构造体和函数提供了一种不便的形式来记录和操作流量后果,以便进行进一步的剖析和评估。 File: istio/pkg/test/framework/components/echo/config/param/params.go在Istio我的项目中,istio/pkg/test/framework/components/echo/config/param/params.go文件的作用是定义了一组用于配置Echo组件的参数。 Params构造体是一个参数的汇合,它定义了多个字段,每个字段对应Echo组件的一个配置参数。在Params构造体中,应用了json和yaml的标签来指定参数的名称和类型,以便在配置文件中进行序列化和反序列化。 以下是Params构造体中几个重要字段的作用: Port:指定Echo组件的服务端口号。Delay:指定申请解决的延迟时间。RateLimitPeriod:指定申请的速率限度周期。RateLimitQps:指定申请的速率限度值。NewParams函数用于创立一个空的Params对象,能够通过该对象设置Echo组件的配置参数。 Get函数用于获取Params构造体中指定字段的值。能够通过.语法来拜访嵌套字段。 GetWellKnown函数用于获取Params构造体中预约义字段的值。预约义字段是在Params构造体中定义了默认值的字段,能够间接获取其值。 Set函数用于设置Params构造体中指定字段的值。 SetAll函数用于设置Params构造体中所有字段的值。能够通过传入另一个Params对象来获取其所有字段的值。 SetAllNoOverwrite函数相似于SetAll函数,然而在设置值时不会笼罩已有的非零值。 SetWellKnown函数用于设置Params构造体中预约义字段的值。 Contains函数用于判断Params构造体中是否存在指定字段。 ContainsWellKnown函数用于判断Params构造体中是否存在预约义字段。 Copy函数用于创立Params构造体的一个正本,包含所有的配置参数。 通过应用这些函数,能够不便地配置和治理Echo组件的参数,并能够在不同环境中灵便地应用和批改这些参数。 File: istio/pkg/test/framework/components/echo/config/source.go在Istio我的项目中,istio/pkg/test/framework/components/echo/config/source.go这个文件的作用是定义用来配置Echo组件的源码。 在源文件中,有以下几个构造体和函数: Source构造体:定义了一个接口,示意配置文件的源码。sourceImpl构造体:实现了Source接口,示意具体的配置文件源码信息。YAML函数:用于从YAML文件中加载配置。它承受一个文件名作为参数,并返回一个Source对象。File函数:用于从文件中读取配置。它承受一个文件名作为参数,并返回一个Source对象。Template函数:用于创立一个配置模板。它承受一个字符串作为参数,并返回一个Source对象。TemplateOrFail函数:与Template函数相似,但如果模板创立失败,则会导致测试失败。MustTemplate函数:与Template函数相似,但如果模板创立失败,则会导致测试终止。YAMLOrFail函数:与YAML函数相似,但如果YAML文件加载失败,则会导致测试失败。MustYAML函数:与YAML函数相似,但如果YAML文件加载失败,则会导致测试终止。Split函数:用于依据指定的宰割符将字符串拆分为多个子字符串。它承受一个字符串和一个宰割符作为参数,并返回一个字符串切片。SplitOrFail函数:与Split函数相似,但如果拆分失败,则会导致测试失败。MustSplit函数:与Split函数相似,但如果拆分失败,则会导致测试终止。Params函数:用于创立一个蕴含参数的Source对象。它承受一个Map类型的参数,并返回一个Source对象。WithParams函数:用于创立一个新的Source对象,并将参数与已存在的参数进行合并。它承受一个Map类型的参数,并返回一个Source对象。WithNamespace函数:用于将指定的命名空间增加到每个对象的元数据中。它承受一个字符串作为参数,并返回一个Source对象。这些函数和构造体的作用是为了不便测试开发者应用源码形式来配置Echo组件,并实现了一些对配置文件操作的便捷函数。 File: istio/pkg/test/framework/components/echo/config/sources.go在Istio我的项目中,istio/pkg/test/framework/components/echo/config/sources.go文件用于定义Echo测试组件的配置源。该文件中定义了几个构造体(Sources)和函数(WithParams、WithNamespace),用于获取Echo测试组件的配置参数。 Sources构造体: Sources构造体定义了Echo测试组件的配置源,包含配置文件的门路、默认的参数值和命名空间等信息。它具备以下字段: ConfigFilePath:配置文件的门路,默认为"echo.config.yaml"。DefaultParams:默认的参数值,用于笼罩配置文件中未指定的参数。这个字段是一个字符串映射表,其中键为参数名,值为参数的默认值。Namespace:Echo测试组件所在的命名空间,默认为"default"。WithParams函数: WithParams函数用于设置Echo测试组件的配置参数。它承受一个参数映射表,并将这些参数增加到配置源的默认参数中。如果配置文件中曾经存在雷同的参数键,则应用传入的参数值进行笼罩。WithNamespace函数: WithNamespace函数用于设置Echo测试组件所在的命名空间。它承受一个命名空间字符串,并将其笼罩配置源中的命名空间字段。这些构造体和函数的作用是对立治理Echo测试组件的配置源,提供了灵便的配置参数设置形式,并容许在须要时笼罩默认的配置。这样能够简化Echo测试组件的配置和应用。 File: istio/pkg/test/framework/components/echo/match/matcher.go在Istio我的项目中,文件istio/pkg/test/framework/components/echo/match/matcher.go的作用是提供用于匹配和筛选Echo服务的申请/响应的性能。 ...

September 22, 2023 · 1 min · jiezi

关于后端:听GPT-讲Istio源代码pkg3

File: istio/pkg/test/util/tmpl/execute.go文件istio/pkg/test/util/tmpl/execute.go是Istio我的项目中的一个辅助工具,用于执行模板化的命令。 在测试和开发过程中,为了不便和自动化地执行一些命令行操作,能够应用模板化的形式定义命令,并将参数动静填充到命令模板中。 Execute和ExecuteOrFail是这个工具提供的两个函数,它们有以下作用: Execute: Execute函数用于执行一个命令模板,并返回命令的输入和错误信息。它能够接受命令模板和参数,并将参数动静填充到模板中。执行过程中,它会应用操作系统的命令执行工具(如exec.Command)来执行命令,并捕捉执行后果。 例如,能够应用Execute函数执行一个命令模板,例如: output, err := Execute("ls {{ .dir }}", map[string]interface{}{"dir": "/tmp"})if err != nil { // 处理错误}fmt.Println(output)ExecuteOrFail: ExecuteOrFail函数与Execute函数相似,然而在命令执行失败时会触发测试失败。它会调用testing.T对象的Fatal办法,使得测试可能立刻完结,并显示错误信息。 例如,能够应用ExecuteOrFail函数执行一个命令模板,并在执行失败时触发测试失败,例如: ExecuteOrFail("rm {{ .file }}", map[string]interface{}{"file": "/tmp/file"})总体而言,execute.go文件中的Execute和ExecuteOrFail函数提供了一种不便的形式来执行模板化的命令,并将命令的输入和错误信息返回给调用者。这在Istio我的项目的测试和开发过程中十分有用,能够简化命令行操作并提供错误处理性能。 File: istio/pkg/test/util/assert/tracker.go在Istio我的项目中,tracker.go文件的作用是提供一种轻量级的跟踪工具,用于在测试中捕捉和验证并发事件的程序。该文件定义了名为Tracker的构造体以及一些与之相干的函数。 Tracker构造体有三个重要的成员变量: t:用于记录事件的工夫戳,以确保事件的程序性。records:用于存储事件并放弃原始的程序。waitCh:用于在WaitOrdered函数中期待有序的事件触发的通道。上面是Tracker构造体的定义: type Tracker struct { t *testing.T records []Record waitCh chan int}NewTracker函数创立并返回一个新的Tracker实例,能够通过传递一个testing.T对象来进行初始化,以便在测试失败时生成具体的谬误音讯。 Record函数用于记录事件并将其附加到Tracker的records切片中,其中事件是一个任意类型的值。 WaitOrdered函数用于期待被记录的事件依照它们被记录的程序触发。能够通过调用Record函数将事件增加到Tracker中,并在WaitOrdered中期待它们按程序触发。如果事件的触发程序与其被记录的程序不统一,则会导致测试失败。 示例: func TestOrder(t *testing.T) { tracker := NewTracker(t) go func() { time.Sleep(time.Second) tracker.Record("Event 1") }() go func() { time.Sleep(2 * time.Second) tracker.Record("Event 2") }() tracker.WaitOrdered("Event 1") tracker.WaitOrdered("Event 2")}在下面的示例中,咱们创立了一个Tracker实例并应用两个并发的goroutine别离记录两个事件。而后应用WaitOrdered函数顺次期待这两个事件按程序触发。如果这两个事件产生的程序不合乎预期,那么测试将失败并生成相应的谬误音讯。 ...

September 22, 2023 · 1 min · jiezi

关于后端:JDK21更新特性详解

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 文章更新打算 | 430: | String Templates (Preview) |1. 什么是 String Templates?String Templates 是 Java 15 中引入的一个新个性,它容许咱们在字符串中应用占位符来动静替换变量的值。它提供了一种更简洁、更直观的形式来构建字符串,而不须要应用传统的字符串拼接或格式化办法。 2. 为什么须要 String Templates?在传统的 Java 中,咱们通常应用字符串拼接或格式化办法来构建动静字符串。这种形式须要手动解决变量的值,并且容易出错。而且,当字符串中蕴含大量变量时,代码会变得简短且难以保护。 String Templates 的引入解决了这个问题,它提供了一种更简洁、更易读的形式来构建动静字符串。通过应用占位符,咱们能够将变量的值间接嵌入到字符串中,而不须要手动解决。 3. String Templates 的实现原理?String Templates 的实现原理是通过在字符串中应用占位符${}来示意变量。在运行时,Java 编译器会将这些占位符替换为理论的变量值。 具体来说,当咱们应用 String Templates 时,编译器会将字符串中的占位符${}解析为一个非凡的表达式,并将其转换为对应的变量值。这个过程是在编译时实现的,所以在运行时不会有额定的性能开销。 4. String Templates 的长处简洁易读:应用占位符${}来示意变量,使得代码更加简洁、易读。类型平安:String Templates 在编译时会进行类型查看,确保变量的类型与占位符的类型匹配,防止了运行时的类型谬误。性能优化:String Templates 的解析过程是在编译时实现的,所以在运行时不会有额定的性能开销。可扩展性:String Templates 反对自定义的格式化函数,能够依据需要进行扩大。5. String Templates 的毛病兼容性:String Templates 是 Java 15 中引入的新个性,须要应用 Java 15 或更高版本的 JDK 能力应用。语法限度:String Templates 的占位符${}只能用于示意变量,不能用于执行任意的表达式。可读性:当字符串中蕴含大量的占位符时,可能会升高代码的可读性。6. String Templates 的应用示例上面是一个应用 String Templates 的简略示例: ...

September 22, 2023 · 12 min · jiezi

关于后端:反方对一辩稿的质询

常见对方质询框架及其纠正:(可用于正方一辩/三辩进攻对方质询/盘问)有很多大学生都是自觉去考研的,因为很迷茫不敢进入社会而考研,那这时再去考研是理智的吗?你在阐述大学生因为迷茫而去考研不明智,而辩题是大学生因为待业难而去考研是否理智,脱离了辩题的思考范畴。咱们思考的是感到待业难的群体如何口头更理智,而非感到迷茫的群体如何口头更理智,按您方的想法,那干别的都不算理智,去找个巨匠聊天才算理智。 blablabla证据显示以后整体市场待业岗位多,只是那些狗屁大学生好高骛远不愿做罢了,只想读研去跟那些学历更高的人卷,这样明明有工作,却去抉择考研,读完找的更好的工作又不好找,这不是舍易求难吗?对方辩友意思是比方能很简略地找个刷盘子的工作,为什么要去读个研去卷大厂AI岗呢? 对方辩友本人给大学生群体立了一个待业是否艰难的规范,认为只有能在社会找到个工作,无论工作是什么,都不应该认为待业难。对方的前提是当今大学生都不应该感觉到待业难,但这显著是谬误的,我感觉待业难不难须要你管吗!我实现我的集体价值,你要我去做我不想要的工作还批评我好高骛远!待业难的定义是个人感觉找到本人冀望范畴内工作的难度比拟高,难与不难是集体在环境中本身的感觉。而且咱们的辩题是大学生因为待业难而做什么更理智,咱们思考的群体是那些感觉到待业难的人,我方认为用考研读研后再去待业对于促成待业是有很大收益的。 正方认为待业难的成因是什么?(咱们没有任务去论证待业市场大环境是否难,就算黄金盛世也有感到待业难的人,而且目前后疫情时代雀食很多人都很难找到本人冀望的工作,这点咱们没任务做数据撑持) 待业难是个人感觉找到本人冀望范畴内工作的难度比拟高,感到难是集体能力和主观环境两个因素的影响。我方不关怀待业市场是否低迷,岗位有多少,我方只思考那些感到找不到冀望工作的大学生。TA们感到难不难取决于TA们本人的价值观,而非由对方辩友定义难不难。TA们去考研进步本身后再待业,对找到冀望工作的益处有很大。 对方只假如考上了研,评估其收益,那对于那些考不上研的大学生是不是不明智的呢?考研是读研要付出的老本,任何行为都有老本和收益,咱们不能把老本和收益分隔开。咱们评估是否理智自身就是思考这个行为的冀望收益减去老本。反方如果把老本和收益分隔开,那也有很多大学生是破费了很多找工作的老本而没有找到冀望工作的。

September 22, 2023 · 1 min · jiezi

关于后端:深入理解-Go-中的-new-和-make-函数

在 Go 语言中,new() 和 make() 是两个罕用的函数,用于创立和初始化不同类型的变量。本文将深入探讨 new() 和 make() 的区别、应用场景以及底层实现原理。 引言Go 中的 new() 和 make() 函数是用于创立和初始化变量的重要工具。new() 用于创立指定类型的零值变量,并返回该变量的指针。make() 用于创立并初始化援用类型的变量,如切片、映射和通道。new() 函数new() 函数的根本语法及用法。new() 创立的变量是指定类型的零值,并返回该变量的指针。new() 实用于创立援用类型以外的其余类型变量。package mainimport "fmt"func main() { // 应用 new() 创立一个 int 类型的零值变量的指针 numPtr := new(int) fmt.Println(*numPtr) // 输入 0}make() 函数make() 函数的根本语法及用法。make() 用于创立并初始化援用类型的变量。make() 实用于创立切片、映射和通道等援用类型的变量。make() 创立的变量不是零值,而是依据类型进行初始化。package mainimport "fmt"func main() { // 应用 make() 创立一个切片,并初始化长度为 3 的切片 slice := make([]int, 3) fmt.Println(slice) // 输入 [0 0 0]}new() 和 make() 的区别new() 用于创立任意类型的变量,而 make() 仅用于创立援用类型的变量。new() 返回的是指针,而 make() 返回的是初始化后的值。new() 创立的变量是零值,make() 创立的变量是依据类型进行初始化。package mainimport "fmt"func main() { // 应用 new() 创立一个构造体的指针 personPtr := new(Person) personPtr.Name = "Alice" personPtr.Age = 30 fmt.Println(personPtr) // 输入 &{Alice 30} // 应用 make() 创立一个映射,并初始化键值对 m := make(map[string]int) m["one"] = 1 m["two"] = 2 fmt.Println(m) // 输入 map[one:1 two:2]}type Person struct { Name string Age int}new() 和 make() 的底层实现原理在 Go 语言中,new() 和 make() 的底层实现原理略有不同。 ...

September 22, 2023 · 2 min · jiezi

关于后端:159235-使用java实现数据视觉查看器

159.235 2023 S02 — Assignment 2This assignment covers the topics: coordinates, transformations, 3d modelling, and visiblesurfaces.Wireframe Data ViewerWrite a Java program that renders a 3 dimensional triangle wireframe surface data modeland allows one to rotate and scale the model so that it can be viewed from any direction.This could be thought of as a simple CAD program.Your application needs to be set up so that the figures rotate as the sliders are adjusting,they uniformaly resize after clicking the appropriate button, and they get re-drawn whentoggling between anti-aliasing on/off.Use the simple viewing model where the “eye” point is on the positive z-axis looking downand the figures are drawn by orthographically projecting onto the xy-plane.You will need to decide how to transform the vertex coordinates in the wireframe data forthe given rotations and scalings. You can then draw each triangle on the Graphics2D canvaswith the transformed vertex positions.Your rendered wireframe figures should appear “solid”—the wireframe outlines should beclearly visible. You need to implement some procedure to remove hidden surfaces. Youshould at least implement the back face culling method. You should find that this willremove most hidden surfaces—but not all of them. Top marks will be earned by thoseprograms that are able to remove all hidden surfaces.A set of triangle mesh wireframe data files are provided on Stream. You program should worksmoothly with all of them. The cow and teapot figures will mainly be used to benchmarkyour submission.Note: you do not need to apply any lighting or shading to the surfaces—this will be dealtwith later on in the course.Completing the assignmentA set of startup Java source files are on Stream that will function as skeleton code forthe assignment. Load these into a new IntelliJ project and start up Main.java—this is the“controller” part of your project. This features a number of JPanels with slider and buttonwidgets. Familiarize yourself with the various components in the project folder.To complete the assignment, provide implementations for the other components. Whendoing so you will need to make small adjustments to Main.java—mostly in the event handlermethod. Complete as follows: ...

September 22, 2023 · 4 min · jiezi

关于后端:ToplingDB-Zero-Copy

背景ToplingDB 是 topling 开发的 KV 存储引擎,fork 自 RocksDB,进行了很多革新,其中最重要的部件是 ToplingZipTable, 是 BlockBasedTable 的代替品,性能更高而内存占用更低。ToplingZipTable 应用 CO-Index 与 PA-Zip 实现索引和数据的存储。CO-Index 指 Compressed Ordered Index, 是一类内存压缩的索引,无需解压,在压缩的状态下能够对索引间接搜寻,并且搜寻速度极快。从 String 类型的 Key,搜寻出一个密实 的 整数 ID。PA-Zip 指 Point Accessible Zip, 无需 BlockCache,能够十分疾速地 按 ID 定点拜访单条数据。PA-Zip 也有非压缩的实现,例如 MyTopling(MySQL) 中长度固定且单条数据较短的表,用一个定长数组就能够十分高效地实现。在这种状况下,是能够实现 zero copy 的,但 RocksDB 中有一些问题导致无奈 zero copy。ToplingZipTable 间接应用 topling-zip 中的 BlobStore 类体系来实现 PA-Zip。2. RocksDB 为什么不能 zero copy2.1. SuperVersion 保活传统上,个别通过援用计数来标记对象的存活,然而多线程援用计数会导致 CPU 核间的频繁通信,导致多核不 Scale。所以 RocksDB 在DB::Get 中,应用了一些技巧,防止了频繁的增减援用计数:对象实例级的 ThreadLocalPtr,每个线程援用一个 SuperVersion 对象,短暂放弃援用计数对于一个 DB 的只读操作:在操作开始处,取出该线程 TLS 的 SuperVersion 指针并将 TLS 指针设为 InUse,取出的 TLS 指针放到该函数的局部变量中,其它线程就察看不到这个 SuperVersion 了在操作完结处,将保留在函数局部变量中的 SuperVersion 指针放回线程 TLS,其它线程就能够察看到这个 SuperVersion 了任何线程创立新的 SuperVersion 对象时(例如Flush/Compact完结时),查看所有线程的 TLS,回收不在 InUse 状态的 SuperVersion,回收后相应 TLS 设为 null,这样当那个 TLS 所属的线程应用它时,发现是 null,就从全局获取最新的 SuperVersion对 TLS 的操作均应用 atomic以这样的形式,SuperVersion 的保活就不须要每个操作都增减援用计数了,从而实现多核线性 Scale。2.2. PinnableSlice最高效的DB::Get 重载版本是 value 为 PinnableSlice 的那个,对于 BlockBasedTable,PinnableSlice 会 Pin 住 BlockCache 中相应的 Block,防止了从 BlockCache 中把 value memcpy 到 std::string 中。PinnableSlice 反对可插拔的 Cleanable 接口,BlockCache 内存的回收就是通过这个 Cleanable 接口实现的。BlockCache 的生存期和 SuperVersion 是互相独立的,所以 PinnableSlice 在这里能够失常工作。2.3. mmap对于应用 mmap 的 SST,因为有 PinnableSlice,所以实践上,咱们能够把 mmap 中存储 value 的内存间接通过指针返回给用户代码。然而问题就出在这里,SST 是(间接)绑定到 SuperVersion 的,要让用户代码拜访 SST 的 mmap,那在用户代码拜访 value 期间就必须保活相应的 SuperVersion。从 DB::Get 返回时,SuperVersion 就放回 TLS 了,从而可能被其它线程回收,用户代码就不能平安地拜访从属于那个 SuperVersion 的 SST 的 mmapRocksDB 本身的 PlainTable 就应用了 mmap,面对这个问题,PlainTable 偷了个懒,只有在 immortal 的状况下,才把 mmap 内存间接返回给用户代码。什么状况下是 immortal 呢?应用了 DB::OpenForReadOnly 的状况下。这个限度就过于刻薄,实际中很难满足!3. ToplingDB 的解决方案首先,咱们绝不能为了 Zero Copy 而毁坏 API 兼容性,必须利用现有的 API 实现 Zero Copy。咱们在 ReadOptions 下面做文章,给 ReadOptions 减少两个办法 StartPin/FinishPin,pin 的对象是 super version:如果想要获取 zero copy 的收益,就在调用 Get 前 StartPin,应用完 Get 回来的 value 之后 FinishPin如果不想改代码,就只是没有 zero copy,所有跟从前一样用户须要关怀的扭转:diff --git a/include/rocksdb/options.h b/include/rocksdb/options.h--- a/include/rocksdb/options.h+++ b/include/rocksdb/options.h@@ -1735,6 +1735,13 @@ struct ReadOptions {std::shared_ptr<struct ReadOptionsTLS> pinning_tls = nullptr;+// pin SuperVersion to enable zero copy on mmap SSTvoid StartPin();void FinishPin();+~ReadOptions();ReadOptions();ReadOptions(bool cksum, bool cache); };实现细节都在 ReadOptionsTLS 中,求知欲强的用户能够看一下具体实现。当然,相应地,SST 的实现局部也要为此做一点适配。咱们给 PlainTable 做了相应的适配,批改少到不堪设想。pinner 设为一个默认结构的 Cleanable,就是指不须要对 value 深拷贝, value 指向的内存也不须要做任何清理工作;pinner 设为 null 时,会对 value 做深拷贝这个批改还带来一个额定收益:当要一一 Get 多条数据时,只须要一次 StartPin/FinishPin,而 StartPin 时会将 SuperVersion 指针放到 ReadOptionsTLS 中,通过 pinning_tls 获取 SuperVersion 防止了绝对低廉的 ThreadLocalPtr 拜访,每次 Get 节俭了大概 30 纳秒。4. db_bench 适配咱们给 db_bench 减少了一个选项 -enable_zero_copy,开启这个选项,Get 就会应用 StartPin/FinishPin 以应用 zero copy。4.1. ToplingZipTable Zero Copy在阿里云 Xeon 8369HB 的云主机上,咱们测进去这样的性能(-key_size=8 -value_size=20):readrandom: 0.234 micros/op 4279978 ops/sec 23.365 seconds 100000000 operations; 114.3 MB/s (100000000 of 100000000 found)Compact 之后,单个 Get 操作 234 纳秒,这其中,DB::Get 占了 83%,约合 194 纳秒,db_bench 驱动代码占 17%,真正干活的 ToplingZipTable::Get 只占了 18%,合 42 纳秒:仅 Flush 之后,不 Compact,单个 Get 操作 254 纳秒,比 234 略微慢一点readrandom: 0.254 micros/op 3939416 ops/sec 25.384 seconds 100000000 operations; 105.2 MB/s (100000000 of 100000000 found)测试过程参考 这里,记得增加命令行参数 -enable_zero_copy=true ,同时,对 db_bench_enterprise.yaml 做小幅批改。--- a/sample-conf/db_bench_enterprise.yaml+++ b/sample-conf/db_bench_enterprise.yaml@@ -119,16 +119,16 @@ CFOptions:default: max_write_buffer_number: 4 memtable_factory: "${cspp}"write_buffer_size: 8Mwrite_buffer_size: 128M # set target_file_size_base as small as 512K is to make many SST files, # thus key prefix cache can present efficiency # 把 target_file_size_base 设得很小是为了产生很多文件,从而体现 key prefix cache 的成果target_file_size_base: 512Ktarget_file_size_base: 64M target_file_size_multiplier: 1 table_factory: dispatch compaction_options_level: ...

September 22, 2023 · 3 min · jiezi

关于后端:Flink-Batch-SQL-Improvements-on-Lakehouse

本文整顿自阿里云研发工程师刘大龙(风离),在 Streaming Lakehouse Meetup 的分享。内容次要分为三个局部: Flink Batch on Paimon 挑战Flink Batch 外围优化后续布局点击查看原文视频 & 演讲PPT 一、Flink Batch on Paimon 挑战家喻户晓,Paimon 在创建之初就是为了解决流式数仓场景的问题。从上面的架构图里咱们能够看到,这里有 Flink CDC 的高效入湖,Flink SQL 进行流式、批式的 ETL、Ad-hoc 剖析,用一套引擎实现数据的入湖、剖析与查问,整个架构上十分简洁,语义对立,解决了传统 lambda 架构下实时离线的数据一致性问题。 Flink 作为一个流批一体的计算引擎,天生就具备上述能力。 作为流计算引擎,Flink 曾经是业界的事实标准;在批处理畛域,Spark 是业界的事实标准,Flink Batch 尽管整体能力上不差,然而如果想在数据湖剖析场景占据一席之地,的确还面临一些挑战。针对 Flink + Paimon 构建流式数仓场景的需要,咱们对 Flink Batch 可能存在的问题进行了总结,次要有如下几个方面: Flink 如果作为一个流计算引擎,对于 Schema 变更是没有强需要的,然而和存储联合之后,就须要不断完善这类 API,补齐相干能力;在数据湖场景,会存在行级的数据更新、删除等需要;个别湖上的数据都是有版本的,每次的写入与更新,可能都会产生一个新的 Snapshot,因而咱们也须要对 Sanpshot 进行治理,比方通过 CALL 命令清理过期 Snapshot,工夫旅行查问;除了数据管理方面的需要,另外一个重要的挑战就是如何通过 Flink Batch 对湖上数据进行高效的 ETL&Ad-hoc 剖析,同时还要保障稳定性。针对这些挑战,从 1.16 版本社区开始投入大量精力对 Flink Batch 做了诸多方面的优化。 二、Flink Batch 外围优化在介绍 Flink Batch 外围优化之前,首先咱们按版本主线回顾一下过来三个版本别离做了哪些重要的性能。 ...

September 22, 2023 · 4 min · jiezi

关于后端:树形-DP如何从方向角度理解树形-DP

题目形容这是 LeetCode 上的 834. 树中距离之和 ,难度为 艰难。 Tag : 「树形 DP」、「DFS」、「动静布局」、「树」 给定一个无向、连通的树。 树中有 n 个标记为 0...n-1 的节点以及 n-1 条边 。 给定整数 n 和数组 edges, $edges[i] = [a_{i}, b_{i}]$示意树中的节点 $a_{i}$ 和 $b_{i}$ 之间有一条边。 返回长度为 n 的数组 answer,其中 answer[i] 是树中第 i 个节点与所有其余节点之间的间隔之和。 示例 1: 输出: n = 6, edges = [[0,1],[0,2],[2,3],[2,4],[2,5]]输入: [8,12,6,10,10,10]解释: 树如图所示。咱们能够计算出 dist(0,1) + dist(0,2) + dist(0,3) + dist(0,4) + dist(0,5) 也就是 1 + 1 + 2 + 2 + 2 = 8。 因而,answer[0] = 8,以此类推。示例 2: ...

September 22, 2023 · 3 min · jiezi

关于后端:Python-内置数据类型详解

内置数据类型在编程中,数据类型是一个重要的概念。 变量能够存储不同类型的数据,不同类型能够执行不同的操作。 Python默认内置了以下这些数据类型,分为以下几类: 文本类型:str 数值类型:int、float、complex 序列类型:list、tuple、range 映射类型:dict 汇合类型:set、frozenset 布尔类型:bool 二进制类型:bytes、bytearray、memoryview 空类型:NoneType 获取数据类型您能够应用type()函数获取任何对象的数据类型: 示例:获取您本人的Python服务器 打印变量x的数据类型: x = 5print(type(x))设置数据类型在Python中,当您为变量赋值时,数据类型就确定了: 示例 数据类型 试一试 x = "Hello World" str x = 20 int x = 20.5 float x = 1j complex x = ["apple", "banana", "cherry"] list x = ("apple", "banana", "cherry") tuple x = range(6) range x = {"name" : "John", "age" : 36} dict x = {"apple", "banana", "cherry"} set x = frozenset({"apple", "banana", "cherry"}) frozenset x = True bool x = b"Hello" bytes x = bytearray(5) bytearray x = memoryview(bytes(5)) memoryview x = None NoneType 设置特定的数据类型如果您想要指定数据类型,能够应用以下构造函数: ...

September 21, 2023 · 1 min · jiezi

关于后端:听GPT-讲Istio源代码pkg2

File: istio/pkg/bootstrap/platform/aws.goaws.go文件是Istio我的项目中的一个文件,次要用来获取与Amazon Web Services (AWS) 平台相干的信息和元数据。它定义了用于与AWS平台进行通信和获取相干信息的函数和变量。 awsMetadataIPv4URL和awsMetadataIPv6URL是用来获取AWS平台IPv4和IPv6元数据的URL地址。awsMetadataTokenIPv4URL和awsMetadataTokenIPv6URL是用来获取蕴含拜访AWS平台元数据所需的长期凭证的URL地址。awsEnv是一个构造体,用于存储与AWS平台相干的环境变量。上面是aws.go文件中的一些重要函数和它们的作用: IsAWS()函数用于查看以后环境是否为AWS平台。NewAWS()函数用于创立一个新的AWS平台对象。requestHeaders()函数用于生成发送申请时所需的HTTP申请头部。Metadata()函数用于获取与AWS平台相干的元数据信息。Locality()函数用于获取以后AWS实例所在的地区信息。Labels()函数用于获取与AWS实例相干的标签信息。IsKubernetes()函数用于查看以后环境是否为AWS上的Kubernetes集群。getAWSInfo()函数用于获取与AWS平台相干的信息。getRegion()函数用于获取以后AWS实例所在的区域信息。getAvailabilityZone()函数用于获取以后AWS实例所在的可用区信息。getInstanceID()函数用于获取以后AWS实例的ID。getToken()函数用于获取拜访AWS平台元数据所需的长期凭证。这些函数和变量的目标是为了不便从AWS平台获取相干信息,以帮忙Istio在AWS环境中失常运行和提供一些与AWS平台相干的性能。 File: istio/pkg/bootstrap/option/instances.go在istio我的项目中,istio/pkg/bootstrap/option/instances.go文件的作用是定义了一系列的选项构造体,用于配置Istio代理的各种参数。 LocalhostValue构造体用于配置本地主机的参数,包含IP地址和端口。HistogramMatch构造体用于配置直方图匹配规定,能够用于流量治理和故障复原。HistogramBucket构造体用于配置直方图的统计桶。以下是其余构造体和相干的选项参数: ProxyConfig用于配置代理的各种参数,如上游集群、管制立体地址等。PilotSubjectAltName用于配置Pilot的证书地址。ConnectTimeout用于配置代理连贯超时工夫。Cluster用于配置代理集群的参数。NodeID用于配置代理节点的惟一标识。NodeType用于配置代理节点的类型。XdsType用于配置XDS协定类型。Region用于配置代理节点所在的地区。Zone用于配置代理节点所在的区域。SubZone用于配置代理节点所在的子区域。NodeMetadata用于配置代理节点的元数据。RuntimeFlags用于配置运行时标记位。DiscoveryAddress用于配置发现服务的地址。XDSRootCert用于配置XDS根证书。Localhost用于配置本地主机地址。Wildcard用于配置通配符。DNSLookupFamily用于配置DNS查找的家族类型。OutlierLogPath用于配置异常情况的日志门路。LightstepAddress用于配置Lightstep的地址。LightstepToken用于配置Lightstep的拜访令牌。OpenCensusAgentAddress用于配置OpenCensus代理的地址。OpenCensusAgentContexts用于配置OpenCensus代理的上下文。StackDriverEnabled用于配置是否启用StackDriver。StackDriverProjectID用于配置StackDriver的我的项目ID。StackDriverDebug用于配置StackDriver的调试模式。StackDriverMaxAnnotations用于配置StackDriver的最大正文数量。StackDriverMaxAttributes用于配置StackDriver的最大属性数量。StackDriverMaxEvents用于配置StackDriver的最大事件数量。PilotGRPCAddress用于配置Pilot的gRPC地址。ZipkinAddress用于配置Zipkin的地址。DataDogAddress用于配置DataDog的地址。StatsdAddress用于配置Statsd的地址。TracingTLS用于配置跟踪的TLS选项。EnvoyMetricsServiceAddress用于配置Envoy指标服务的地址。EnvoyMetricsServiceTLS用于配置Envoy指标服务的TLS选项。EnvoyMetricsServiceTCPKeepalive用于配置Envoy指标服务的TCP放弃活动状态。EnvoyAccessLogServiceAddress用于配置Envoy拜访日志服务的地址。EnvoyAccessLogServiceTLS用于配置Envoy拜访日志服务的TLS选项。EnvoyAccessLogServiceTCPKeepalive用于配置Envoy拜访日志服务的TCP放弃活动状态。EnvoyExtraStatTags用于配置Envoy额定的统计标签。EnvoyStatsMatcherInclusionPrefix用于配置Envoy统计匹配的前缀。EnvoyStatsMatcherInclusionSuffix用于配置Envoy统计匹配的后缀。EnvoyStatsMatcherInclusionRegexp用于配置Envoy统计匹配的正则表达式。EnvoyStatusPort用于配置Envoy的状态端口。EnvoyPrometheusPort用于配置Envoy的Prometheus端口。STSPort用于配置STS的端口。GCPProjectID用于配置GCP我的项目ID。GCPProjectNumber用于配置GCP项目编号。Metadata用于配置元数据。STSEnabled用于配置是否启用STS。DiscoveryHost用于配置发现主机的地址。MetadataDiscovery用于配置元数据发现的选项。LoadStatsConfigJSONStr用于配置加载统计配置的JSON字符串。EnvoyHistogramBuckets用于配置Envoy直方图的统计桶。这些选项参数通过对应的函数提供获取或设置其值的性能,以便在运行时动静地配置istio代理的各个属性。 File: istio/pkg/bootstrap/option/convert.go在istio我的项目中,istio/pkg/bootstrap/option/convert.go文件的作用是为了将配置文件的内容转换为对应的数据结构,以便在Istio的启动过程中应用。 具体来说,该文件中的TransportSocket构造体定义了一系列的转换器用于将配置文件中的TransportSocket配置项,转换成各种类型的TransportSocket对象,比方tls, tls_passthrough, tcp, http, metadata等。这些配置项用于指定Istio流量治理中的网络传输方式和平安强制性。 以下是上述提到的几个构造体和函数的作用: keepaliveConverter:将配置文件中的Keepalive配置转换为对应的Keepalive对象,用于管制网络连接的放弃活动状态。transportSocketConverter:依据配置文件中的TransportSocket配置项,转换成对应的TransportSocket对象,用于指定Istio中的网络传输方式。tlsContextConvert:将配置文件中的TLS配置转换为对应的TLSContext对象,用于指定Istio中的TLS配置。nodeMetadataConverter:将配置文件中的节点元数据转换为对应的节点元数据对象,用于依据节点信息筛选流量。sanConverter:将配置文件中的SAN配置转换为对应的SAN对象,用于指定Istio中的Subject Alternative Name设置。addressConverter:将配置文件中的网络地址字符串转换为对应的网络地址对象。jsonConverter:将配置文件中的JSON字符串转换为对应的JSON对象。durationConverter:将配置文件中的工夫距离字符串转换为对应的Duration对象。openCensusAgentContextConverter:将配置文件中的OpenCensus配置转换为对应的OpenCensusAgentContext对象。convertToJSON:将给定的对象转换为JSON字符串。marshalMetadata:将给定的元数据对象转换为对应的元数据字符串。这些函数和转换器的目标是为了实现Istio配置项的解析和转换,确保配置文件中的内容能够正确地映射到Istio的数据结构中,以便Istio可能正确地进行网络传输和流量管制。 File: istio/pkg/slices/slices.go在Istio我的项目中,slices.go文件位于istio/pkg/slices/目录中,它是一个蕴含了各种在Slice(切片)操作上的辅助函数的工具库。 上面是对各个函数的具体介绍: Equal(a, b interface{}) bool: 用于比拟两个切片是否相等。EqualFunc(a, b interface{}, equals func(a, b interface{}) bool) bool: 应用自定义的相等函数比拟两个切片是否相等。SortFunc(slicePtr interface{}, compare func(a, b int) bool): 应用自定义的比拟函数对切片进行排序。Sort(slicePtr interface{}): 对切片进行排序,应用默认的比拟函数。Clone(slicePtr interface{}) interface{}: 克隆一个新的切片。Delete(slicePtr interface{}, index int) interface{}: 在切片中删除指定索引地位的元素,并返回新的切片。Contains(slicePtr interface{}, elem interface{}) bool: 查看切片中是否蕴含指定的元素。FindFunc(slicePtr interface{}, elem interface{}, equals func(a, b interface{}) bool) int: 应用自定义的相等函数查找切片中指定元素的索引。Reverse(slicePtr interface{}): 反转切片中的元素。FilterInPlace(sliceInPtr, sliceOutPtr interface{}, keep func(int, interface{}) bool): 应用给定的过滤函数过滤原切片,并将过滤后果保留到新的切片中。Filter(sliceInPtr interface{}, keep func(int, interface{}) bool) interface{}: 应用给定的过滤函数过滤原切片,并返回过滤后果的新切片。Map(sliceInPtr, sliceOutPtr interface{}, mapper func(int, interface{}) interface{}): 应用给定的映射函数对切片中的元素进行映射,并将后果保留到新的切片中。MapFilter(sliceInPtr, sliceOutPtr interface{}, mapper func(int, interface{}) (interface{}, bool)): 将映射函数利用到切片的每个元素上,并依据返回的布尔值来决定是否保留该元素,并将后果保留到新的切片中。Reference(slicePtr interface{}) *[]interface{}: 返回切片的援用。Dereference(sliceRef *[]interface{}) interface{}: 解援用切片的援用,并返回切片。Flatten(slicePtr interface{}) interface{}: 将多维切片扁平化为一维切片。这些函数提供了对切片进行常见操作的简洁和不便的形式,使得开发人员能够更容易地解决和操作切片。 ...

September 21, 2023 · 2 min · jiezi

关于后端:听GPT-讲Istio源代码pkg1

File: istio/pkg/jwt/routing.go在Istio我的项目中,istio/pkg/jwt/routing.go文件的作用是定义了用于JWT(JSON Web Token)路由的相干构造体和函数。 Separator 构造体代表JWT主题中多个值之间的分隔符。它用于将JWT主题的多个值宰割为单个路由规定。RoutingClaim 构造体代表用于路由的JWT申明。它蕴含了申明的名称和可选的分隔符。这些申明用于提取JWT中的特定信息,以便用于构建路由规定。ToRoutingClaims 是一个函数,用于将JWT申明转换为路由申明。它承受一个字符串切片,代表JWT申明的配置,并将其解析为对应的 RoutingClaim 构造体的切片。ToRoutingMap 是一个函数,用于将JWT申明映射到路由规定。它承受一个字符串切片和一个用于路由规定的字符串,将JWT申明解析为 RoutingClaim 构造体,并返回用于路由规定的映射。这些构造体和函数的作用是为了反对基于JWT的路由规定。JWT是一种用于身份验证和受权的平安传输协定,它将信息编码为JSON格局并应用签名进行验证。通过解析JWT中的申明,能够将其用于构建路由规定,从而实现基于身份验证信息的申请路由。这在Istio中能够用于实现基于用户身份的灰度公布、A/B测试等性能。 File: istio/pkg/jwt/jwt.go在Istio我的项目中,pkg/jwt/jwt.go文件的作用是实现JWT(JSON Web Tokens)解决的相干性能。 该文件定义了几个构造体和函数来解决JWT相干的操作。上面对其中的构造体和函数进行具体介绍: JwksFetchMode构造体:用于定义JWT验证期间公钥(keys)的获取形式。JwksFetchMode是一个整数类型,定义了几种不同的获取形式。上面是几种不同的获取形式: JwksFromURL:从URL获取公钥JwksFromConfigMap:从Kubernetes中的ConfigMap获取公钥JwksFromFile:从文件获取公钥JwksFromSecret:从Kubernetes中的Secret获取公钥String函数:用于将JwksFetchMode转化为字符串示意。该函数接管一个JwksFetchMode类型的参数,并返回对应的字符串示意。ConvertToJwksFetchMode函数:用于将字符串示意的JwksFetchMode转化为相应的整数值。该函数接管一个字符串类型的参数,并返回对应的JwksFetchMode整数值。这些构造体和函数的作用是为了在Istio中解决JWT验证时,提供灵便的公钥获取形式。JwksFetchMode定义了几种常见的获取形式,而String和ConvertToJwksFetchMode函数则用于实现获取形式的转换和解决。 File: istio/pkg/ctrlz/ctrlz.go在Istio我的项目中,ctrlz.go文件的作用是实现Istio的管制立体的Ctrl-Z性能,该性能使得用户能够通过向管制立体的特定端口发送SIGUSR2信号,在管制立体上获取各种信息和状态。 以下是对每个要害变量和函数的具体介绍: 变量: coreTopics:存储了一组外围主题,用于监控和收集Istio管制立体的外围信息。allTopics:存储了一组所有的主题,用于监控和收集Istio管制立体的信息。topicMutex:用于爱护coreTopics和allTopics的互斥锁。listeningTestProbe:标记是否正在侦听测试探针的UDP包。构造体: Server:定义了一个Ctrl-Z Server,用于接管SIGUSR2信号并解决申请。topic:定义了一个主题的构造体,用于存储主题的相干信息。函数: augmentLayout:从其余源中获取布局,并增加到以后的布局中,以加强最终的日志布局。registerTopic:注册主题,将主题增加到allTopics中,并返回主题的惟一标识符。getLocalIP:获取本地IP地址。getTopics:获取已注册的主题列表。normalize:规范化日志布局文本。RegisterTopic:注册主题的内部接口,对外提供注册主题性能。Run:启动Ctrl-Z服务器,开始监听SIGUSR2信号。listen:监听指定的本地地址,并期待Ctrl-Z信号。Close:敞开Ctrl-Z服务器,进行监听。Address:返回以后正在监听的本地地址。通过应用这些函数,能够在Istio管制立体上注册和治理各种主题,用于监控和收集不同层面的信息(外围主题或全副主题)。而后,通过监听SIGUSR2信号并解决申请,能够提供Ctrl-Z性能,使用户可能获取所需的信息和状态。 File: istio/pkg/ctrlz/home.go文件istio/pkg/ctrlz/home.go是Istio我的项目中的一个文件,次要用于实现Istio的控制面板性能。上面具体介绍该文件的相干内容: mimeTypes:这是一个字符串切片,蕴含了一些常见的MIME类型。MIME类型是用于标识文件内容类型的一种机制,能够用于批示浏览器如何解决来自服务器的文件。homeInfo:这是一个构造体,用于存储控制面板主页的相干信息。它蕴含以下字段: Title:控制面板主页的题目。Description:控制面板主页的形容信息。Sections:控制面板主页的各个局部,是一个字符串切片。getHomeInfo函数:这个函数是用于获取控制面板主页的相干信息。在函数外部,它创立一个homeInfo构造体实例,并设置相应的字段值。最初将该构造体实例返回。registerHome函数:这个函数是用于向控制面板注册主页信息的。在函数外部,它调用了getHomeInfo函数获取控制面板主页的信息,并将该信息注册到控制面板的门路上。总结一下,istio/pkg/ctrlz/home.go文件次要实现了Istio控制面板的首页性能,通过getHomeInfo函数获取主页信息,而后通过registerHome函数将该信息注册到控制面板门路上。 心愿这可能具体解答您的问题。 File: istio/pkg/ctrlz/topics/assets/assets.go在Istio我的项目中,istio/pkg/ctrlz/topics/assets/assets.go文件的作用是为Istio的管制立体提供动态文件资源。 具体介绍如下: assets.go文件定义了一些常量和函数,用于拜访和解决Istio管制立体中的动态文件资源。这些动态文件资源包含Web页面、JavaScript、CSS文件等,用于构建Istio管制立体中的用户界面。 在该文件中,有以下几个比拟重要的局部: FS变量:FS是一个http.FileSystem类型的变量,示意Istio管制立体中的动态文件系统。它应用了go-bindata工具将动态资源文件编译为可执行文件中的嵌入式数据。FS变量通过调用bindataFS()函数初始化,该函数返回一个文件系统对象,该对象蕴含了编译的动态资源。ParseTemplate函数:ParseTemplate函数用于解析和执行动态资源文件中的Go模板。它承受一个模板名称和一个可选的参数,并返回一个解析后的模板对象。具体作用是对指定的动态资源文件中的Go模板进行解析,并将解析后果返回。 ParseTemplateToString函数:应用ParseTemplate函数将模板解析为字符串格局。ParseTemplateToBytes函数:应用ParseTemplate函数将模板解析为字节切片格局。ExecuteTemplateToString函数:应用解析后的模板对象,将其参数转化为字符串格局。ExecuteTemplateToBytes函数:应用解析后的模板对象,将其参数转化为字节切片格局。这些函数与模板相干,能够对动态资源中的模板进行解析和执行,以生成最终的内容。 总结:istio/pkg/ctrlz/topics/assets/assets.go文件的作用是为Istio管制立体提供动态文件资源,并提供了一些函数来解析和执行这些动态资源中的模板。FS变量是用于拜访动态资源的文件系统对象,并通过ParseTemplate函数来解析和执行动态资源中的Go模板。 File: istio/pkg/ctrlz/topics/mem.go在Istio我的项目中,istio/pkg/ctrlz/topics/mem.go文件的作用是定义了一些内存统计相干的话题以及操作函数。 该文件中定义了几个构造体,包含MemTopic、Title、Prefix。 MemTopic 构造体示意内存统计的话题,蕴含了话题名称以及相应的统计数据。Title 构造体代表一个话题的题目,用于在输入中显示。Prefix 构造体示意话题的前缀,用于辨别不同的话题。此外,文件中还定义了一些用于操作话题的函数。 Activate 函数用于激活指定的内存统计话题。它承受一个话题名称作为参数,并更新内存统计数据。MemTopic 函数用于获取指定话题的内存统计数据。它承受一个话题名称作为参数,并返回相应的统计数据。Title 函数用于依据给定的前缀获取一个或多个内存统计话题的题目。它承受一个前缀作为参数,并返回符合条件的话题题目列表。总之,istio/pkg/ctrlz/topics/mem.go 文件定义了一些话题以及操作函数,用于收集和显示内存统计数据。它提供了一种不便的形式来监控和治理Istio我的项目中的内存应用状况。 File: istio/pkg/ctrlz/topics/signals.go在Istio我的项目中,istio/pkg/ctrlz/topics/signals.go文件的作用是定义了用于解决信号的主题相干的逻辑。 这个文件中定义了一个名为signalsTopic的构造体,该构造体蕴含了以下几个字段和办法: Title字段:示意信号主题的题目,用于在打印信号主题时进行标识。Prefix字段:示意信号主题的前缀,用于在打印信号主题时进行标识。Activate办法:用于激活信号主题,并将信号告诉的函数注册到相应的信号中。ServeHTTP办法:用于解决HTTP申请,从而触发相应的信号逻辑。printSignals办法:用于打印信号的详细信息。SignalsTopic构造体示意一个信号主题,它蕴含了一个name字段,示意该主题的名称。 Title函数返回信号主题的题目。 Prefix函数返回信号主题的前缀。 Activate函数用于激活信号主题,并将信号告诉函数注册到相应的信号中。 综上所述,signals.go文件的作用是定义了用于解决信号的主题相干的逻辑,包含信号主题的定义、激活以及解决信号告诉的函数等。这些逻辑能够用于实现在Istio运行时中解决和管理系统信号的性能。 File: istio/pkg/ctrlz/topics/collection.go在Istio我的项目中,collection.go文件位于istio/pkg/ctrlz/topics目录下,它的作用是定义与汇合(collection)相干的主题(topics)和函数。 上面是对一些要害变量和构造体的具体解释: _:在Go语言中,下划线 _用来示意一个变量被申明但未被应用。在这个文件中,下划线用于疏忽某些变量,避免编译器收回未应用的正告。ReadableCollection:一个接口类型,示意可读的汇合。collectionTopic:一个构造体类型,示意汇合主题。它蕴含以下字段: collections:可读汇合的列表。prefix:汇合主题的前缀。activate:激活汇合主题的函数。mainContext、listContext、itemContext:这些构造体类型用于示意上下文信息。staticCollection:一个构造体类型,示意动态汇合。它蕴含以下字段: name:汇合的名称。keys:汇合的键列表。get:获取汇合的函数。在这个文件中还定义了一些函数: Title:返回汇合的题目。Prefix:返回汇合主题的前缀。Activate:激活汇合主题的函数。handleMain、handleCollection、handleItem、handleError:这些函数用于解决汇合主题的不同事件。listCollection:获取汇合的列表。getItem:获取汇合中的特定项。NewCollectionTopic:创立一个新的汇合主题。NewStaticCollection:创立一个新的动态汇合。Name:返回汇合的名称。Keys:返回汇合的键列表。Get:获取汇合中的特定项。这些函数的作用不仅包含汇合操作,还波及汇合主题的创立、解决和事件回调等性能。它们容许在Istio中以一种对立的形式治理和操作汇合。 ...

September 21, 2023 · 2 min · jiezi

关于后端:Mac使用szrz

从应用体验上说,sz/rz要比scp要好得多.但Mac上应用这两个命令须要进行相应配置. <font size=1>sz:将选定的文件发送(send)到本地机器 rz:运行该命令会弹出一个文件抉择窗口,从本地抉择文件上传到Linux服务器</font> 下载安装lrzsz brew install lrzsz 留神设置软链接时,要和以后brew装置的sz/rz的版本统一 ln -s /usr/local/Cellar/lrzsz/你所装置的版本/bin/szln -s /usr/local/Cellar/lrzsz/你所装置的版本/bin/rz留神: 新版本homebrew的装置门路为/opt/homebrew/Cellar/,不再是/usr/local/Cellar/,以上目录需相应批改如下: ln -s /opt/homebrew/Cellar/lrzsz/你所装置的版本/bin/szln -s /opt/homebrew/Cellar/lrzsz/你所装置的版本/bin/rz 下载并装置automatic zmoderm for iTerm2配置automatic zmoderm for iTerm2 cd /usr/local/bin 新建两个脚本,iterm2-recv-zmodem.sh和iterm2-send-zmodem.sh 内容如下: iterm2-recv-zmodem.sh: #!/bin/bash# 这个脚本来自 github,删掉了一些 ** 舆论。osascript -e 'tell application "iTerm2" to version' > /dev/null 2>&1 && NAME=iTerm2 || NAME=iTermif [[ $NAME = "iTerm" ]]; then FILE=$(osascript -e 'tell application "iTerm" to activate' -e 'tell application "iTerm" to set thefile to choose folder with prompt "Choose a folder to place received files in"' -e "do shell script (\"echo \"&(quoted form of POSIX path of thefile as Unicode text)&\"\")")else FILE=$(osascript -e 'tell application "iTerm2" to activate' -e 'tell application "iTerm2" to set thefile to choose folder with prompt "Choose a folder to place received files in"' -e "do shell script (\"echo \"&(quoted form of POSIX path of thefile as Unicode text)&\"\")")fiif [[ $FILE = "" ]]; then echo Cancelled. # Send ZModem cancel echo -e \\x18\\x18\\x18\\x18\\x18 sleep 1 echo echo \# Cancelled transferelse cd "$FILE" /usr/local/bin/rz -E -e -b --bufsize 4096 sleep 1 echo echo echo \# Sent \-\> $FILEfi ...

September 21, 2023 · 2 min · jiezi

关于后端:搭建GraphQL服务

js版 GraphQL在 NodeJS 服务端中应用最多 装置graphql-yoga: npm install graphql-yoga 新建index.js: const {GraphQLServer} = require("graphql-yoga")const server = new GraphQLServer({ typeDefs: ` type Query { hello(name:String):String! } `, resolvers: { Query: { hello: (parent, {name}, ctx) => { return `${name},你好!`; } } }})server.start({ port: 4600}, ({port}) => { console.log(`服务器已启动,请拜访: http://localhost:${port}`);}) node index.js 运行 点击链接 进入playground: query{ hello(name:"dashen")} 参考自 5分钟疾速搭建一个Graphql服务器 Golang版 入门教程 Go罕用的GraphQL服务端库 graphql-go/graphql我的项目的demo: (文档点此) package mainimport ( "encoding/json" "fmt" "log" "github.com/graphql-go/graphql")func main() { // Schema fields := graphql.Fields{ "hello": &graphql.Field{ Type: graphql.String, Resolve: func(p graphql.ResolveParams) (interface{}, error) { return "world", nil }, }, } rootQuery := graphql.ObjectConfig{Name: "RootQuery", Fields: fields} schemaConfig := graphql.SchemaConfig{Query: graphql.NewObject(rootQuery)} schema, err := graphql.NewSchema(schemaConfig) if err != nil { log.Fatalf("failed to create new schema, error: %v", err) } // Query query := ` { hello } ` params := graphql.Params{Schema: schema, RequestString: query} r := graphql.Do(params) if len(r.Errors) > 0 { log.Fatalf("failed to execute graphql operation, errors: %+v", r.Errors) } rJSON, _ := json.Marshal(r) fmt.Printf("%s \n", rJSON) // {"data":{"hello":"world"}}}执行输入 ...

September 21, 2023 · 1 min · jiezi

关于后端:小试GraphQL

之前做的需要,根本都是REST格调,以github提供的api为例,比拟二者差别。试用GraphQL,找寻其独到之处 <h3 align="center"> <font color="orange">REST</font></h3> REST 一个URI代表一种资源通过HTTP动词对资源进行操作 以创立一个仓库为例 GET, PATCH和DELETE相似 <h3 align="center"><font color="orange">GraphQL</font></h3> GraphQL的endpoint只有一个所有申请都是POST 能够在 Exploer右边写查问,左边显示后果。 查问以后登录的用户名: 查问Go我的项目以后的star数: GraphQL的endpoint只有一个,即 https://api.github.com/graphql 应用Postman: 应用query和mutation来辨别是查问还是批改 <h3 align="center"> <font color="orange">二者区别</font></h3> REST一个URI就是一个资源,GraphQL只有一个URIREST返回所有的内容,response体积较大,GraphQL能够只返回须要的数据,返回值体积小GraphQL是一种语言,有本人的语法和类型零碎 会有谬误提醒~ GraphQL的劣势: 取你所须要的数据,不多也不少           n+1问题 nesting(嵌套查问)            比方想取一个pr的commits、comment、reviews,用REST须要申请四次,而后还须要对返回值进行组装;而用GraphQL则只须要一次申请,拿到的就是须要的数据 资源孤岛 (REST) vs Graph(GraphQL) graphql-voyager 强类型(每一个GraphQL的申请发到服务端之后,服务端都会进行校验,不通过会报错)Migrating from REST to GraphQL 参考: 为什么GraphQL比REST好用? 本文由mdnice多平台公布

September 21, 2023 · 1 min · jiezi

关于后端:SWEN20003-面向对象软件开发

SWEN20003 Object Oriented Software Development Project 2, 2023The University of MelbourneSchool of Computing and Information SystemsSWEN20003 Object Oriented Software DevelopmentProject 2, Semester 2, 2023Released: Friday, 8th September 2023 at 4:30pm AESTProject 2A Due: Wednesday, 20th September 2023 at 4:30pm AESTProject 2B Due: Friday, 13th October 2023 at 4:30pm AEDTPlease read the complete specification before starting on the project, because thereare important instructions through to the end!OverviewIn this project, you will create a music arcade game called ShadowDance in the Java programminglanguage, continuing from your work in Project 1. We will provide a full working solution forProject 1; you may use all or part of it, provided you add a comment explaining where you foundthe code at the top of each file that uses the sample code.This is an individual project. You may discuss it with other students, but all of the implementation must be your own work. By submitting the project you declare that you understandthe University’s policy on academic integrity and are aware of consequences of any infringement,including the use of artificial intelligence.You may use any platform and tools you wish to develop the game, but we recommend using IntelliJIDEA for Java development as this is what we will support in class.Extensions & late submissions: If you need an extension for the project, please complete theExtension form in the Projects module on Canvas. Make sure you explain your situation withsome supporting documentation such as a medical certificate, academic adjustment plan, weddinginvitation, etc. You will receive an email saying if the extension was approved or if we need moreinformation.If you submit late (either with or without an extension), please complete the Late form in theProjects module on Canvas. For both forms, you need to be logged in using your universityaccount. Please do not email any of the teaching team regarding extensions or late submissions.All of this is explained again in more detail at the end of this specification.There are two parts to this project, with different submission dates. The first task, Project2A, requires that you produce a class design demonstrating how you plan to implement the game.This should be submitted in the form of a UML diagram showing all the classes you plan to implement, the relationships (e.g. inheritance and associations) between them, and their attributes,as well as their primary public methods. You do not need to show constructors, getters/setters,dependency, composition or aggregation relationships. If you so choose, you may show the relationship on a separate page to the class members in the interest of neatness, but you must use correctUML notation. Please submit as a PDF file only on Canvas.1SWEN20003 Object Oriented Software Development Project 2, 2023The second task, Project 2B, is to complete the implementation of the game as described in therest of this specification. You do not need to strictly follow your class design from Project 2A;you will likely find ways to improve the design as you implement it. Submission will be via GitLaband you must make at least 5 commits throughout your project.Game Overview‘The aim is simple : the player has to hit the corresponding musical notes that appear on screenin different lanes on time to score points. To win each level, you need to beat a target score. Thesecond level features a special lane that has special notes such as bomb, speed up, slow downand double score. The third level includes enemies who try to steal notes from the lanes and aguardian who will shoot projectiles at these enemies when a key is pressed. Can you beat thetarget scores and win the game?”The game features three levels : Level 1, Level 2 and Level 3. In Level 1, the notes will descend from the top vertically in the 4 lanes. The player has to press the corresponding arrow keywhen the note overlaps with the stationary note symbol at the bottom. The accuracy of how closethe note was to the stationary note when the key was pressed, will determine the points given.There will be hold notes that require the player to hold down the key. To finish the level, theplayer needs to beat the target score of 150 when all the notes have fallen. If the player’s score islower, the game ends. You have already implemented Level 1 in Project 1 (the only change requiredis to the start/end screens which is explained later).Level 2 features the same game-play as above but the player now has to deal with additional featuressuch as a special lane that has special notes. Similar to a normal note, if the corresponding key ispressed for the special note, its effect is applied (this is explained in detail later). To win the level,the player must beat a score of 400.Level 3 is the final level. It includes all of the above as well as extra features such as enemies anda guardian. An enemy moves horizontally and it will steal notes from nearby lanes by collidingwith them. The guardian will shoot projectiles at the nearest enemy when the corresponding keyis pressed. To win the level, the player must beat a score of 350.Note that the game does not need to be played progressively. You can choose which level to playfrom the start screen and also at the end of each level.An Important NoteBefore you attempt the project or ask any questions about it on the discussion forum, it is crucialthat you read through this entire document thoroughly and carefully. We’ve covered every detailbelow as best we can without making the document longer than it needs to be. Thus, if there isany detail about the game you feel was unclear, try referring back to this project spec first, as itcan be easy to miss some things in a document of this size. And if your question is more to do onhow a feature should be implemented, first ask yourself: ‘How can I implement this in a way that2SWEN20003 Object Oriented Software Development Project 2, 2023both satisfies the description given, and helps make the game easy and fun to play?’ Moreoften than not, the answer you come up with will be the answer we would give you!Figure 1: Start Screen Screenshot(a) Completed Level 2 Screenshot (b) Completed Level 3 ScreenshotFigure 2: Level ScreenshotsNote : the actual positions of the entities in the levels we provide you may not be the same as inthese screenshots.3SWEN20003 Object Oriented Software Development Project 2, 2023The Game EngineThe Basic Academic Game Engine Library (Bagel) is a game engine that you will use to developyour game. You can find the documentation for Bagel here.CoordinatesEvery coordinate on the screen is described by an (x, y) pair. (0, 0) represents the top-left of thescreen, and coordinates increase towards the bottom-right. Each of these coordinates is called apixel. The Bagel Point class encapsulates this.FramesBagel will refresh the program’s logic at the same refresh rate as your monitor. Each time, thescreen will be cleared to a blank state and all of the graphics are drawn again. Each of these stepsis called a frame. Every time a frame is to be rendered, the update() method in ShadowDance iscalled. It is in this method that you are expected to update the state of the game.Your code will be marked on 120Hz screens. The refresh rate is now typically 120 times persecond (Hz) but some devices might have a lower rate of 60Hz. In this case, when your game isrunning, it may look different to the demo videos as the constant values in this specification havebeen chosen for a refresh rate of 120Hz. For your convenience, when writing and testing your code,you may change these values to make your game playable (these changes are explained later). Ifyou do change the values, remember to change them back to the original specification valuesbefore submitting, as your code will be marked on 120Hz screens.The LevelsOur game will have three levels, each with elements to implement that are described below.Window and BackgroundThe background (background.png) should be rendered on the screen to completely fill up yourwindow throughout the game (for the start screen and all the levels). The default window sizeshould be 1024 * 768 pixels. The background has already been implemented for you in the skeletonpackage.Start ScreenEach level has the same start screen. The screen has a title message that reads SHADOW DANCEshould be rendered in the font provided in res folder (FSO8BITR.ttf), in size 64. The bottom leftcorner of this message should be located at (220, 250).4SWEN20003 Object Oriented Software Development Project 2, 2023Additionally, an instruction message consisting of 4 lines:SELECT LEVELS WITHNUMBER KEYS1 2 3should be rendered below the title message, in the font provided, in size 24. The bottom left ofthe first line in the message should be calculated as follows: the x-coordinate should be increasedby 100 pixels and the y-coordinate should be increased by 190 pixels.There must be adequate spacing between the 4 lines to ensure readability (you can decide onthe value of this spacing yourself, as long as it’s not small enough that the text overlaps or too bigthat it doesn’t fit within the screen). You can align the lines as you wish.The player chooses which level to play by pressing the corresponding key (1, 2 or 3). Once the levelis over, the player will be re-directed back to the start screen. To help when testing your game,you can allow the player to pause the game whilst in a level (i.e. everything in the window willstop moving) by pressing the Tab key (this is not assessed but will help you when coding!)World FileThe lanes and the notes will be defined in a world file, describing the type and their position ortime of appearance in the window. The world files for each level are level1.csv, level2.csv andlevel3.csv correspondingly. (For 60Hz screens, use the corresponding ‘-60” file, i.e. for Level 1use level1-60.csv). A world file is a comma-separated value (CSV) file with rows in one of thefollowing formats:Lane, type of lane, x-coordinate(or)Type of lane, type of note, frame-numberAn example of a world file:Lane,Special,200Lane,Right,742Down,Normal,776Down,Hold,1357Special,DoubleScore,2370The type of lane refers to either the arrow key which it corresponds to or if it is a special lane,for example: the first entry in the above example is for the lane corresponding to the special lane.The type of note refers to whether the note is normal, a hold note or a special note, and theframe number is the frame in which the note starts appearing on screen. For example, the lastentry in the above example refers to a special note of the double score type that appears from the2370th frame onwards in the special lane.5SWEN20003 Object Oriented Software Development Project 2, 2023You must actually load the files—copying and pasting the data, for example, is not allowed. Youhave been provided with extra world files to test on (test1.csv, test2.csv, test3.csv). Markingwill be conducted on a hidden different CSV file of the same format. Note: You can assumethat there will always be only one special lane in both Levels 2 and 3, and that there will be amaximum of four normal lanes in each level. The number of notes in the CSV may vary however.End ScreenEach level has the same end screen. The end screen has two messages - a win/loss message andan instruction message.When all the notes in the CSV file have fallen, if the player’s score is higher than the target scorefor that level, this is considered as a win. Hence, the first message is a winning message that readsCLEAR! The x-coordinate of this message should be centered horizontally and the y-coordinate is ...

September 21, 2023 · 26 min · jiezi

关于后端:面试题精讲如何将二进制转为十六进制

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 系列文章地址 /** * 二进制转换为十六进制 * 这里次要用于解决图片数据,因为数据库存储了图片的Base64编码 */private String bytesToHexString(byte[] bytes) { StringBuilder hexString = new StringBuilder(); for (byte b : bytes) { String hex = Integer.toHexString(0xff & b); if (hex.length() == 1) { hexString.append('0'); } hexString.append(hex); } return hexString.toString();}这个办法承受一个byte数组作为参数,示意二进制数据。它会将每个字节转换为对应的十六进制字符串,并将这些字符串拼接在一起,最初返回一个残缺的十六进制字符串。 具体的实现步骤如下: 创立一个StringBuilder对象hexString,用于存储转换后的十六进制字符串。应用for-each循环遍历bytes数组中的每个字节。对于每个字节,应用Integer.toHexString()办法将其转换为对应的十六进制字符串。0xff & b是为了确保将字节转换为无符号整数。如果转换后的十六进制字符串长度为1,阐明只有一位,须要在后面补0。将转换后的十六进制字符串追加到hexString中。循环完结后,应用toString()办法将hexString转换为一个残缺的十六进制字符串,并返回。这个办法能够用于将任意二进制数据转换为十六进制字符串,不仅限于解决图片数据。你能够在其余须要将二进制数据转换为十六进制字符串的场景中应用这个办法。<!-- md tj.md --> 本文由mdnice多平台公布

September 21, 2023 · 1 min · jiezi

关于后端:ToplingDB-NestLoudsTrie-索引

背景ToplingDB 是 topling 开发的 KV 存储引擎,fork 自 RocksDB,进行了很多革新,其中最重要的部件是 ToplingZipTable, 是 BlockBasedTable 的代替品,性能更高而内存占用更低。ToplingZipTable 应用 CO-Index 与 PA-Zip 实现索引和数据的存储。CO-Index 指 Compressed Ordered Index, 是一类内存压缩的索引,无需解压,在压缩的状态下能够对索引间接搜寻,并且搜寻速度极快。从 String 类型的 Key,搜寻出一个密实 的 整数 ID。PA-Zip 指 Point Accessible Zip, 无需 BlockCache,能够十分疾速地 按 ID 定点拜访单条数据。本文形容 CO-Index 家族中最通用的索引:NestLoudsTrie2. Succinct 数据结构Succinct Data Structure是一种可能在靠近于信息论上限的空间内来表白对象的技术,通常应用位图来示意,用定义在位图上的 rank 和 select 操作来定位。rank 和 select 能够通过空间占用极少的索引来实现,实践上,只须要 �(�) 的索引空间就能够用 �(1) 的工夫复杂度实现 rank 和 select 操作,然而这个 O(1) 的常数项很大。在实践中,咱们会通过稍多一点的空间,换取更小的 O(1) 常数项。驰名的开源我的项目 SDSL-Lite 中有各种 Succinct 数据结构的实现,是一个大而全的 Succinct 我的项目。3. topling-zip 简介与 SDSL-Lite 相同,有着 10 余年历史的 ToplingDB 的底层外围库 topling-zip 在 Succinct 上并不谋求大而全,而是“小而精”,所有以实用为目标,性能优先。topling-zip 中的 Succinct 最后是专为 NestLoudsTrie 实现的,而 NestLoudsTrie 是 Topling FSA(DFA+NFA) 家族的一份子,同时也是自动机压缩算法的一个 Building Block目前开源的 topling-zip 只蕴含 Topling FSA 中实用于数据库索引的局部,不蕴含正则表达式引擎及各种字符串匹配算法的局部(例如多正则引擎及专利的拼音纠错算法)topling 的所有数据结构在设计上都都反对 mmap: 数据在内存中的格局和在文件中的格局完全相同。不仅如此,topling 的所有构件在设计上都严格贯彻“高内聚”、“低耦合”的准则,这也是 Unix 哲学:每个构件只做一件事并且做好这件事。就最根底的 Succinct: 反对 rank select 的 bitmap 来看,topling 的性能远高于广为人知的 SDSL-LiteRank-Select Benchmark(比照 SDSL-Lite),这个比照是 5,6 年前测的,当初 Topling 比当初还有肯定晋升4. Succinct Trie4.1. Succinct TreeTree 的传统实现中,每个结点蕴含两个指针:struct Node { Node firstChild, nextSibling; };每个结点占用 2 ptr,如果咱们对传统办法进行优化,结点指针用最小的 bits 数来表白,N 个结点就须要 2∗⌈���2(�)⌉ 个 bits。比照传统根本版和传统优化版,假如共有 216 个结点(包含 null 结点),传统优化版须要 2 bytes,传统根本版须要 4/8 bytes。比照传统优化版和Succinct,假如共有 10亿(~ 230 )个结点。传统优化版每个指针占用 ⌈���2(230)⌉=30 bits,总内存占用: 2∗308∗230 ≈ 7.5GB。如果应用 Succinct,n 个结点的 Tree 空间占用是 O(2n) bits,这个例子中空间占用就是: 2.58∗230 ≈ 312.5MB (每个结点 2.5 bits,其中 0.5 bits 是 rank-select 索引占用的空间),差距是 30 倍!4.2. Unary 编码Succinct Tree 中,每个结点被编码为 111110 序列,其中 1 的个数代表该结点的孩子数量,叶节点没有孩子,所以叶节点的编码就只有单个 0。这叫做 Unary Degree Sequence。4.3. 深度优先 or 宽度优先Tree 最常见的遍历程序是深度优先和宽度优先,相应地,Succinct Tree 也有深度优先和宽度优先编码,不论是深度优先还是宽度优先,单个结点的 bit 编码都是 Unary Degree Sequence。深度优先编码能反对更多的高级操作,然而须要 bitmap 反对除了 rank 和 select 之外的其它操作(findopen 和 findclose,这里不深刻开展)。宽度优先实际上是按层遍历,所以叫做 LOUDS (Level Order Unary Degree Sequence),它的益处是只须要 rank 和 select 操作,能够实现很高的性能,害处是反对的高级操作少。侥幸的是,作为 DB 索引,LOUDS 反对的操作刚好够用4.3. Trie 结点在 Tree 结点的根底上增加了 LabelTrie 结点的传统实现是struct Node { Map<char, Node*> children; };后面 Tree 的firstChild + nextSibling 实际上就是个单向链表,Trie 为每个子节点增加了一个 Key。这个 map children 实现从概念上十分简洁明确,然而即使依照传统的实现形式,其冗余空间占比也过高。咱们留神到,作为 Tree,其结点数 == 边数 + 1,即NodeNum == EdgeNum + 1,除了根节点,每个结点有且仅有一条入边。所以,咱们能够这样定义 Node:struct Node { char incomingLabel; Node firstChild, nextSibling;};这个 Node,编译器为了对齐,incomingLabel 实际上会占用一个指针宽度,很节约空间,然而相比后面的 map children 也小了很多。如果应用 Succinct,其 Tree 构造空间占用是 2.5n 个 bit,同时,其结点是用 [0,�) 的整数编号的,所以,咱们把 IncomingLabel 保留在一个独立的 char 数组中,从而,每个结点的空间占用就是 10.5 个 bit。Patricia Trie作为字符串索引,Trie 树的大部分结点都只有一个孩子,所以不论是传统的 Trie 树,还是 Succinct Trie 树,这都是一个极大的节约,不光节约存储空间,还节约 CPU 工夫。所以,几十年以前,有人就提出了一个优化计划,把所有连贯的并且只有一个孩子的结点,压缩成一个结点,同时把这些结点上的 Label 也连接成一个字符串。这就是 Patricia Trie,这个压缩形式叫做门路压缩。6. 多层嵌套Succinct Trie 还有一个神奇的能力,能够从孩子结点导航到父节点,更正式的形容:能够在 O(1) 的工夫内,从孩子结点的 id 计算出父节点的 id有了这个能力,咱们就能够从任何一个结点 S 登程,向根节点行走,把行走门路上的 IncomingLabel 拼接起来,就失去了结点 S 所代表的字符串。这样,咱们就能够在 Patricia 的根底上,进一步升高存储空间:把 Patricia 中压缩门路上的字符串保留到另一个 Patricia 中,并且能够进行多层嵌套。这就是 NestLoudsTrie。Topling NestLoudsTrieTopling NestLoudsTrie 实现了作为 DB 索引须要的所有操作,并且进行了十分粗疏的优化,Benchmark 进行单项测试:每秒钟可执行 100 万次搜寻操作Iterator 每秒可扫描 500 万个 KeySuccinct 始终被大家诟病性能低下,然而通过咱们的不懈努力,在 ToplingDB 中,实现了性能与空间的双重效力。8. ReorderNestLoudsTrie 中保留的 N 个 Key 会映射到整数区间 [0,�) ,美中不足的是,因为宽度优先,所以 Key 和 n 的对应关系不是 Bytewise 字典序(深度优先的天然序就是字典序)。能够通过破费更多的 CPU 工夫,实现字典序映射的操作,然而咱们谋求的第一指标是性能。所以,在创立 ToplingZipTable 时,咱们须要一个 Reorder 操作,把 Value 程序重排成 NestLoudsTrie 的整数映射程序。这些计算都是在创立 SST 时实现的,进步读取/搜寻的性能。这个美中不足的侥幸之处在于,尽管不是字典序,然而靠近字典序,靠近字典序,对于空间局部性十分重要,特地是在 Iter 扫描时。9. 优化适配层如前所述,Topling 的所有组件均是“高内聚”,“低耦合”,NestLoudsTrie 本来属于 DFA 家族,与 ToplingDB 没有任何关系。要将它适配到 ToplingDB 的 CO-Index,适配层就须要肯定开销。9.1. memcpyNestLoudsTrie 的搜寻、扫描性能很高,这就使得哪怕适配层仅仅是把扫描进去的只有几十字节长的 key memcpy 到 ToplingDB,这个 memcpy 所占的工夫也相当可观(在火焰图中清晰可见)。ToplingDB/RocksDB 中须要在 UserKey 之后拼接上 8 字节的 Tag(Seq, ValueType) 失去 InternalKey,而NestLoudsTrie 中保留的是 UserKey,所以须要将 UserKey 拷贝一次再进行拼接。所以,咱们为 NestLoudsTrie Iterator 的外部 buffer 预留一些额定空间(目前16字节),从而适配层就能够间接将 Tag 放到这个预留空间中,免去了这个额定的 memcpy。更进一步,因为 NestLoudsTrie 是 readonly 的,咱们能够确定 Iterator 的最大内存用量,从而 Iterator 就只须要一块内存,这并不是为了节俭内存用量,而是为了优化 CPU Cache,升高 CPU 耗费!在这个优化之后,本来不须要适配层,间接实现的 UintIndex 也享受到了这个优化,也在 Iterator 中预留额定空间,省掉 memcpy,把这个 buffer 间接 inline 在 UintIndex::Iter 中,整个 UintIndex::Iter 也只有一块内存。9.2. 虚函数 & Layout 优化COIndex::Iterator 和 NestLoudsTrie::Iterator 是两套体系,两者之间进行适配,即使省去了 memcpy,接口转化的虚函数调用还是难以避免的。上面这个 key() 本来是个虚函数,在 Iterator scan 的火焰图中占比并非微不足道。接下来的优化略微有点违反“高内聚”,“低耦合”了,所以必须在可控范畴之内。NestLoudsTrie::Iter 的 m_word 成员继承自 BaseDFA::Iter,相当于 vector<byte>,fstring 相当于 string_view/Slice,咱们精心设计对象布局,让所有 COIndex::Iter 派生类的 key 都在同一个偏移处,并且,针对 NestLoudsTrie::Iter,让其 m_word 成员的 ptr, len 正好对准到其它 COIndex 的 m_key{ptr,len} 成员。当然,这些数据成员的对准都要有编译期查看!这样,只须要 Iter::Next/Prev 是虚函数就能够了,实现这个优化还有更重要的一个起因:UintIndex 和 FixLenIndex 的扫描更快,扫描单条数据只须要几个纳秒,如果 key() 是虚函数,减少的开销相当可观。不能因为 NestLoudsTrie 不在 COIndex 体系而连累他人。最开始没有用当初这个对准 m_key 和 m_word 的计划,而是把 m_word 的 data 指针和 size 拷贝到 m_key,仍有一些不必要的开销,在火焰图中能够察看到。【完】 ...

September 21, 2023 · 2 min · jiezi

关于后端:树形-DP树形-DP-的通用思路

题目形容这是 LeetCode 上的 310. 最小高度树 ,难度为 中等。 Tag : 「树形 DP」、「DFS」、「动静布局」 树是一个无向图,其中任何两个顶点只通过一条门路连贯。 换句话说,一个任何没有简略环路的连通图都是一棵树。 给你一棵蕴含 $n$ 个节点的树,标记为 $0$ 到 $n - 1$ 。给定数字 $n$ 和一个有 $n - 1$ 条无向边的 edges 列表(每一个边都是一对标签),其中 $edges[i] = [a_i, b_i]$ 示意树中节点 $a_i$ 和 $b_i$ 之间存在一条无向边。 可抉择树中任何一个节点作为根。当抉择节点 $x$ 作为根节点时,设后果树的高度为 $h$ 。在所有可能的树中,具备最小高度的树(即,min(h))被称为 最小高度树 。 请你找到所有的 最小高度树 并按 任意程序 返回它们的根节点标签列表。 树的 高度 是指根节点和叶子节点之间最长向下门路上边的数量。 示例 1: 输出:n = 4, edges = [[1,0],[1,2],[1,3]]输入:[1]解释:如图所示,当根是标签为 1 的节点时,树的高度是 1 ,这是惟一的最小高度树。示例 2: 输出:n = 6, edges = [[3,0],[3,1],[3,2],[3,4],[5,4]]输入:[3,4]提醒: $1 <= n <= 2 \times 10^4$$edges.length = n - 1$$0 <= ai, bi < n$$ai != bi$所有 $(ai, bi)$ 互不雷同给定的输出保障是一棵树,并且不会有反复的边树形 DP这是一道树形 DP 模板题。 ...

September 21, 2023 · 3 min · jiezi

关于后端:集成开发环境软件Eclipse与MyEclipse区别

Eclipse和MyEclipse是两款宽泛应用的集成开发环境(IDE),次要用于Java语言的开发,同时也反对其余计算机语言的开发插件,比方C++和Python等。这两款工具之间的次要区别在于Eclipse是开源的,而MyEclipse则是基于Eclipse的商业版本。 Eclipse最后是由IBM公司开发的代替商业软件Visual Age for Java的下一代IDE开发环境,并于2001年11月奉献给开源社区。现在,Eclipse由非营利软件供应商联盟Eclipse基金会治理,包含Eclipse我的项目、Eclipse工具我的项目、Eclipse技术我的项目等,这些我的项目为高度集成的工具开发提供一个全功能、具备商业品质的工业平台。 Eclipse是一款凋谢源代码的集成开发环境(IDE),采纳了丰盛的插件架构和灵便的扩展性。它广泛应用于Java开发,但也反对其余编程语言,如C/C++、Python等。Eclipse提供了弱小的代码编辑器、调试器、版本控制集成等性能,帮忙开发人员更高效地编写和治理代码。此外,Eclipse领有宏大的社区和插件生态系统,用户能够依据我的项目需要抉择并装置各种插件来扩大性能。而且,Eclipse是收费的,并且实用于多个操作系统。 MyEclipse是Eclipse的商业版本,由Genesis Development Solutions公司开发。它基于Eclipse,减少了更多功能和工具,以晋升Java语言开发人员的效率。MyEclipse蕴含了相似于Eclipse的外围性能,包含代码编辑器、调试器、版本控制集成等。除此之外,MyEclipse还提供了一些独特的性能,例如图形界面设计器、针对Web利用程序开发的工具、数据库工具等,旨在进步开发效率。 MyEclipse有不同版本,每个版本针对特定的开发需要和指标用户,提供特定的性能汇合。作为商业软件,MyEclipse提供有限期的收费试用版,但须要购买许可证能力享受残缺性能。 总结来说,Eclipse是一款功能强大的开源IDE,宽泛用于Java开发,并具备丰盛的插件生态系统;而MyEclipse是基于Eclipse的商业化IDE,具备更多加强性能和工具,实用于特定的开发需要。在抉择适合的工具时,能够依据集体爱好、我的项目要求和估算来做出决策。今天我将具体解说如何下载和装置Eclipse软件。如有疑难,点击链接退出群聊【信创技术交换群】:http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=EjDhISXNgJlMMemn85v...

September 21, 2023 · 1 min · jiezi

关于后端:面试题精讲JavaOptional用法

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 系列文章地址 Java 8 引入了 Optional 类,用于解决空指针异样(NullPointerException)的问题。Optional 是一个容器类,能够蕴含一个非空的值或者示意值不存在。通过应用 Optional,咱们能够更加优雅地解决可能为空的值,防止了繁琐的空值检查和异样解决。 上面是 Optional 类的一些罕用办法和用法: 创立 Optional 对象: 应用 Optional.of(value):创立一个蕴含指定值的 Optional 对象。如果传入的值为 null,则会抛出 NullPointerException。应用 Optional.ofNullable(value):创立一个蕴含指定值的 Optional 对象。如果传入的值为 null,则会创立一个空的 Optional 对象。应用 Optional.empty():创立一个空的 Optional 对象。判断值是否存在: 应用 isPresent() 办法:判断 Optional 对象中是否蕴含值。如果值存在,返回 true;否则,返回 false。获取值: 应用 get() 办法:获取 Optional 对象中的值。如果值存在,返回该值;否则,抛出 NoSuchElementException 异样。在应用 get() 办法之前,最好先应用 isPresent() 办法进行判断。解决值不存在的状况: 应用 ifPresent(Consumer<? super T> consumer) 办法:如果值存在,则执行指定的操作。能够传入一个 Consumer 函数式接口,用于解决值存在的状况。应用 orElse(T other) 办法:如果值不存在,则返回指定的默认值。应用 orElseGet(Supplier<? extends T> supplier) 办法:如果值不存在,则通过指定的供给函数获取一个默认值。应用 orElseThrow(Supplier<? extends X> exceptionSupplier) 办法:如果值不存在,则抛出指定的异样。上面是一个简略的示例,展现了 Optional 的用法: ...

September 21, 2023 · 1 min · jiezi

关于后端:线程池面试题

如果咱们正当的应用线程池,则能够防止把零碎搞崩的困境。总得来说,应用线程池能够带来以下几个益处: 1、升高资源耗费。通过反复利用已创立的线程,升高线程创立和销毁造成的耗费。 2、进步响应速度。当工作达到时,工作能够不须要等到线程创立就能立刻执行。 3、减少线程的可管理型。线程是稀缺资源,应用线程池能够进行统一分配,调优和监控。 线程池的外围属性有哪些?threadFactory(线程工厂):用于创立工作线程的工厂。corePoolSize(外围线程数):当线程池运行的线程少于 corePoolSize 时,将创立一个新线程来解决申请,即便其余工作线程处于闲暇状态。workQueue(队列):用于保留工作并移交给工作线程的阻塞队列。maximumPoolSize(最大线程数):线程池容许开启的最大线程数。handler(回绝策略):往线程池增加工作时,将在上面两种状况触发回绝策略:1)线程池运行状态不是 RUNNING;2)线程池曾经达到最大线程数,并且阻塞队列已满时。keepAliveTime(放弃存活工夫):如果线程池以后线程数超过 corePoolSize,则多余的线程闲暇工夫超过 keepAliveTime 时会被终止。 线程池目前有5个状态:RUNNING:承受新工作并解决排队的工作。SHUTDOWN:不承受新工作,但解决排队的工作。STOP:不承受新工作,不解决排队的工作,并中断正在进行的工作。TIDYING:所有工作都已终止,workerCount 为零,线程转换到 TIDYING 状态将运行 terminated() 钩子办法。TERMINATED:terminated() 已实现。 常见的阻塞队列有以下几种:ArrayBlockingQueue:基于数组构造的有界阻塞队列,按先进先出对元素进行排序。LinkedBlockingQueue:基于链表构造的有界/无界阻塞队列,按先进先出对元素进行排序,吞吐量通常高于 ArrayBlockingQueue。Executors.newFixedThreadPool 应用了该队列。 回绝策略AbortPolicy:停止策略。默认的回绝策略,间接抛出 RejectedExecutionException。调用者能够捕捉这个异样,而后依据需要编写本人的解决代码。 DiscardPolicy:摈弃策略。什么都不做,间接摈弃被回绝的工作。 DiscardOldestPolicy:摈弃最老策略。摈弃阻塞队列中最老的工作,相当于就是队列中下一个将要被执行的工作,而后从新提交被回绝的工作。如果阻塞队列是一个优先队列,那么“摈弃最旧的”策略将导致摈弃优先级最高的工作,因而最好不要将该策略和优先级队列放在一起应用。 CallerRunsPolicy:调用者运行策略。在调用者线程中执行该工作。该策略实现了一种调节机制,该策略既不会摈弃工作,也不会抛出异样,而是将工作回退到调用者(调用线程池执行工作的主线程),因为执行工作须要肯定工夫,因而主线程至多在一段时间内不能提交工作,从而使得线程池有工夫来解决完正在执行的工作。

September 20, 2023 · 1 min · jiezi

关于后端:LeetCode-mysql-刷题三确认率MySQL-中的-null-处理-判断三角形的四种方法

明天一题难度是中等,一题难度是简略 第一题确认率考查的知识点是:null 值解决,第二题考查的是如何判断三角形 题目题目链接:确认率 用户的 确认率 是 'confirmed' 音讯的数量除以申请的确认音讯的总数。没有申请任何确认音讯的用户的确认率为 0 。确认率四舍五入到 小数点后两位 。 编写一个 SQL 查问来查找每个用户的 确认率 。 以 任意程序 返回后果表。 查问后果格局如下所示。 Create table If Not Exists Signups (user_id int, time_stamp datetime);Create table If Not Exists Confirmations (user_id int, time_stamp datetime, action ENUM('confirmed','timeout'));Truncate table Signups;insert into Signups (user_id, time_stamp) values ('3', '2020-03-21 10:16:13');insert into Signups (user_id, time_stamp) values ('7', '2020-01-04 13:57:59');insert into Signups (user_id, time_stamp) values ('2', '2020-07-29 23:09:44');insert into Signups (user_id, time_stamp) values ('6', '2020-12-09 10:39:37');Truncate table Confirmations;insert into Confirmations (user_id, time_stamp, action) values ('3', '2021-01-06 03:30:46', 'timeout');insert into Confirmations (user_id, time_stamp, action) values ('3', '2021-07-14 14:00:00', 'timeout');insert into Confirmations (user_id, time_stamp, action) values ('7', '2021-06-12 11:57:29', 'confirmed');insert into Confirmations (user_id, time_stamp, action) values ('7', '2021-06-13 12:58:28', 'confirmed');insert into Confirmations (user_id, time_stamp, action) values ('7', '2021-06-14 13:59:27', 'confirmed');insert into Confirmations (user_id, time_stamp, action) values ('2', '2021-01-22 00:00:00', 'confirmed');insert into Confirmations (user_id, time_stamp, action) values ('2', '2021-02-28 23:59:59', 'timeout');输出:Signups 表:+---------+---------------------+| user_id | time_stamp |+---------+---------------------+| 3 | 2020-03-21 10:16:13 || 7 | 2020-01-04 13:57:59 || 2 | 2020-07-29 23:09:44 || 6 | 2020-12-09 10:39:37 |+---------+---------------------+User_id是该表的主键。每一行都蕴含ID为user_id的用户的注册工夫信息。Confirmations 表:+---------+---------------------+-----------+| user_id | time_stamp | action |+---------+---------------------+-----------+| 3 | 2021-01-06 03:30:46 | timeout || 3 | 2021-07-14 14:00:00 | timeout || 7 | 2021-06-12 11:57:29 | confirmed || 7 | 2021-06-13 12:58:28 | confirmed || 7 | 2021-06-14 13:59:27 | confirmed || 2 | 2021-01-22 00:00:00 | confirmed || 2 | 2021-02-28 23:59:59 | timeout |+---------+---------------------+-----------+(user_id, time_stamp)是该表的主键。user_id是一个援用到注册表的外键。action是类型为('confirmed', 'timeout')的ENUM该表的每一行都示意ID为user_id的用户在time_stamp申请了一条确认音讯,该确认音讯要么被确认('confirmed'),要么被过期('timeout')。输入:+---------+-------------------+| user_id | confirmation_rate |+---------+-------------------+| 6 | 0.00 || 3 | 0.00 || 7 | 1.00 || 2 | 0.50 |+---------+-------------------+解释:用户 6 没有申请任何确认音讯。确认率为 0。用户 3 进行了 2 次申请,都超时了。确认率为 0。用户 7 提出了 3 个申请,所有申请都失去了确认。确认率为 1。用户 2 做了 2 个申请,其中一个被确认,另一个超时。确认率为 1 / 2 = 0.5。解析此题考点是 null 值解决 ...

September 20, 2023 · 3 min · jiezi

关于后端:怎样判断一个数是否为偶数

要求代码行数尽可能少;package mainimport ( "fmt" "strconv")func main(){ fmt.Printf("传入的值是否为奇数:%t\n",Judge_is_even(7))}func Judge_is_even(num int) bool { //fmt.Println(num % 2) rs, _ := strconv.ParseBool(strconv.Itoa(num % 2)) return rs}num % 2,值为0时即无余数,为偶数;值为1时即余1,为奇数; Go中泛int型无奈间接转换为bool类型,须要先转成string..再由string转为bool 要求性能尽可能高:思考实质,用位运算. 一个整数,无论占1个Byte还是2个或4个,即无论能表征2的8次方多的整数,亦或是2的16次方或2的32次方多,但在二进制转十进制中,其最初一个坑位都是X*2的0次方即X(X为0或1),而其下面几位为0或1乘以2的1-n次方,必为偶数,故而最初一位X为0或1,即决定了整个整数的奇偶:如果为0,最初一位值为0*2的0次方=0*1=0,为偶数;如果为1,则为1*1=1,为奇数; "计算机中的数字通常用二进制补码示意—— 如果为负数,补码与原码雷同,间接看最初一位(因为数字1的后面N位均为0,跟它做与运算,后面必定为0),奇数为1,偶数为0,与1相与,后果不变。 如果为正数,补码转原码:放弃符号位不动,其它各位取反+1,即为正数的绝对值原码全副取反+1。还是看最初1位,先取反,再+1,后果还是和原来雷同。进行与运算时还是原来的末位,所以用跟1做与运算还是放弃原来的后果。" 奇数的二进制数的最初一位永远是 1,与 1 按位且只会失去 1,偶数相同。 package mainimport ( "fmt" "strconv")func main() { fmt.Printf("传入的值是否为奇数:%t\n", Judge_is_even(81))}func Judge_is_even(num int) bool { rs, _ := strconv.ParseBool(strconv.Itoa(num & 1)) return rs}可参考 本文由mdnice多平台公布

September 20, 2023 · 1 min · jiezi

关于后端:面试题精讲说一说springboot加载配置文件优先级

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 系列文章地址 Spring Boot 加载配置文件的优先级是依据不同的地位和命名规定来确定的。上面依照优先级从高到低的程序来介绍: 命令行参数:通过命令行参数指定的配置会笼罩其余配置。例如,应用--spring.config.name和--spring.config.location参数能够指定配置文件的名称和地位。操作系统环境变量:Spring Boot 会主动将操作系统环境变量中以SPRING_结尾的变量转换为配置属性。例如,将SPRING_APPLICATION_NAME设置为myapp,则能够在配置文件中应用${spring.application.name}来援用该值。命令行属性:能够通过-D参数或者--spring.config.name和--spring.config.location参数来指定配置文件的名称和地位。jar 包内部的 application.properties 或 application.yml:如果存在config文件夹,Spring Boot 会加载该文件夹下的application.properties或application.yml文件。jar 包外部的 application.properties 或 application.yml:如果 jar 包外部存在application.properties或application.yml文件,Spring Boot 会加载该文件。jar 包外部的 application-{profile}.properties 或 application-{profile}.yml:如果指定了激活的 profile,Spring Boot 会加载对应的application-{profile}.properties或application-{profile}.yml文件。jar 包内部的 application-{profile}.properties 或 application-{profile}.yml:如果存在config文件夹,Spring Boot 会加载该文件夹下的application-{profile}.properties或application-{profile}.yml文件。jar 包内部的 application.properties 或 application.yml:如果存在config文件夹,Spring Boot 会加载该文件夹下的application.properties或application.yml文件。须要留神的是,Spring Boot 会依照上述程序加载配置文件,前面加载的配置会笼罩后面加载的配置。因而,如果存在多个配置文件,能够通过优先级来管制配置的加载程序。 另外,Spring Boot 还反对应用@PropertySource注解来加载自定义的配置文件,能够通过value属性指定配置文件的门路。这种形式的优先级介于 jar 包外部和 jar 包内部的配置文件之间。 总结起来,Spring Boot 加载配置文件的优先级从高到低顺次为:命令行参数 > 操作系统环境变量 > 命令行属性 > jar 包内部的配置文件 > jar 包外部的配置文件 > jar 包内部的 profile 配置文件 > jar 包外部的 profile 配置文件。 ...

September 20, 2023 · 1 min · jiezi

关于后端:etcd的安装和使用

装置及启动 在Mac上,举荐应用brew装置 brew install etcd 能够应用etcd启动服务,但更举荐应用 brew services 来治理应用brew装置的利用~ # 启动某个利用,这里用 etcd 做演示brew services start etcd# 进行某个利用brew services stop etcd# 查看以后利用列表# 能够看到相干利用的情况brew services list 相干操作 验证是否胜利启动: etcdctl endpoint health 或 curl -L http://172.16.101.55:2379/health 查看版本: curl http://127.0.0.1:2379/version V3.4版本之后默认是V3接口,不再反对V2: etcd v3应用gRPC作为其消息传递协定。 etcd我的项目包含一个基于gRPC的Go客户端和一个命令行实用程序etcdctl,用于通过gRPC与etcd集群进行通信。 对于不反对gRPC的语言,etcd提供了JSON gRPC网关。 该网关提供一个RESTful代理,该代理将HTTP/JSON申请转换为gRPC音讯ETCD v3 restful api 应用详解 v2和v3接口差别较大, 如果想持续应用v2, 须要在启动时指定 --enable-v2=true,否则间接申请v2的api会报404 etcd --enable-v2=true: (上面持续应用v2接口) 查看key:curl 127.0.0.1:2379/v2/keys 新建key:(如果key之前存在,则默认会先删除,再新建一个key。如果想要间接update,则需追加 -d prevExist=true,但若加该参数,如果key之前不存在会报错) curl 127.0.0.1:2379/v2/keys/ckl -XPUT -d value="shuang" 创立目录:curl 127.0.0.1:2379/v2/keys/mulu666 -XPUT -d dir=true ...

September 20, 2023 · 1 min · jiezi

关于后端:COMP90073-Security-Analytics

Faculty of Engineering and Information TechnologyThe University of MelbourneCOMP90073 Security Analytics,Semester 2, 2023Assignment 2: Blue Team & Red Team CybersecurityRelease: Fri 1 Sep 2023Due: Tue 17 Oct 2023Marks: The Project will contribute 25% of your overall mark for the subject.You will be assigned a mark out of 25, according to the criteria below. 1. OverviewYou’ve recently been brought into head up the cybersecurity team FashionMarketData.com -who are a major player in providing platforms for online fashion retailers to leverage theirdata through machine learning. However, after recently witnessing high profile databreaches, including at Medibank and AHM, leadership of thecompany are concerned thatthe business might face existential financial, legal, and reputational risks stemming fromhackers potentially manipulating their data, or exploiting their machine learning models.The CEO has tasked you with heading up the newly formed Blue and Red Teamcybersecurity groups inside the company, and developing a report for the board that outlinesboth risks and opportunities for the company. The Blue Team are concerned about userspotentially uploading images that do not match their labels, througheither mistaken use ofthe platform, or to potentially actively manipulate the company's systems. As such, the BlueTeam are working on designing and implementing systems that ensure only genuine,fashion-related images are processed and ingested into the company’s crowd sourceddatasets. In practice, this will involve reliably detecting and distinguishing both anomalousand out of distribution samples.The Red Team are taking a different bent. Ratherthanactivelydefending the company’ssystems, they’re more concerned with understanding the scope of vulnerabilities in machinelearning models that have rapidly become a core part of the company’s business practices.As such, the team plans to construct evasion and data poisoning attacks against exemplar,non-production models, and to use these results to build a picture of the vulnerabilitiespresent within the company’s systems and processes.Finally, you will need to present a report for the non-technical leadership ofFashionMarketData.com, based upon your insights from working with both the Blue and Redteams. Due to the critical nature of understanding the risk that the company may face fromits data management and machine learning practices, it is crucial that you deliver this reportat the next meeting of thecompany'sboard, which will be on Tuesday the 17th of October,2023.DatasetsTounderstand these vulnerabilities, you have been provided with images encompassing 10distinct fashion categories, which have primarily been drawn from the Fashion-MNISTdataset. This dataset consists of 28*28 grayscale images in 10 distinct fashioncategories.This compilation serves as your in-distribution (normal) dataset, representative of the coreand expected content within the fashion domain. Examples of the first 3 fashion categories inthe given dataset are shown below.Your primary task is to devise and refine multiple algorithms with the specific aim ofidentifying anomalies and out-of-distribution (OOD) images. OOD samples refer to imagesthat do not belong to the fashion categories defined w.r.t. the in-distribution data, such asairplanes, animals, and hand-written letters/characters, etc. Meanwhile, anomaly samplespertain to fashion images that diverge from typical fashion items. While they remaincategorically fashion images, they differ from the familiar images in the dataset due todistortions, rotations, cropping, and similar alterations.To facilitate this objective, five separate datasets will be made available to you. Each datasetwill play a crucial role in training, validating, and testing the efficiency and accuracy of thealgorithms you develop.Dataset DescriptionTraining set[train_data.npy]train_labels.npy]This dataset features images from 10 unique fashioncategories, labelled from 0 to 9. It acts as the principalguide to discern the standard content in the fashiondomain. You will employ this dataset for both anomalyand OOD detection tasks.For Anomaly DetectionValidation setanomaly_validation_data.npyThis set comprises both original and distorted fashionitems. Importantly, items labelled '1' indicate ananomaly status, while those labelled '0' representnormal data. This validation set is primarily intended fortuning your model's hyperparameters and reporting itsperformance using the relevant metrics in your analysis.For Anomaly Detection ...

September 20, 2023 · 13 min · jiezi

关于后端:典型的微服务架构是什么样的

典型的微服务架构是什么样的?典型的微服务架构是什么样的?下图列举了典型的微服务架构所蕴含的部件。 负载均衡器它将传入流量调配给多个后端服务,是高可用架构的要害组件。流量的调配个别遵循某种算法。比方轮询 (Round Robin),最小连贯 (Lest Connections)等。 CDN(内容散发网络)CDN 是一组散布在不同地区的服务器,用于保留动态内容以放慢响应速度。客户端首先在 CDN 服务器中查找内容,如果找不到再转到后端服务。 API 网关它解决传入的申请,并将其路由到相干服务。它与身份验证模块和服务发现模块交互。 身份验证解决用户的身份鉴权 (Authentication) 和受权(Authorization)。 服务注册和发现微服务注册和发现在此组件中进行,API 网关在此组件中寻找相干服务地址并发送申请到相干服务。 治理组件该组件负责配置、线上监控和治理。 微服务微服务分为不同的域,并在各个域中独立设计和部署。每个域都有本人的数据库。API 网关通过 REST API 或其余协定调用微服务,同一域内的微服务通过 RPC 来交互。 中间件 - 音讯队列微服务之间还能够通过音讯队列来进行异步交互和扇出 (Fan Out)。比方,领取服务会破费较长时间来实现付款,那么上游的交易系统就能够通过Kafka来发送申请,等到领取实现后再通过Kafka进行回调。 缓存为了放慢热点数据的响应速度,微服务能够在拜访数据库前先查问缓存。架构中退出缓存后,咱们须要留神缓存和数据库的数据一致性。 微服务的劣势能够疾速设计、部署和横向扩大。每个域都能够由专门的团队独立保护。业务需要能够在每个域中定制,从而失去更好的反对。

September 20, 2023 · 1 min · jiezi

关于后端:后端开发需要安装哪些软件插件

从明天开始更新一系列对于后端开发须要装置哪些软件/插件的文章,每日更新筹备好了吗?言归正传,后端开发须要装置的软件、插件有很多种,以下是一些罕用的软件和插件:1.编程语言和运行环境:依据开发我的项目的需要,须要装置相应的编程语言和运行环境。比方,Java、Python、Go、Node.js等语言及其对应的运行环境。2.包管理器:用于装置和治理软件包。例如,对于Java开发,能够装置Maven或Gradle等包管理器。对于Python开发,能够装置pip等包管理器。3.集成开发环境(IDE):例如Eclipse、IntelliJ IDEA、PyCharm等IDE可提供代码编辑、调试、测试等性能,进步开发效率。4.数据库管理系统:*Oracle:传统行业,尤其是政府、医疗、学校和大企业,基本上宽泛应用Oracle。*MySQL:MySQL是一种风行的关系型数据库,宽泛用于Web应用程序和企业级应用程序中。它的长处包含高可靠性、性能强和易于应用,通常被用于新我的项目,尤其是一些面向互联网连贯的我的项目。*PostgreSQL:PostgreSQL是一种高级关系型数据库,具备高度的可扩展性、高级的数据完整性和高可靠性。*Microsoft SQL Server:由Microsoft公司开发的关系型数据库,通常用于企业级应用程序和Web应用程序,具备高度的可靠性、安全性和可扩展性。*MongoDB:MongoDB是一种文档型的NoSQL数据库,宽泛用于Web应用程序和大规模数据存储。*Cassandra:Cassandra是一种分布式的NoSQL数据库,宽泛用于大规模数据存储和解决。*Redis:Redis是一种内存型的NoSQL数据库,宽泛用于缓存、队列和数据存储。 5.服务器软件:例如Nginx、Apache、Tomcat等服务器软件可用于部署和运行应用程序。6.版本控制系统:例如Git、SVN等版本控制系统用于治理和跟踪代码的变动。7.虚拟化软件:例如VirtualBox、VMware等虚拟化软件可用于在一台计算机上模仿多个操作系统环境。8.调试工具:例如Chrome开发者工具、Fiddler等调试工具可用于排查代码中的问题和调试程序。9.测试工具:例如JUnit、pytest等测试工具用于编写和运行单元测试、集成测试和功能测试等,保障代码的品质和稳定性。10.继续集成/继续部署(CI/CD)工具:例如Jenkins、Travis CI等CI/CD工具可自动化构建、测试和部署应用程序。11.容器化平台:例如Docker、Kubernetes等容器化平台可用于打包、治理和运行应用程序。总之,后端开发须要装置的软件和插件有很多种,不同的工具和插件都有不同的用处和劣势,依据我的项目需要抉择适宜本人的工具和插件能够让开发更加高效和舒服。如有疑难,点击链接退出群聊【信创技术交换群】:http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=EjDhISXNgJlMMemn85v...

September 20, 2023 · 1 min · jiezi

关于后端:REST-API设计模式和反模式

RESTful API曾经成为构建古代网络应用的事实标准。它们容许一个灵便和可扩大的架构,能够很容易地被宽泛的客户端所生产。然而,设计一个既强壮又可保护的REST API是很有挑战性的,特地是对于刚入行的开发者。 在这篇文章中,咱们将探讨一些常见的REST API设计模式和开发者应该留神的反模式。咱们还将提供Golang和Open API Schema的代码片段来帮忙阐明这些概念。 REST API设计模式1.以资源为导向的架构(ROA) 面向资源的架构(ROA)是一种设计模式,强调资源在RESTful API中的重要性。资源是RESTful API的要害构件,它们应该被设计成易于生产和操作的形式。 在Golang中实现ROA的一种形式是应用gorilla/mux包进行路由。这里有一个例子: r := mux.NewRouter()r.HandleFunc("/users/{id}", getUser).Methods("GET")r.HandleFunc("/users", createUser).Methods("POST")r.HandleFunc("/users/{id}", updateUser).Methods("PUT")r.HandleFunc("/users/{id}", deleteUser).Methods("DELETE")在Open API Schema中,你能够应用path参数来定义资源。上面是一个例子: paths: /users/{id}: get: … put: … delete: … /users: post: …2. HATEOAS 超媒体作为利用状态的引擎(HATEOAS)是一种设计模式,容许客户动静地浏览RESTful API。API提供超媒体链接,客户能够依照这些链接来发现资源并与之互动。 为了在GoLang中实现HATEOAS,你能够应用go-jsonapi包。这里有一个例子: type User struct { ID string `json:"id"` Name string `json:"name"` Links *Links `json:"links,omitempty"`}type Links struct { Self *Link `json:"self,omitempty"`}type Link struct { Href string `json:"href,omitempty"`}func getUser(w http.ResponseWriter, r *http.Request) { userID := mux.Vars(r)["id"] user := User{ID: userID, Name: "John Doe"} user.Links = &Links{ Self: &Link{Href: fmt.Sprintf("/users/%s", userID)}, } jsonapi.MarshalOnePayload(w, &user)}在Open API Schema中,你能够应用links参数来定义超媒体链接。这里有一个例子: ...

September 20, 2023 · 2 min · jiezi

关于后端:Nginx系列一Nginx基础概念

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 系列文章地址 Nginx的三个次要利用场景 动态资源服务通过本地文件系统提供服务动态资源服务是指通过本地文件系统提供动态文件(如HTML、CSS、JavaScript、图片等)的服务。这种服务通常由Web服务器来提供,比方Nginx、Apache等。 动态资源服务的实现原理很简略,当客户端申请动态资源时,服务器会依据申请的URL门路找到对应的文件,并将文件内容返回给客户端。这个过程不须要进行动静解决,因而能够进步服务的性能和响应速度。 在Nginx中配置动态资源服务非常简单,只须要在配置文件中指定动态资源的根目录即可。例如,以下是一个简略的Nginx配置示例: server { listen 80; server_name example.com; root /path/to/static/files; location / { try_files $uri $uri/ =404; }}上述配置中,root指定了动态资源的根目录,location /示意所有申请都会被该配置块解决。try_files指令用于尝试查找申请的文件,如果找到则返回文件内容,否则返回404谬误。 反向代理服务反向代理是一种服务器架构模式,它将客户端的申请转发给后端的多个服务器进行解决,并将处理结果返回给客户端。与正向代理不同,反向代理是对服务器端的资源进行代理,客户端并不知道申请的资源实际上是由哪个服务器提供的。 反向代理的次要作用是负载平衡和进步零碎的可靠性和安全性。通过将申请分发给多个后端服务器,能够平衡服务器的负载,进步零碎的并发解决能力。同时,反向代理还能够暗藏后端服务器的实在IP地址,减少零碎的安全性。 Nginx是一款罕用的反向代理服务器,它具备高性能、高并发解决能力和灵便的配置选项。在Nginx中配置反向代理非常简单,只须要在配置文件中指定后端服务器的地址即可。以下是一个简略的Nginx反向代理配置示例: server { listen 80; server_name example.com; location / { proxy_pass http://backend_server; }}上述配置中,proxy_pass指令用于指定后端服务器的地址,能够是IP地址或域名。当客户端发送申请时,Nginx会将申请转发给后端服务器,并将后端服务器的响应返回给客户端。 缓存Nginx具备弱小的性能缓存性能,能够无效进步网站的访问速度和性能。Nginx的性能缓存次要包含两个方面:动态文件缓存和反向代理缓存。 动态文件缓存是指将动态文件(如HTML、CSS、JavaScript、图片等)缓存到内存中,当客户端申请这些文件时,间接从缓存中返回,而不须要再次读取文件。这样能够大大减少文件的读取工夫,进步网站的响应速度。 反向代理缓存是指将后端服务器的响应后果缓存到内存中,当客户端发送雷同的申请时,间接从缓存中返回响应后果,而不须要再次申请后端服务器。这样能够缩小对后端服务器的拜访压力,进步零碎的并发解决能力。 Nginx的缓存配置非常灵活,能够依据须要进行配置。能够设置缓存的有效期、缓存的大小、缓存的存储地位等。以下是一个简略的Nginx缓存配置示例: http { proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m; server { listen 80; server_name example.com; location / { proxy_cache my_cache; proxy_cache_valid 200 302 10m; proxy_cache_valid 404 1m; proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; proxy_cache_bypass $http_cache_control; proxy_no_cache $http_pragma $http_authorization; proxy_pass http://backend_server; } }}上述配置中,proxy_cache_path指令用于指定缓存的存储地位和大小。proxy_cache指令用于启用缓存,proxy_cache_valid指令用于设置缓存的有效期。proxy_cache_use_stale指令用于指定在后端服务器不可用时是否应用过期的缓存。proxy_cache_bypass和proxy_no_cache指令用于管制缓存的应用条件。 ...

September 20, 2023 · 1 min · jiezi

关于后端:面试题精讲Mysql如何实现乐观锁

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 系列文章地址 在 MySQL 中,能够通过应用乐观锁来实现并发管制,以防止数据抵触和并发更新问题。乐观锁是一种乐观的思维,它假如并发操作不会导致抵触,只有在提交更新时才会查看是否发生冲突。 上面介绍两种常见的实现乐观锁的形式: 版本号(Version)机制: 在数据表中增加一个版本号字段,通常是一个整数类型。当读取数据时,将版本号一起读取进去。在更新数据时,先查看以后读取的版本号是否与数据库中的版本号统一,如果统一则进行更新操作,并将版本号加 1;如果不统一,则示意数据曾经被其余事务批改,须要进行相应的解决(例如回滚或者从新尝试)。通过版本号的比拟,能够判断数据是否被其余事务批改过,从而实现乐观锁的成果。示例代码如下(应用 Java 语言): // 读取数据String sql = "SELECT id, name, version FROM table_name WHERE id = ?";PreparedStatement pstmt = connection.prepareStatement(sql);pstmt.setInt(1, id);ResultSet rs = pstmt.executeQuery();if (rs.next()) { int version = rs.getInt("version"); // 更新数据 String updateSql = "UPDATE table_name SET name = ?, version = ? WHERE id = ? AND version = ?"; PreparedStatement updateStmt = connection.prepareStatement(updateSql); updateStmt.setString(1, newName); updateStmt.setInt(2, version + 1); updateStmt.setInt(3, id); updateStmt.setInt(4, version); int affectedRows = updateStmt.executeUpdate(); if (affectedRows == 0) { // 更新失败,数据已被其余事务批改 // 进行相应的解决 }}工夫戳(Timestamp)机制: ...

September 19, 2023 · 1 min · jiezi

关于后端:高并发系统设计之缓存

本文已收录至GitHub,举荐浏览 Java随想录 微信公众号:Java随想录 原创不易,重视版权。转载请注明原作者和原文链接这篇文章来聊聊缓存。在解决高流量的互联网利用时,缓存起着至关重要的作用,是优化网站性能的第一伎俩。 缓存能够显著地进步零碎的性能和用户体验,让访问速度更快。 提到缓存,咱们往往首先想到的就是Redis。的确,Redis是缓存最常见的实现伎俩,但Redis并不是「银弹」,在某些场景下Redis未必是最佳选项。 本文会介绍几种缓存计划,心愿能帮读者关上思路。具体理论利用场景中该应用哪种计划,各位读者见仁见智了。 Nginx缓存Nginx能够通过「Proxy Buffer」和「Proxy Cache」实现缓存的目标。 Proxy BufferNginx的Proxy Buffer是用来长期存储从代理服务器收到的响应数据的。 在反向代理场景中,Nginx会从后端服务器接管响应,而后再将这些响应发送给客户端。如果响应速度较慢,或者一次性数据量较大,可能会导致Nginx阻塞,不能及时处理其余申请。 这时候,Proxy Buffer就显得十分有用,它能够暂存这部分数据,让Nginx可能持续解决其余申请。 举个例子,假如有一个大文件须要通过Nginx从后端服务器传输到用户浏览器。当Nginx从后端服务器获取该文件时,如果没有应用Proxy Buffer,Nginx就必须始终期待整个文件都传输结束,能力释放出来解决其余申请。 但如果启用了Proxy Buffer,那么Nginx就能够把接管到的数据先寄存到Buffer里,而后逐渐传输给用户,同时也能解决其余申请。这样就大大提高了Nginx的并发解决能力。 Nginx中Proxy Buffer默认是开启的,Proxy Buffer相干参数次要有以下几个: proxy_buffering:这是一个开关,用于管制是否启用nginx对后端服务器响应进行缓存。默认值为on。proxy_buffers:定义了须要应用多少个、每个多大的内存缓存区来解决响应。它的设置格局为 number size ,比方 "8 4k" 或者 "4 8k"。nginx的默认设置为"8 4k"或"4 8k",取决于操作系统的页面大小。proxy_buffer_size:定义读取响应头部的缓冲区大小。这通常不须要批改,除非你预期会有十分大的响应头。这个大小也定义了一次能够读取的最大量数据,因而如果可能接管到超大的回应,则须要增大这个值。默认值为读取 proxy_buffers 的第一个参数。proxy_busy_buffers_size:在HTTP响应从被代理服务器读入且尚未传送给客户端时,该值限度了能够在busy buffer中应用的内存数。这个值必须小于或等于 proxy_buffers 中提供的最大值。没有默认值,但必须设置为不大于 proxy_buffers 的大小。proxy_temp_file_write_size:设置子申请写入临时文件时数据的大小。默认值是8KB或者与 proxy_buffers 雷同。proxy_max_temp_file_size:设置能够存储在临时文件中的最大数据量,默认值为1024MB。如果超过这个值,nginx将开始删除旧的临时文件。proxy_temp_path:定义了存储临时文件的门路。默认是零碎的长期目录。联合下面参数,示例配置如下: http { proxy_buffering on; proxy_buffer_size 4k; proxy_buffers 8 16k; proxy_busy_buffers_size 24k; proxy_temp_file_write_size 32k; proxy_max_temp_file_size 0; server { listen 80; location / { proxy_pass http://backend; proxy_temp_path /path/to/temp; } }}这个配置中,开启了Nginx对后端服务器响应的缓存。同时,设置了读取响应头部的缓冲区大小为4KB,解决响应的内存缓冲区数量为8个,每个16KB。在HTTP响应从被代理服务器读入且尚未传送给客户端时,能够在busy buffer中应用的内存数限度为24KB。子申请写入临时文件时数据的大小设定为32KB。并且设置了能够存储在临时文件中的最大数据量为0,示意没有下限。而临时文件的存储门路则是"/path/to/temp"。 ...

September 19, 2023 · 2 min · jiezi

关于后端:本地缓存无冕之王Caffeine-Cache

本文已收录至GitHub,举荐浏览 Java随想录 微信公众号:Java随想录 原创不易,重视版权。转载请注明原作者和原文链接在惯例的软件开发流程中,缓存的重要性日益凸显。它不仅为用户带来了更迅速的反馈工夫,还能在大多数状况下无效加重零碎负荷。 本篇文章将详述一个本地缓存框架:「Caffeine Cache」。 Caffeine Cache以其高性能和可扩展性博得「本地缓存之王」的名称,它是一个Java缓存库。它的设计指标是优化计算速度、内存效率和实用性,以合乎古代软件开发者的需要。 Spring Boot 1.x版本中的默认本地缓存是Guava Cache。在 Spring5 (SpringBoot 2.x)后,Spring 官网放弃了 Guava Cache 作为缓存机制,而是使用性能更优良的 Caffeine 作为默认缓存组件,这对于Caffeine来说是一个很大的必定。 接下来,咱们会具体介绍 Caffeine Cache 的个性和利用,并将这个高效的缓存工具无缝集成到你的我的项目中。 淘汰算法在解析Caffeine Cache之前,咱们首先要了解缓存淘汰算法。一个优良的淘汰算法能使效率大幅晋升,因为缓存过程总会随同着数据的淘汰。 FIFO(First In First Out)先进先出:以时序为基准,先进入缓存的数据会被先淘汰。当缓存满时,把最早放入缓存的数据淘汰掉。 长处:实现简略,对于某些不常反复申请的利用成果较好。 毛病:并未思考到数据项的拜访频率和拜访工夫,可能淘汰的是最近和频繁拜访的数据。 LRU(Least Recently Used)最近最久未应用:此算法依据数据的历史拜访记录来进行决策,最久未被拜访的数据将被淘汰。LRU通过保护一个所有缓存项的链表,新数据插入到链表的头部,如果缓存满了,就会从链表尾部开始移除数据。 长处:LRU思考了最近的数据拜访模式,对于局部性原理的体现优良,简略实用。 毛病:不能体现数据的拜访频率,如果数据最近被拜访过,即便拜访频度低也不会被淘汰。比方,如果一个数据在一分钟的前59秒被频繁拜访,而在最初一秒无任何拜访,然而有一批冷门数据在最初一秒进入缓存,那么热点数据可能会被淘汰掉。 LFU(Least Frequently Used)最近起码频率应用:其基本原理是对每个在缓存中的对象进行计数,记录其被拜访的次数。当缓存满了须要淘汰某些对象时,LFU算法会优先淘汰那些被拜访次数起码的对象。 长处:LFU可能较好地解决长期拜访稳固、频率较高的状况,因为这样能够确保频繁拜访的对象不容易被淘汰。 毛病:对于一些临时高频拜访但之后不再拜访的对象,LFU无奈无效解决。因为这些对象的拜访次数曾经十分高,之后即便不再拜访,也不容易被淘汰,可能造成缓存空间的节约。并且LFU须要保护所有对象的拜访计数,这可能会耗费比拟多的存储空间和计算资源。 W-TinyLFU( Window Tiny Least Frequently Used):Caffeine 应用的就是 Window TinyLfu 淘汰策略,此策略提供了一个近乎最佳的命中率。 看名字就能大略猜出来,它是 LFU 的变种,它在面临缓存换页(即缓存空间有余而须要替换旧缓存项)问题时,通过统计频率信息来抉择最佳的候选项进行替换。 工作原理: 频率滤波:W-TinyLFU 应用一个小型的滑动窗口记录最近拜访过的对象,以捕捉对象的应用频率。这个窗口内的数据被插入到一个 LFU 计数器中,该计数器基于频率革除起码应用的对象。突发性适应:W-TinyLFU 还蕴含一个 Admission Window,用于对新增加到缓存的项进行跟踪,以便可能解决忽然呈现的新热点数据。替换策略:当缓存满了,且有新的元素须要退出时,W-TinyLFU 应用频率信息抉择起码应用的条目进行替换。如果新条目标应用频率较高,那么将替换掉应用频率较低的老条目;如果新项的应用频率较低,则可能会被回绝。相较于传统的 LRU 和 LFU 策略,W-TinyLFU具备以下长处: ...

September 19, 2023 · 4 min · jiezi

关于后端:McCabe度量法

概论: McCabe度量法是由 托马斯·麦克凯 提出的一种基于程序控制流的复杂性度量办法。又称环路度量,循环复杂度(Cyclomatic complexity), 也称为条件复杂度或圈复杂度,是一种软件度量。它认为程序的复杂性很大水平上取决于程序图的复杂性。繁多的程序构造最为简略,循环和抉择所形成的环路越多,程序就越简单。 McCabe度量法以图论为工具,先画出程序图,而后用该图的环路数作为程序复杂性的度量值。程序图是进化的程序流程图。也就是说,把程序流程图的每一个解决符号都进化成一个结点,原来连贯不同解决符号的流线变成连贯不同结点的有向弧,这样失去的有向图就叫做程序图。 依据图论,在一个强连通的有向图G中,环的个数V(G)由以下公式给出: $$V(G)=m-n+2$$ 其中,V(G)是有向图G中环路数,m是图G中弧数,n是图G中结点数,p是图G中强连通重量个数。在一个程序中,从程序图的入口点总能达到图中任何一个结点,因而,程序总是连通的,但不是强连通的。为了使图成为强连通图,从图的进口点到入口点加一条用虚线示意的有向边,使图成为强连通图。这样就能够应用上式计算环路复杂性了。 有的也有用E来代表图G中弧数,即 $$V(G)=E-N+2$$ 例题: 例1 采纳McCabe度量法计算下图所示程序的环路复杂性为( ) A.1  B.2  C.3  D.4   解: 环形复杂度 $V(G)=M-N+2$,其中,E是流图中边的条数,M是结点数。 即 V(G) = 11-10+2 = 3 例2 下图用 白盒测试 办法进行测试,图中有( )条门路。采纳McCabe度量计算该程序图的环路复杂性为( ) 问题1 选项 A.3   B.4   C.5   D.6   问题2 选项 A.3   B.4   C.5   D.6   解: <p>将所有结点标注序号,依据图示,能够找到不同的门路共4条: 1-2-3-11;1-2-3-4-5-6-10-11;1-2-3-4-5-7-9-10-11;1-2-3-4-5-7-8-9-10-11。 第一空抉择B选项。 ...

September 19, 2023 · 1 min · jiezi

关于后端:LeetCode-mysql-刷题二电影评分判断日期的五种方法-审核中

题目题目链接:电影评分 请你编写一个解决方案: 查找评论电影数量最多的用户名。如果呈现平局,返回字典序较小的用户名。 查找在 February 2020 均匀评分最高 的电影名称。如果呈现平局,返回字典序较小的电影名称。 字典序 ,即按字母在字典中呈现程序对字符串排序,字典序较小则意味着排序靠前。 返回后果格局如下例所示。 Create table If Not Exists Movies (movie_id int, title varchar(30));Create table If Not Exists Users (user_id int, name varchar(30));Create table If Not Exists MovieRating (movie_id int, user_id int, rating int, created_at date);Truncate table Movies;insert into Movies (movie_id, title) values ('1', 'Avengers');insert into Movies (movie_id, title) values ('2', 'Frozen 2');insert into Movies (movie_id, title) values ('3', 'Joker');Truncate table Users;insert into Users (user_id, name) values ('1', 'Daniel');insert into Users (user_id, name) values ('2', 'Monica');insert into Users (user_id, name) values ('3', 'Maria');insert into Users (user_id, name) values ('4', 'James');Truncate table MovieRating;insert into MovieRating (movie_id, user_id, rating, created_at) values ('1', '1', '3', '2020-01-12');insert into MovieRating (movie_id, user_id, rating, created_at) values ('1', '2', '4', '2020-02-11');insert into MovieRating (movie_id, user_id, rating, created_at) values ('1', '3', '2', '2020-02-12');insert into MovieRating (movie_id, user_id, rating, created_at) values ('1', '4', '1', '2020-01-01');insert into MovieRating (movie_id, user_id, rating, created_at) values ('2', '1', '5', '2020-02-17');insert into MovieRating (movie_id, user_id, rating, created_at) values ('2', '2', '2', '2020-02-01');insert into MovieRating (movie_id, user_id, rating, created_at) values ('2', '3', '2', '2020-03-01');insert into MovieRating (movie_id, user_id, rating, created_at) values ('3', '1', '3', '2020-02-22');insert into MovieRating (movie_id, user_id, rating, created_at) values ('3', '2', '4', '2020-02-25');输出:Movies 表:+-------------+--------------+| movie_id | title |+-------------+--------------+| 1 | Avengers || 2 | Frozen 2 || 3 | Joker |+-------------+--------------+movie_id 是这个表的主键(具备惟一值的列)。title 是电影的名字。Users 表:+-------------+--------------+| user_id | name |+-------------+--------------+| 1 | Daniel || 2 | Monica || 3 | Maria || 4 | James |+-------------+--------------+user_id 是表的主键(具备惟一值的列)。MovieRating 表:+-------------+--------------+--------------+-------------+| movie_id | user_id | rating | created_at |+-------------+--------------+--------------+-------------+| 1 | 1 | 3 | 2020-01-12 || 1 | 2 | 4 | 2020-02-11 || 1 | 3 | 2 | 2020-02-12 || 1 | 4 | 1 | 2020-01-01 || 2 | 1 | 5 | 2020-02-17 || 2 | 2 | 2 | 2020-02-01 || 2 | 3 | 2 | 2020-03-01 || 3 | 1 | 3 | 2020-02-22 || 3 | 2 | 4 | 2020-02-25 |+-------------+--------------+--------------+-------------+(movie_id, user_id) 是这个表的主键(具备惟一值的列的组合)。这个表蕴含用户在其评论中对电影的评分 rating 。created_at 是用户的点评日期输入:Result 表:+--------------+| results |+--------------+| Daniel || Frozen 2 |+--------------+解释:Daniel 和 Monica 都点评了 3 部电影("Avengers", "Frozen 2" 和 "Joker") 然而 Daniel 字典序比拟小。Frozen 2 和 Joker 在 2 月的评分都是 3.5,然而 Frozen 2 的字典序比拟小。解析本题考查的知识点是应用 union all 将两张表后果合并起来 ...

September 19, 2023 · 3 min · jiezi

关于后端:ESS101系统标识规则

ESS101 Mod & SimSP1 2023Assignment 2 - System IdentificationIn this assignment, we will explore various aspects of parameter estimation including least-squares estimation andsystem identification. Write a small report providing the answers to the questions. For compute exercise, providethe answers in the report and a file with the Matlab code, too. 1. InstructionsThe assignments comprise an important part of the examination in thiscourse. Hence, it is important tocomply with the following rules and instructions: ...

September 19, 2023 · 5 min · jiezi

关于后端:ElasticSearch节点嗅探机制实践

背景介绍咱们小组次要负责四轮场景下的司乘匹配工作,基于开源分布式搜索引擎ElasticSearch实现订单的召回。同时咱们应用Flink实时生产kafka音讯,将订单数据写入到对应的ES索引中。 想要应用Elasticsearch服务,则要先创立一个能够连贯到ES集群的客户端。ES官网提供了很多版本的 Java 客户端,蕴含但不限于: Transport 客户端Low Level REST 客户端High Level REST 客户端Java API 客户端晚期咱们应用的是向SLB域名(SLB是负载平衡服务的缩写)发送申请,在SLB前面有配置对应的ES节点ip,应用SLB来实现负载平衡。但随着流量的增长,在节假日和线上压测时,经常出现SLB带宽超限的问题,影响零碎的稳定性。 于是咱们改用ip直连的形式,RestClient客户端自身自带ip节点的负载平衡策略,实现上应用了 Collections.rotate() 办法,感兴趣的能够能够看底层的算法思路。 尽管解决了SLB带宽超限的问题,但当初需手动配置ip列表,比拟容易出错,一旦配错一个节点,就会引起线上报错,而且每次扩缩容时都要进行ip列表的变更。 于是咱们开始调研节点的嗅探机制,先从官网文档动手。 官网文档给出的示例如下: RestClient restClient = RestClient.builder( new HttpHost("localhost", 9200, "http")) .build();Sniffer sniffer = Sniffer.builder(restClient) .setSniffIntervalMillis(60000).build();下面代码的含意就是初始化一个嗅探器,每60s更新一次节点列表。 还能够启用失败嗅探,在每次申请失败之后,节点列表都会立刻更新,而不是在下一轮一般的嗅探中更新。这种首先须要创立一个 SniffOnfalureListener,并在创立 RestClient 时设置一个监听器,在每次节点失败时告诉该监听器。 SniffOnFailureListener sniffOnFailureListener = new SniffOnFailureListener();RestClient restClient = RestClient.builder( new HttpHost("localhost", 9200)) .setFailureListener(sniffOnFailureListener) .build();Sniffer sniffer = Sniffer.builder(restClient) .setSniffIntervalMillis(60000) .build();sniffOnFailureListener.setSniffer(sniffer);除了嗅探器之外,还发现了另一个非凡的配置:节点选择器。 节点选择器能够实现对节点列表的过滤,比方我想过滤出协调节点,只向协调节点发送申请,就能够定义一个NodeSelector来实现。 源码分析上面咱们开始分析Sniffer组件的底层实现,先进入build()办法: public Sniffer build() { if (nodesSniffer == null) { this.nodesSniffer = new ElasticsearchNodesSniffer(restClient); } return new Sniffer(restClient, nodesSniffer, sniffIntervalMillis, sniffAfterFailureDelayMillis);}咱们能够看到实例化一个sniffer对象之前,先创立了一个nodeSniffer对象,指向的类型是ElasticsearchNodesSniffer,这个是真正的发送ES节点嗅探申请的类,咱们待会再看。 ...

September 19, 2023 · 3 min · jiezi

关于后端:CSSE7030-java-游戏算法

CSSE7030Assignment 2Semester 1, 2023CSSE1001/CSSE7030 1 IntroductionSokoban is a simple game in which a player tries to push crates onto goal locations in a grid. In assignment 2,you will create a slightly modified text-based version of Sokoban, in which the player may also need to collectpotions in order to be able to push all crates to goal locations within an allocated number of moves. Yourimplementation will follow the Apple Model-View Controller (MVC) structure mentioned in lectures.You are required to implement a collection of classes and methods as specified in Section 5 of this document.Your program’s output must match the expected output exactly; minor differences in output (such as whitespaceor casing) will cause tests to fail, resulting in zero marks for those tests. Any changes to this document will belisted in a changelog on Blackboard, and summarized on theEdstem megathread. ...

September 19, 2023 · 8 min · jiezi