码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 一些可以参考的文档集合10


     之前的文章集合:

    一些可以参考文章集合1_xuejianxinokok的博客-CSDN博客

    一些可以参考文章集合2_xuejianxinokok的博客-CSDN博客

    一些可以参考的文档集合3_xuejianxinokok的博客-CSDN博客

    一些可以参考的文档集合4_xuejianxinokok的博客-CSDN博客

    一些可以参考的文档集合5_xuejianxinokok的博客-CSDN博客

    一些可以参考的文档集合6_xuejianxinokok的博客-CSDN博客
    一些可以参考的文档集合7_xuejianxinokok的博客-CSDN博客
     

    一些可以参考的文档集合8_xuejianxinokok的博客-CSDN博客

     一些可以参考的文档集合9_xuejianxinokok的博客-CSDN博客


    20230309

     Spring Cloud Gateway夺命连环十问?-51CTO.COM传统的单体架构中只有一个服务开放给客户端调用,但是微服务架构中是将一个系统拆分成多个微服务,那么作为客户端如何去调用这些微服务呢?如果没有网关的存在,只能在本地记录每个微服务的调用地址。https://www.51cto.com/article/748557.html


    20230326

    LoadBalancer

    由于互联网技术的发展,网络数据的请求数节节攀升,这使得服务器承受的压力越来越大。在早期的系统架构中,通常使用 Load Balancer 来将网络流量平摊到多个服务器中,以此减轻单台服务器的压力。但是现如今,后端服务的种类在不断地变多,每个种类的后端都以 API 的形式对外暴露,这使得 API 的数量也在不断变多。以传统的 Load Balancer 为主的系统架构的局限性就变得明显起来,因为它主要工作在四层,在七层上功能较弱,于是一款主要工作在七层且具有丰富扩展能力的基础设施便应运而生,它就是 API Gateway。

    Load Balancer 的主要作用是为多个后端服务提供负载均衡功能,依据不同的负载均衡算法让这些服务可以分摊流量。Load Balancer 的历史非常悠久,从演进路径上看大致可以分为以下这几个阶段:

    • 第一阶段(2000 以前):这一阶段的 Load Balancer 通常由硬件设备组成,具有高性能、高可靠性的特点,但灵活性较差,价格昂贵。比较典型的是 F5 这种基于硬件的 Load Balancer 。

    • 第二阶段(2000-2010):Load Balancer 开始以软件形式实现,使其更加灵活和可扩展,通常以软件分发的形式出现,因此价格也比较低廉,比如 LVS 就属于这一类。

    • 第三阶段(2010 至今):随着云计算技术的兴起,Load Balancer 也开始有了云版本,这个版本的 Load Balancer 其中一个好处是可以帮助企业以更低的成本获得高性能的负载均衡服务,另一个好处是它能够利用云计算的可扩展性和弹性的特点来提高整体可用性。例如 AWS 的 Classic Load Balancer、Application Load Balancer、Network Load Balancer 等。

    LoadBalancer 听名字就知道跟负载均衡有关。这个类型与 NodePort 很相似,目的都是向外部暴露一个端口,主要的区别在于 LoadBalancer 会在集群的外部再做一个负载均衡器,而这个设备是需要外部环境支持的,外部环境发送到这个设备的请求,会被设备负载之后转发到集群中。

    图中有个Vip的概念,这里的Vip指的是 Vitual IP,也就是虚拟IP,外部用户通过访问这个虚拟IP,可以负载到我们不同的service上,达到负载均衡和高可用的特点

    API Gateway 简单来说是一种主要工作在七层、专门用于 API 的管理和流量转发的基础设施,并在此基础上拥有 Load Balancer 所不具备的强大的扩展性,比如:认证、可观测性、自定义插件等等。API Gateway 支持各式的自定义开发,比如支持丰富的编程语言、支持在流量转发的不同阶段注入自定义的处理逻辑,而 Load Balancer 基本不支持任何自定义功能开发。

    还有一点就是 Load Balancer 通常采用流量直接分发的形式做负载均衡,它通过算法将流量数据直接发向某个后端服务器节点。这意味着后端等待接收流量的每一个服务实例行为都必须是一致的,减少了一定的灵活性。而 API Gateway 则是以 URL Path 、Domain、Header 等维度进行流量分发,后端等待接收流量的服务实例可以多种多样,可以是某个 Private API,也可以是某个 gRPC 的 API,使流量分发变得十分地灵活。

    对于需要大流量、极高稳定性的网络出入口的场景,工作在四层的 Load Balancer 显然更为适用。它可以把网络原始四层流量直接分发到各个后端服务中,不存在中间层多次解析应用层协议的影响,具有更强的吞吐能力。

    而工作在七层的 API Gateway 作为统一的入口,由于需要解析协议,因此存在一定的吞吐量限制。即使是使用四层的 API Gateway 来做网络出入口也不太有优势,因为这一层不是 API Gateway 的侧重点,相比于 Load Balancer 多年在这一层的技术累计,API Gateway 优势也不明显。

    在合理的架构设计下,一般都将 API Gateway 和 Load Balancer 配合使用,使用 Load Balancer 作为整个系统的网络出入口,将流量分发到多个 API Gateway 实例,然后每个 API Gateway 实例分别对请求进行路由、认证、鉴权等操作,这样可以使得整个网络更加稳健、可靠、可扩展。

    《Kubernetes》,你需要掌握的 Service 和 Ingress-51CTO.COMk8s 我们已经从 NameSpace、Pod、PodController到Volumn都介绍过了,相信看完的小伙伴们也会很有收获的~那么今天我们继续来到k8s的课堂,这节我们将要来说下 k8S 搭建完服务后如何访问!https://www.51cto.com/article/665538.html

    API 网关和负载均衡器,到底怎么选?_文化 & 方法_陈泵_InfoQ精选文章API 网关和负载均衡器,到底怎么选? 本文介绍了LoadBalancer和APIGateway的功能特点,并探讨了它们之间的区别,希望可https://www.infoq.cn/article/mDlgpAcKK4V3Qr4r9d8E


    API 网关最好是支持 I/O 异步、同步非阻塞的,如果服务是同步阻塞调用,可以理解为微服务模块之间是没有彻底解耦的,即如果A依赖B提供的API,如果B提供的服务不可用将直接影响到A不可用,除非同步服务调用在API网关层或客户端做了相应的缓存。因此为了彻底解耦,在微服务调用上更建议选择异步方式进行。而对于 API 网关需要通过底层多个细粒度的 API 组合的场景,推荐采用响应式编程模型进行而不是传统的异步回调方法组合代码,其原因除了采用回调方式导致的代码混乱外,还有就是对于 API 组合本身可能存在并行或先后调用,对于采用回调方式往往很难控制。

    流量网关与服务网关的区别

    流量网关和服务网关在系统整体架构中所处的位置如图所示,流量网关(如Nignx)是指提供全局性的、与后端业务应用无关的策略,例如 HTTPS证书卸载、Web防火墙、全局流量监控等。而微服务网关(如Spring Cloud Gateway)是指与业务紧耦合的、提供单个业务域级别的策略,如服务治理、身份认证等。也就是说,流量网关负责南北向流量调度及安全防护,微服务网关负责东西向流量调度及服务治理。

    【升级】Spring Cloud Gateway 4来了服务网关传统的单体架构中只需要开放一个服务给客户端调用,但是微服务架构中是将一个系统拆分成多个微服务,如果没https://mp.weixin.qq.com/s/QCiZcsvwmL90rpmYszN4_w


    20230303

    Manticore Search 是一个易于使用的开源快速搜索数据库。Elasticsearch 的不错替代品。

    GitHub - manticoresoftware/manticoresearch: Easy to use open source fast database for search | Good alternative to Elasticsearch now | Drop-in replacement for E in the ELK soonEasy to use open source fast database for search | Good alternative to Elasticsearch now | Drop-in replacement for E in the ELK soon - GitHub - manticoresoftware/manticoresearch: Easy to use open source fast database for search | Good alternative to Elasticsearch now | Drop-in replacement for E in the ELK soonhttps://github.com/manticoresoftware/manticoresearch


    20230221

    事件监听器

    内存泄漏的另一个常见原因是事件监听器,当您将事件侦听器附加到元素时,它会创建对侦听器函数的引用,该函数可以防止垃圾收集器释放元素使用的内存。如果在不再需要该元素时未删除侦听器函数,这可能会导致内存泄漏。

    我们一起来看一个例子:

    复制

    1. let button = document.getElementById("my-button");
    2. // attach an event listener to the button
    3. button.addEventListener("click", function() {
    4. console.log("Button was clicked!");
    5. });
    6. // do something with the button
    7. // ...
    8. // remove the button from the DOM
    9. button.parentNode.removeChild(button);

    在此示例中,我们将事件侦听器附加到按钮元素,然后从 DOM 中删除该按钮。即使按钮元素不再存在于文档中,事件侦听器仍附加到它,这会创建对侦听器函数的引用,以防止垃圾收集器释放该元素使用的内存。如果在不再需要该元素时未删除侦听器函数,这可能会导致内存泄漏。

    为避免此类内存泄漏,在不再需要该元素时删除事件侦听器很重要:

    复制

    1. button.removeEventListener("click", function() {
    2. console.log("Button was clicked!");
    3. });

    另一种方法是使用 EventTarget.removeAllListeners() 方法删除所有已添加到特定事件目标的事件侦听器。

    复制

    button.removeAllListeners();

    使用垃圾收集器 API

    另一种内存管理技术是使用垃圾收集器 API,它允许您手动触发垃圾收集并获取有关堆当前状态的信息。

    这对于调试内存泄漏和性能问题很有用。

    以下是一个例子:

    复制

    1. let object1 = {};
    2. let object2 = {};
    3. // create a circular reference between object1 and object2
    4. object1.next = object2;
    5. object2.prev = object1;
    6. // manually trigger garbage collection
    7. gc();

    在此示例中,我们创建了两个对象,object1 和 object2,并通过向它们添加 next 和 prev 属性在它们之间创建循环引用。然后,我们使用 gc() 函数手动触发垃圾收集,这将释放对象使用的内存,即使它们仍在被引用。

    请务必注意,并非所有 JavaScript 引擎都支持 gc() 函数,其行为也可能因引擎而异。还需要注意的是,手动触发垃圾回收会对性能产生影响,因此,建议谨慎使用,仅在必要时使用。

    除了 gc() 函数,JavaScript 还为一些 JavaScript 引擎提供了 global.gc() 和 global.gc() 函数,也为一些浏览器引擎提供了 performance.gc() ,可以用来检查 堆的当前状态并测量垃圾收集过程的性能。

    3. 使用堆快照和分析器

    JavaScript 还提供堆快照和分析器,可以帮助您了解您的应用程序如何使用内存。堆快照允许您拍摄堆当前状态的快照并对其进行分析以查看哪些对象使用的内存最多。

    下面是一个示例,说明如何使用堆快照来识别应用程序中的内存泄漏:

    复制

    1. // Start a heap snapshot
    2. let snapshot1 = performance.heapSnapshot();
    3. // Do some actions that might cause memory leaks
    4. for (let i = 0; i < 100000; i++) {
    5. myArray.push({
    6. largeData: new Array(1000000).fill("some data"),
    7. id: i
    8. });
    9. }
    10. // Take another heap snapshot
    11. let snapshot2 = performance.heapSnapshot();
    12. // Compare the two snapshots to see which objects were created
    13. let diff = snapshot2.compare(snapshot1);
    14. // Analyze the diff to see which objects are using the most memory
    15. diff.forEach(function(item) {
    16. if (item.size > 1000000) {
    17. console.log(item.name);
    18. }
    19. });

    在此示例中,我们在执行将大数据推送到数组的循环之前和之后拍摄两个堆快照,然后,比较这两个快照以识别在循环期间创建的对象。

    接着,我们可以分析差异以查看哪些对象使用了最多的内存,这可以帮助我们识别由大数据引起的内存泄漏。

    分析器允许您跟踪应用程序的性能并识别内存使用率高的区域:

    复制

    1. let profiler = new Profiler();
    2. profiler.start();
    3. // do some actions that might cause memory leaks
    4. for (let i = 0; i < 100000; i++) {
    5. myArray.push({
    6. largeData: new Array(1000000).fill("some data"),
    7. id: i
    8. });
    9. }
    10. profiler.stop();
    11. let report = profiler.report();
    12. // analyze the report to identify areas where memory usage is high
    13. for (let func of report) {
    14. if (func.memory > 1000000) {
    15. console.log(func.name);
    16. }
    17. }

    在这个例子中,我们使用 JavaScript 分析器来开始和停止跟踪我们应用程序的性能。该报告将显示有关已调用函数的信息以及每个函数的内存使用情况。

    并非所有 JavaScript 引擎和浏览器都支持堆快照和分析器,因此在您的应用程序中使用它们之前检查兼容性很重要。

    JavaScript 内存管理:如何避免常见的内存泄漏并提高性能-51CTO.COM


    20230217

    我如何在 SerenityOS 上谋生

    How I make a living working on SerenityOS – Andreas Kling – I like computers!This post describes in detail how I support myself while working on the SerenityOS project.https://awesomekling.github.io/How-I-make-a-living-working-on-SerenityOS/


    20230216

    volatile禁止指令重排序

    volatile除了可见性保证之外,还提供了“Happens-Before”的保证:

    1. 如果一个读写最初发生在写入volatile变量之前,那他就不会被重排序到这个写入volatile变量之后发生。

    2. 如果一个读写发生在读取volatile变量之后,那他就不会被重排序到这个读取volatile变量之前发生。

      // c是一个volatile变量a = 1;b = 2;//此时 a和b 的读写操作不会被重排序到c的赋值操作之后执行。也就是说a和b的读写操作此刻一定执行了c = 3; //但d = 4可能会被重排序到c的赋值操作之前执行。d = 4;

    3. 如果一个读写发生在读取volatile变量之后,那他就不会被重排序到这个读取volatile变量之前发生。

      // c是一个volatile变量,c = 3;a = 1;b = 2; //此时发生对c的读取操作,那d = 4不会被被重排序到c的读取之前执行,也就是说此刻d的读写一定还没被执行//但 a和b 的读写此时也不一定执行了,他们可能会被重排序到c的读取操作之后执行。x = c; d = 4

    禁止指令重排序

            在java实现单例模式中有个volatile的经典用法。下面举例说明

    public class Singleton {      private static Singleton instance;      private Singleton (){}        public static Singleton getInstance() {          if (instance == null) {            instance = new Singleton();          }          return instance;      }
    }

            上述单例模式会存在线程安全问题,在instance未初始化之前,当多线程并发时,instance == null 的判断都返回true,结果会导致多个线程重复初始化 Signleton 类

    加锁改进,保证线程安全:

    public class Singleton {      private static Singleton singleton;  // 语句1    //private volatile static Singleton singleton; 语句2    private Singleton (){}      public static Singleton getSingleton() {        if (singleton == null) {  //语句3          synchronized (Singleton.class) {                if (singleton == null) {                    singleton = new Singleton();  //语句4              }            }        }        return singleton;      }
    }

        当我们加上synchronized和双重校验时,能保证线程安全,同一时间只有一个线程可以初始化Singleton类,但仍存在一个问题,语句4是非原子性操作,前面说到对象的初始化可以分为3个步骤(划分内存区域,初始化对象,将对象的引用赋予变量),指令重排序可能在对象初始化完成前就将对对象的引用赋予变量,那此时如果另外一个线程执行到语句3时,发现已经有对像引用,不为null,就直接拿到一个未初始化完成的对象,可能会造成业务报错。

        解决方法只需要对singleton 变量使用volatile修饰,即将语句1替换成语句2,阻止语句4内部的指令重排序,保证最终拿到的单例对象一定是初始化完成后的对象。

    单例模式的双重锁为什么要加volatile

    需要volatile关键字的原因是,在并发情况下,如果没有volatile关键字,在第5行会出现问题。instance = new TestInstance();可以分解为3行伪代码

    a. memory = allocate() //分配内存

    b. ctorInstanc(memory) //初始化对象

    c. instance = memory //设置instance指向刚分配的地址

    上面的代码在编译运行时,可能会出现重排序从a-b-c排序为a-c-b。在多线程的情况下会出现以下问题。当线程A在执行第5行代码时,B线程进来执行到第2行代码。假设此时A执行的过程中发生了指令重排序,即先执行了a和c,没有执行b。那么由于A线程执行了c导致instance指向了一段地址,所以B线程判断instance不为null,会直接跳到第6行并返回一个未初始化的对象。

    如何保证可见性?

    在JVM底层volatile是采用“内存屏障”来实现的。观察加入volatile关键字和没有加入volatile关键字时所生成的汇编代码发现,加入volatile关键字时,会多出一个lock前缀指令,lock前缀指令实际上相当于一个内存屏障(也成内存栅栏),内存屏障会提供3个功能:

    I. 它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;

    II. 它会强制将对缓存的修改操作立即写入主存;

    III. 如果是写操作,它会导致其他CPU中对应的缓存行无效。

    Volatile关键字看它就够了!最详细的一篇介绍。Java中的Volatile关键字最详细的一篇介绍文章,看完就回深刻理解和使用它。https://mp.weixin.qq.com/s/68TfPtatl1drZYB2kxBVAQ

    Java中 volatile 关键字的最全总结,赶快给自己查缺补漏吧!Java中volatile关键字的最全总结https://mp.weixin.qq.com/s/snxOvuED1KvrOVexdsutSg

    从 B 站出发,用 Chrome devTools performance 分析页面如何渲染

    从 B 站出发,用 Chrome devTools performance 分析页面如何渲染一文讲透页面渲染那些事……https://mp.weixin.qq.com/s/n7crw4NBsGiZPeYaX7BFrg


     20230201

    Java agent 是在 JDK 1.5 中引入的,它允许我们在处于运行状态的 JVM 中,修改组成类的字节,在这个过程中,并不需要这些类的源码。

    字节码操纵技术探秘_Java_Victor Grazi_InfoQ精选文章字节码操纵技术探秘大家可能已经非常熟悉下面的处理流程:将一个“.java”文件输入到Java编译器中(可能会使用javhttps://www.infoq.cn/news/Living-Matrix-Bytecode-Manipulation


    20230131

    JVM 在设计之初,就考虑到了虚拟机状态的监控、程序 Debug、线程和内存分析等功能。

    在 JDK1.5 之前,JVM 规范就定义了 JVMPI(Java Virtual Machine Profiler Interface)也就是 JVM 分析接口以及 JVMDI(Java Virtual Machine Debug Interface)也就是 JVM 调试接口,JDK1.5 以及以后的版本,这两套接口合并成了一套,也就是 Java Virtual Machine Tool Interface,就是 JVMTI 。通过 JVMTI 可以探查 JVM 内部的一些运行状态,甚至控制 JVM 应用程序的执行。

    Byte Buddy

    Byte Buddy 是致力于解决字节码操作和 Instrumentation API 的复杂性的开源框架。Byte Buddy 所声称的目标是将显式的字节码操作隐藏在一个类型安全的领域特定语言背后。通过使用 Byte Buddy,任何熟悉 Java 编程语言的人都容易地进行字节码操作。

    官网的示例展现了如何生成一个简单的类,这个类是 Object 的子类,并且重写了 toString 方法,用来返回“Hello World!”与原始的 ASM 类似,intercept 会告诉 Byte Buddy 为拦截到的指令提供方法实现。

    Class<?> dynamicType = new ByteBuddy()  .subclass(Object.class)  .method(ElementMatchers.named("toString"))  .intercept(FixedValue.value("Hello World!"))  .make()  .load(getClass().getClassLoader())  .getLoaded();System.out.println(dynamicType.getSimpleName());// 输出:Object$ByteBuddy$ilIxkTl1

    字节码增强工具对比

    框架ASMJavassistJDK ProxyCglibByteBuddy
    起源时间20021999200020112014
    增强方式字节码指令字节码指令和源码(注:源码文本)源码源码源码
    源码编译NA不支持支持支持支持
    Agent支持支持支持不支持,依赖框架不支持,依赖框架支持
    性能高中低中中
    维护状态是是停止升级停止维护活跃
    优点超高性能,应用场景广泛同时支持字节码指令和源码两种增强方式JDK原生类库支持零侵入,提供良好的API扩展编程
    缺点字节码指令对应用开发者不友好场景非常局限,只适用于Java接口已经不再维护,对于新版JDK17+支持不好,官网建议切换到ByteBuddy
    应用场景小,高性能,广泛用于语言级别广泛用于框架场景广泛用于Trace场景

    Java 自动化探针技术的核心原理和实践_语言 & 开发_蒋志伟_InfoQ精选文章Java 自动化探针技术的核心原理和实践JVMTI技术JVM在设计之初,就考虑到了虚拟机状态的监控、程序Debug、线程和内存分析等功能。 https://www.infoq.cn/article/JYWWVhcGCWL7vGK1RIap

    Spring AOP之切入点Pointcut API详细介绍及使用-51CTO.COM通过XML或Java风格的配置启用@AspectJ支持。在这两种情况下,还需要确保AspectJ的aspectjweaver.jar库位于应用程序的类路径上(版本1.8或更高)。https://www.51cto.com/article/745270.html


    20230130

    Consumer媒体类型

    你可以根据请求的Content-Type缩小请求映射,示例如下:​

    1. // 使用consumes属性按内容类型缩小映射范围
    2. @PostMapping(path = "/pets", consumes = "application/json")
    3. public void addPet(@RequestBody Pet pet) {
    4. // ...
    5. }

    consume属性还支持否定表达式——例如,!text/plain表示除text/plain以外的任何内容类型。

    你可以在类级别声明共享消费属性。然而,与大多数其他请求映射属性不同的是,当在类级使用时,方法级使用属性重写,而不是扩展类级声明。

    MediaType为常用的媒体类型提供常量,例如APPLICATION_JSON_VALUE和APPLICATION_XML_VALUE。

    Producer媒体类型

    你可以根据Accept请求头和控制器方法产生的内容类型列表来缩小请求映射,如下面的例子所示:​

    1. // 使用produces属性按内容类型缩小映射范围。
    2. @GetMapping(path = "/pets/{petId}", produces = "application/json")
    3. @ResponseBody
    4. public Pet getPet(@PathVariable String petId) {
    5. // ...
    6. }

    媒体类型可以指定字符集。支持非表达式——例如,!text/plain表示除“text/plain”之外的任何内容类型。

    你可以在类级别声明一个共享的produces属性。然而,与大多数其他请求映射属性不同的是,当在类级使用时,方法级产生属性重写,而不是扩展类级声明。

    请求参数与Header

    可以根据请求参数条件缩小请求映射。你可以测试是否有请求参数(myParam),或者是否有特定的值(myParam=myValue)。下面的例子展示了如何测试一个特定的值:​

    1. // 测试myParam是否等于myValue
    2. @GetMapping(path = "/pets/{petId}", params = "myParam=myValue")
    3. public void findPet(@PathVariable String petId) {
    4. // ...
    5. }

    你也可以使用相同的请求头条件,如下面的例子所示:​

    1. // 测试myHeader是否等于myValue
    2. @GetMapping(path = "/pets", headers = "myHeader=myValue")
    3. public void findPet(@PathVariable String petId) {
    4. // ...
    5. }

    编程方式注册

    你可以以编程方式注册处理程序方法,可以将其用于动态注册或高级情况,例如不同url下相同处理程序的不同实例。下面的例子注册了一个处理器方法:​

    1. @Configuration
    2. public class MyConfig {
    3. @Autowired
    4. public void setHandlerMapping(RequestMappingHandlerMapping mapping, UserHandler handler) throws NoSuchMethodException {
    5. RequestMappingInfo info = RequestMappingInfo.paths("/user/{id}").methods(RequestMethod.GET).build();
    6. // 指定接口处理的方法
    7. Method method = UserHandler.class.getMethod("getUser", Long.class);
    8. mapping.registerMapping(info, handler, method);
    9. }
    10. }

    SpringMVC接口定义RequestMapping这些细节你用过吗?-51CTO.COMSpring MVC支持对请求映射使用组合注释。这些注释本身是用@RequestMapping进行元注释的,并且组合起来重新声明@RequestMapping属性的一个子集(或全部),目的更窄、更具体。https://www.51cto.com/article/745175.html


    20230113

    宽度代表了执行的时间,超过 50ms 就被任务是长任务,需要优化。

    长度代表了调用栈深度,一般特别长的都是有递归在。

     通过 Performance 证明,网页的渲染是一个宏任务用调试工具分析网页的执行过程https://mp.weixin.qq.com/s?__biz=Mzg3OTYzMDkzMg==&mid=2247486730&idx=1&sn=c2267ac48b09f85022c33317fbac1a91&chksm=cf00c231f8774b27ecaf61ac16683aa63ff8c115243be2bba9d8182e41aa71c25de51fec9e59&scene=178&cur_album_id=2150427089953521666#rd快速掌握 Performance 性能分析:一个真实的优化案例通过 Chrome Devtools Performance 做性能分析和优化https://mp.weixin.qq.com/s?__biz=Mzg3OTYzMDkzMg==&mid=2247487220&idx=1&sn=ebd2e335a8a5d2fd11a12c2a0d89ec67&chksm=cf00c1cff87748d94243820afa2268ca66abef8f325608c1b7ae2aa2e2a559e74b2ef589bcba&scene=178&cur_album_id=2150427089953521666#rd

    会用 Performance 工具,就能深入理解 Event Loop用 performance 工具分析网页执行流程https://mp.weixin.qq.com/s/22tS74K5JQr1V98Q4DPqJg

     从 B 站出发,用 Chrome devTools performance 分析页面如何渲染一文讲透页面渲染那些事……https://mp.weixin.qq.com/s/n7crw4NBsGiZPeYaX7BFrg


    20230112

    图解浏览器的多进程渲染机制浏览器的不同进程之间是如何配合,最终渲染页面的?https://mp.weixin.qq.com/s/6QR7niKFHY4StFZwDRfyKQ

    JS 的异步机制一探异步机制是通往 JavaScript 精通之路的重要环节,在日常编程中如果理解不足,容易留下难以排查的 Bug,本文先介绍 JavaScript 异步编程发展历程,再通过实例来说明不同场景下异步编程的注意点。https://mp.weixin.qq.com/s/jfXQgAR6Su8yvwgc24g-Lw

    (10月最新) 前端图形学实战: 从零开发几何画板(vue3 + vite版)前端图形学实战https://mp.weixin.qq.com/s?__biz=MzU2Mzk1NzkwOA==&mid=2247494644&idx=1&sn=e233f6c3ecd9e039a4c1adf1594fa2f8&chksm=fc50f20fcb277b19bf6aff944b103ae28242d50d04fab99d1bfc253f97ba7d91324df4ac3ca7&token=264195061&lang=zh_CN#rd

    你只会用前端数据埋点 SDK 吗?https://mp.weixin.qq.com/s/9Qwp6g8QKFK2ehDLyEu0Wg

    在前端 Network 还能这样玩 - 全栈修仙之路 - SegmentFault 思否这几年手机和网络已经是大多数人生活中的必需品,其中有很多人,比如我家”超哥“,她每次到一个新的环境中一般开口都会来一句,”请问你家有 WIFI 么,密码是多...https://segmentfault.com/a/1190000021894327


    多种Bean自动映射工具对比 | LiJing's Blog用一个属性拷贝工具,把vo转成dto,是 Apache 的还是 Spring 的,还是其他的什么,哪个效率最高?接下来用数据验证下,并提供出各种案例的使用对比。https://xiaojingge.com/blog/posts/1202366877.html

    Vue3必学技巧-自定义HooksVue3时代Composition Api,通过利用各种Hooks和自定义Hooks将碎片化的响应式变量和方法按功能分块写,实现高内聚低耦合https://mp.weixin.qq.com/s/SUMBFEzwhP7-3dx0XSeLbA


    ModelMapper 是一个 Object To Object 的工具,类似于 MapStruct又不同于 MapStruct。主要原因是 ModelMapper 是利用反射的原理实现的 Object To Object。

    ModelMapper - Getting StartedModelMapper is an intelligent, refactoring safe object mapping library that automatically maps objects to each other. It uses a convention based approach while providing a simple refactoring safe API for handling specific use cases.http://modelmapper.org/getting-started/

    目录
     一,滤波器与卷积核
     二,卷积层和池化输出大小计算
     三,深度学习框架的张量形状格式
     四,Pytorch 、Keras 的池化层函数理解
     五,Pytorch 和 Keras 的卷积层函数理解
     六,softmax 回归
     七,交叉熵损失函数
     八,感受野理解
     九,卷积和池化操作的作用
     十,卷积层与全连接层的区别
     十一,CNN 权值共享问题
     十二,CNN 结构特点
     十三,深度特征的层次性
     十四,什么样的数据集不适合深度学习
     十五,什么造成梯度消失问题
     十六,Overfitting 和 Underfitting 问题
     十七,L1 和 L2 区别
     十八,TensorFlow计算图概念
     十九,BN(批归一化)的作用
     二十,什么是梯度消失和爆炸
     二十一,RNN循环神经网络理解
     二十二,训练过程中模型不收敛,是否说明这个模型无效,导致模型不收敛的原因
     二十三,VGG 使用 2 个 3*3 卷积的优势
     二十四,Relu比Sigmoid效果好在哪里?
     二十五,神经网络中权值共享的理解
     二十六,对 fine-tuning(微调模型的理解),为什么要修改最后几层神经网络权值?
     二十七,什么是 dropout?
     二十八,HOG 算法原理描述
     二十九,激活函数
     三十,卷积层和池化层有什么区别
     三十一,卷积层和池化层参数量计算
     三十二,神经网络为什么用交叉熵损失函数
     三十三,数据增强方法有哪些
     三十四,ROI Pooling替换为ROI Align的效果,及各自原理
     三十五,CNN的反向传播算法推导
     三十六,Focal Loss 公式
     三十七,快速回答
     三十八,交叉验证的理解和作用
     三十九,介绍一下NMS和IOU的原理
     Reference
    -----------------------------------
    ©著作权归作者所有:来自51CTO博客作者嵌入式视觉的原创作品,请联系作者获取转载授权,否则将追究法律责任
    大厂必考深度学习算法面试题总结
    https://blog.51cto.com/armcvai/5991130

    大厂必考深度学习算法面试题总结_嵌入式视觉的技术博客_51CTO博客大厂必考深度学习算法面试题总结,包含深度学习基础、CNN模型、机器学习等知识点的必考算法面试题https://blog.51cto.com/armcvai/5991130


    20230105

    用这四招优雅地实现 Spring Boot 异步线程间数据传递-51CTO.COMTaskDecorator是什么?官方api的大致意思:这是一个执行回调方法的装饰器,主要应用于传递上下文,或者提供任务的监控/统计信息。https://www.51cto.com/article/743928.html

    @Column

    当实体的属性与其映射的数据库表的列不同名时需要使用@Column 标注说明,该注解通常置于实体的属性前或属性的getter方法之前,还可与 @Id 标注一起使用。

    • name:用于设置映射数据库表的列名。
    • unique:是否是唯一标识,默认为 false(不唯一)
    • nullable:否允许为 null,默认为true(null)
    • insertable:表示在 ORM 框架执行插入操作时,该字段是否应出现 INSERT 语句中,默认为true
    • updatable:表示在 ORM 框架执行更新操作时,该字段是否应该出现在 UPDATE 语句中,默认为 true。对于一经创建就不可以更改的字段,该属性非常有用,如对于birthday字段。或者创建时间/注册时间(可以将其设置为 false 不可修改)。
    • length:数据长度,仅对String类型的字段有效,默认值255
    • precision、scale:表示精度,当字段类型为double时,precision表示数值的总长度,scale表示小数点所占的位数,默认值均为0。
    • columnDefinition:表示该字段在数据库中的实际类型。通常ORM框架可以根据属性类型自动判断数据库中字段的类型,但是如果要将 String 类型映射到特定数据库的 BLOB 或 TEXT 字段类型,该属性非常有用。

    @Temporal

    对于日期时间属性映射时,可使用 @Temporal 注解来调整精度。

    • DATE:日期
    • TIME:时间
    • TIMESTAMP:日期时间

    复制

    1. @Data
    2. @Entity
    3. @Table(name = "student_info")
    4. public class Student {
    5. @Column
    6. @Temporal(TemporalType.DATE)
    7. private Date birthday;
    8. }

    @DynamicInsert、@DynamicUpdate

    • @DynamicInsert:设置为true,表示insert对象的时候,生成动态的insert语句,如果这个字段的值是null就不会加入到insert语句中。
    • @DynamicUpdate:设置为true,表示update对象的时候,生成动态的update语句,如果这个字段的值是null就不会被加入到update语句中。

    复制

    1. @Data
    2. @Entity
    3. @Table(name = "user_info")
    4. @DynamicInsert
    5. @DynamicUpdate
    6. public class User {
    7. @Id
    8. @Column(name = "id")
    9. @GenericGenerator(name="idGenerator", strategy="uuid")
    10. @GeneratedValue(generator = "idGenerator")
    11. private String id;
    12. @Column(name = "name")
    13. private String name;
    14. @Basic
    15. private Integer age;
    16. @Column(name = "create_time")
    17. private Long createTime;
    18. @Column(name = "remark")
    19. private String remark;
    20. }

    JPA实体类注解,看这篇就全会了-51CTO.COM当实体类与其映射的数据库表名不同名时需要使用@Table标注说明,该标注与@Entity标注并列使用,置于实体类声明语句之前。https://www.51cto.com/article/743932.html


    20221229

    分词器的设置

    Chinese | RedisChinese supporthttps://redis.io/docs/stack/search/chinese/

    RedisJson和RedisSearch探究(三)_六狗回来的博客-CSDN博客_redis search这一篇,讨论RedisSearch如何通过java进行操作。RedisSearch是一个搜索的工具,在搜索的时候,它会先将要搜索的内容进行分词处理,创建索引的时候也会分词。对于英文来说,分词比较简单,基本上空格和标点符号就可以,但是中文分词相对复杂一些,因为中文不能通过空格进行简单的分词。现在有各种不同的中文分词器,比如jieba,IK已经RedisSearch使用的分词器:friso。friso在gitee上可以找到:https://gitee.com/lionsoul/frisofrishttps://blog.csdn.net/hebeiqiaozhonghui/article/details/122739332

    20221228

    1. <!-- https://mvnrepository.com/artifact/com.redislabs/jredisearch -->
    2. <dependency>
    3. <groupId>com.redislabs</groupId>
    4. <artifactId>jredisearch</artifactId>
    5. <version>2.2.0</version>
    6. </dependency>
    1. import io.redisearch.client.AddOptions;
    2. import io.redisearch.client.Client;
    3. import io.redisearch.Document;
    4. import io.redisearch.SearchResult;
    5. import io.redisearch.Query;
    6. import io.redisearch.Schema;
    7. public class RediSearchExample {
    8. public static void main(String[] args) {
    9. // 连接 Redis 服务器和指定索引
    10. Client client = new Client("myidx", "127.0.0.1", 6379);
    11. // 定义索引
    12. Schema schema = new Schema().addTextField("title",
    13. 5.0).addTextField("desc", 1.0);
    14. // 删除索引
    15. client.dropIndex();
    16. // 创建索引
    17. client.createIndex(schema, Client.IndexOptions.Default());
    18. // 设置中文编码
    19. AddOptions addOptions = new AddOptions();
    20. addOptions.setLanguage("chinese");
    21. // 添加数据
    22. Document document = new Document("doc1");
    23. document.set("title", "天气预报");
    24. document.set("desc", "今天的天气很好,是个阳光明媚的大晴天,有蓝蓝的天空和白白的云朵。");
    25. // 向索引中添加文档
    26. client.addDocument(document,addOptions);
    27. // 查询
    28. Query q = new Query("天气") // 设置查询条件
    29. .setLanguage("chinese") // 设置为中文编码
    30. .limit(0,5);
    31. // 返回查询结果
    32. SearchResult res = client.search(q);
    33. // 输出查询结果
    34. System.out.println(res.docs);
    35. }
    36. }

    1. 127.0.0.1:6379> ft.add myidx doc1 1.0 fields title "He urged her to study English" desc "good idea"
    2. OK
    3. 127.0.0.1:6379> ft.search myidx "english" limit 0 10
    4. 1) (integer) 1
    5. 2) "doc1"
    6. 3) 1) "title"
    7. 2) "He urged her to study English"
    8. 3) "desc"
    9. 4) "good idea"
    10. 127.0.0.1:6379> ft.add myidx doc2 1.0 language "chinese" fields title "Java 14 发布了!新功能速览" desc "Java 14 在 2020.3.17 日发布正式版了,但现在很多公司还在使用 Java 7 或 Java 8"
    11. OK
    12. 127.0.0.1:6379> ft.search myidx "正式版"
    13. 1) (integer) 0

    轻量级搜索引擎-RediSearch - 简书Clickhouse最佳实践[https://www.jianshu.com/p/a72a4782a102] RediSearch 是一个高性能的全文搜索引擎,它可以作为一个...https://www.jianshu.com/p/8c7fc78a6f57


    20221220

    软件的复杂度包括本质复杂度和偶然复杂度。本质复杂度就是在解决问题时,无论如何都必须要面对的复杂度;而偶然复杂度,是由于选用的做事方法不当,导致额外增加的复杂度。

    为什么大家更偏向复杂而远离简单,除了缺少思考,找不到问题的核心解以外,还有一个重要原因就是为了所谓的“证明自己”。

    如同 DDD 在中小系统所带来的灾难一样,根本原因更多是因为大家并不愿意承认自己的系统是中小系统,自己所承接的业务是偏向简单的业务。最终导致简单的模块赋以复杂的束缚,最终效率被工具本身所制约。

    ‘复杂’总是伴随着光环,当我们解决一个复杂问题后,我们会得到更多人的肯定,向大家证明和展示自己的实力。而简单往往更‘暗淡’,如同上文提到的互换瓶盖,大家并不会因此认可服务生的能力,甚至觉得也没什么大不了。如此往复,让大家更青睐复杂,更远离简单。

    系统的混乱并非业务本身之复杂,我们并不擅长处理『简单』_软件工程_阿里技术_InfoQ写作社区作者:聂晓龙一、前言一群高智商青年在餐厅吃饭,餐桌上一个瓶盖标识为盐的瓶子里装的是胡椒粉,而标识为胡椒粉的瓶子里装的却是盐,他们想出了一个充满才气的方案来完成对调--仅需要一张餐巾纸、一根吸管和两个空https://xie.infoq.cn/article/921d6451a17e152b043e01166


    20221214

    @Inherited​只能实现类上的注解继承。要想实现方法上注解的继承,你可以通过反射在继承链上找到方法上的注解。

    自定义注解可以通过标记元注解@Inherited​实现注解的继承,不过这只适用于类。如果要继承定义在接口或方法上的注解,可以使用Spring的工具类AnnotatedElementUtils。

    Java中的注解可以继承吗?-51CTO.COM@Inherited​只能实现类上的注解继承。要想实现方法上注解的继承,你可以通过反射在继承链上找到方法上的注解。是不是听起来很麻烦,好在Spring框架中提供了AnnotatedElementUtils类,来方便我们处理注解的继承问题。https://www.51cto.com/article/742266.html


    20221209

    用了那么久的 Lombok,你知道它的原理么?-51CTO.COM我们学会了如何自己写一个属于自己的简易Lombok的插件。https://www.51cto.com/article/741851.html

    Optional最佳实践

    就像编程语言的任何其他功能一样,它可以正确使用或被滥用。为了了解使用Optional类的最佳方法,需要了解以下内容:

    **1.**它解决的问题

    Optional的方法是尝试通过增加构建更具表现力的API的可能性来减少Java系统中空指针异常的情况,这些API解释了有时缺少返回值的可能性。

    如果从一开始就存在Optional,那么大多数库和应用程序可能会更好地处理缺少的返回值,从而减少了空指针异常的数量以及总体上的错误总数。

    **2.**它不解决的问题

    Optional并不意味着是一种避免所有类型的空指针的机制。例如,它仍然必须测试方法和构造函数的强制输入参数。

    像使用null时一样,Optional不能帮助传达缺失值的含义。以类似的方式,null可能意味着很多不同的东西(找不到值等),因此缺少Optional值也可以。

    该方法的调用方仍然需要检查该方法的JavaDoc以理解缺省选项的含义,以便正确地处理它。

    同样,以一种类似的方式,可以将检查的异常捕获在一个空块中,没有什么阻止调用方进行调用  get() 并继续进行。

    **3.**何时使用

    Optional的预期用途主要是作为返回类型。获取此类型的实例后,可以提取该值(如果存在)或提供其他行为(如果不存在)。

    Optional类的一个非常有用的用例是将其与流或返回Optional值以构建流畅的API的其他方法结合。请参见下面的代码段

    1. User user = users.stream().findFirst().orElse(new User("default", "1234"));
    2. 复制代码

    **4.**什么时候不使用

    a)不要将其用作类中的字段,因为它不可序列化

    如果确实需要序列化包含Optional值的对象,则Jackson库提供了将Optionals视为普通对象的支持。这意味着Jackson将空对象视为空,将具有值的对象视为包含该值的字段。可以在jackson-modules-java8项目中找到此功能。

    b)不要将其用作构造函数和方法的参数,因为这会导致不必要的复杂代码。

    User user = new User("john@gmail.com", "1234", Optional.empty());


    20221208

    Annotation Processor是javac的一个工具,它用来在编译时扫描和处理注解,通过Annotation Processor可以获取到注解和被注解类的相关信息,然后根据注解自动生成Java代码,省去了手动编写,提高了编码效率。

    回到顶部

    它可以做什么

    在编译的时候动态生成类或者改变类的代码!如:

    lomock:减少get 和set方法的模板代码生成

    mapstruct: 动态生成po vo 互转的Convert类

    hibernate-jpamodelge 动态生成PO类的元数据映射,减少操作字段的模板代码

    编译时代理

    javac AbstractProcessor - 意犹未尽 - 博客园说明 Annotation Processor是javac的一个工具,它用来在编译时扫描和处理注解,通过Annotation Processor可以获取到注解和被注解类的相关信息,然后根据注解自动生成https://www.cnblogs.com/LQBlog/p/14208046.html


    20221201

    默认的缓存状态收集器 CacheStats

    默认情况下,缓存的状态会用一个 CacheStats 对象记录下来,通过访问 CacheStats 对象就可以知道当前缓存的各种状态指标,那究竟有哪些指标呢?

    先说一下什么是“加载”,当查询缓存时,缓存未命中,那就需要去第三方数据库中查询,然后将查询出的数据先存入缓存,再返回给查询者,这个过程就是加载。

    • totalLoadTime:总共加载时间。

    • loadFailureRate:加载失败率,= 总共加载失败次数 / 总共加载次数

    • averageLoadPenalty:平均加载时间,单位-纳秒

    • evictionCount:被淘汰出缓存的数据总个数

    • evictionWeight:被淘汰出缓存的那些数据的总权重

    • hitCount:命中缓存的次数

    • hitRate:命中缓存率

    • loadCount:加载次数

    • loadFailureCount:加载失败次数

    • loadSuccessCount:加载成功次数

    • missCount:未命中次数

    • missRate:未命中率

    • requestCount:用户请求查询总次数

    removalListener 清除、更新监听

    当缓存中的数据发送更新,或者被清除时,就会触发监听器,在监听器里可以自定义一些处理手段,比如打印出哪个数据被清除,原因是什么。这个触发和监听的过程是异步的,就是说可能数据都被删除一小会儿了,监听器才监听到。

    本地缓存之王——Caffeine 组件最强讲解!https://mp.weixin.qq.com/s/JBXtlYHGX3gfV9ZOfqR2nw


    20221125

    html中的template 

    const template = document.querySelector('#id-of-template')
    const content = template.content.cloneNode(true)

    container.append(content)

    使用