一些可以参考的文档集合10

news/2025/1/15 21:01:23/

 之前的文章集合:

一些可以参考文章集合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

事件监听器

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

我们一起来看一个例子:

复制

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

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

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

复制

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

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

复制

button.removeAllListeners();

使用垃圾收集器 API

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

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

以下是一个例子:

复制

let object1 = {};
let object2 = {};// create a circular reference between object1 and object2
object1.next = object2;
object2.prev = object1;// manually trigger garbage collection
gc();

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

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

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

3. 使用堆快照和分析器

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

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

复制

// Start a heap snapshot
let snapshot1 = performance.heapSnapshot();// Do some actions that might cause memory leaks
for (let i = 0; i < 100000; i++) {myArray.push({largeData: new Array(1000000).fill("some data"), id: i});
}// Take another heap snapshot
let snapshot2 = performance.heapSnapshot();// Compare the two snapshots to see which objects were created
let diff = snapshot2.compare(snapshot1);// Analyze the diff to see which objects are using the most memory
diff.forEach(function(item) {if (item.size > 1000000) {console.log(item.name);}
});

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

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

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

复制

let profiler = new Profiler();profiler.start();// do some actions that might cause memory leaks
for (let i = 0; i < 100000; i++) {myArray.push({largeData: new Array(1000000).fill("some data"), id: i});
}profiler.stop();let report = profiler.report();// analyze the report to identify areas where memory usage is high
for (let func of report) {if (func.memory > 1000000) {console.log(func.name);}
}

在这个例子中,我们使用 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缩小请求映射,示例如下:​

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

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

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

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

Producer媒体类型

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

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

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

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

请求参数与Header

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

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

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

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

编程方式注册

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

@Configuration
public class MyConfig {@Autowiredpublic void setHandlerMapping(RequestMappingHandlerMapping mapping, UserHandler handler) throws NoSuchMethodException {RequestMappingInfo info = RequestMappingInfo.paths("/user/{id}").methods(RequestMethod.GET).build(); // 指定接口处理的方法Method method = UserHandler.class.getMethod("getUser", Long.class); mapping.registerMapping(info, handler, method); }
}

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:日期时间

复制

@Data
@Entity
@Table(name = "student_info")
public class Student {@Column@Temporal(TemporalType.DATE)private Date birthday;
}

@DynamicInsert、@DynamicUpdate

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

复制

@Data
@Entity
@Table(name = "user_info")
@DynamicInsert
@DynamicUpdate
public class User {@Id@Column(name = "id")@GenericGenerator(name="idGenerator", strategy="uuid")@GeneratedValue(generator = "idGenerator")private String id;@Column(name = "name")private String name;@Basicprivate Integer age;@Column(name = "create_time")private Long createTime;@Column(name = "remark")private String remark;
}

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

<!-- https://mvnrepository.com/artifact/com.redislabs/jredisearch -->
<dependency><groupId>com.redislabs</groupId><artifactId>jredisearch</artifactId><version>2.2.0</version>
</dependency>
import io.redisearch.client.AddOptions;
import io.redisearch.client.Client;
import io.redisearch.Document;
import io.redisearch.SearchResult;
import io.redisearch.Query;
import io.redisearch.Schema;public class RediSearchExample {public static void main(String[] args) {// 连接 Redis 服务器和指定索引Client client = new Client("myidx", "127.0.0.1", 6379);// 定义索引Schema schema = new Schema().addTextField("title",5.0).addTextField("desc", 1.0);// 删除索引client.dropIndex();// 创建索引client.createIndex(schema, Client.IndexOptions.Default());// 设置中文编码AddOptions addOptions = new AddOptions();addOptions.setLanguage("chinese");// 添加数据Document document = new Document("doc1");document.set("title", "天气预报");document.set("desc", "今天的天气很好,是个阳光明媚的大晴天,有蓝蓝的天空和白白的云朵。");// 向索引中添加文档client.addDocument(document,addOptions);// 查询Query q = new Query("天气") // 设置查询条件.setLanguage("chinese") // 设置为中文编码.limit(0,5);// 返回查询结果SearchResult res = client.search(q);// 输出查询结果System.out.println(res.docs);}
}

127.0.0.1:6379> ft.add myidx doc1 1.0 fields title "He urged her to study English" desc "good idea"
OK127.0.0.1:6379> ft.search myidx "english" limit 0 10
1) (integer) 1
2) "doc1"
3) 1) "title"2) "He urged her to study English"3) "desc"4) "good idea"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"
OK127.0.0.1:6379> ft.search myidx "正式版"
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的其他方法结合。请参见下面的代码段

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

**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)

使用  <template>更好的原因有几个——有些比其他的更好(感谢 Spankalee概述了一些我没有想到的)——所以选择对你来说最有说服力的:

  • 与隐藏容器中的内容不同,a<template>的内容是惰性的:不加载图像和脚本、不应用样式、不查询元素等。
  • 内容模型验证已关闭;<template>可以安全地包含  <td><li>或者<dd>没有验证者抱怨。同样,<template>几乎可以在任何地方呈现,而 <div>可能并非如此。
  • CSS 可能会失败、被禁用或自定义,因此使用 CSS 声明来隐藏 <div>并不是真正的防弹。另一方面<template>,即使没有 CSS,该元素也有可能始终被隐藏。如果您走那条路,hiddenHTML 属性可能是更好的选择。
  • 搜索引擎可能会索引隐藏在 CSS 中的内容。或者可能不是。目前还不清楚,因为他们的索引算法是出了名的不透明。您可能不希望索引无意义的模板数据。
  • <template>如果你问我,它只是更语义化和更明显的意图,一个隐藏的容器,这可能与第三方工具、扩展等特别相关。

Templating in HTML | Kitty GiraudelI’m Kitty Giraudel, a non-binary trans frontend developer based in Berlin, focused on accessibility and inclusivity.https://kittygiraudel.com/2022/09/30/templating-in-html/


MySQL 8.0.29之前,在线 DDL 操作中即时添加列只能添加在表的最后一列,对于在某个具体列后面快速添加列很不方便,MySQL 8.0.29 扩展了对 ALTER TABLE … ALGORITHM=INSTANT 的支持:用户可以在表的任何位置即时添加列、即时删除列、添加列时评估行大小限制。

新特性解读 | MySQL8.0 ALTER TABLE … ALGORITHM=INSTANT作者:张娜 爱可生南区DBA组成员,负责MySQL、TiDB日常维护、故障处理。 本文来源:原创投稿 *爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。 一、前言 MySQL 8.0.29之前,在线 DDL 操作中即时添加列只能添加在表的最后一列,对于在某个具体列后面快速添加列很不方...https://opensource.actionsky.com/20220809-mysql/

8.0.30 之前,如何更改 REDO 日志文件大小?

针对这些版本,修改 REDO 日志文件大小的步骤比较繁琐。假设需要更改其大小为 2G ,步骤如下:

1、 REDO 日志文件的更改涉及两个传统参数:其最终大小是这两个参数的值相乘。

(1) innodb_log_files_in_group: REDO 日志磁盘上的文件个数,默认为2。

(2) innodb_log_file_size: REDO 日志磁盘上单个文件的大小,默认为48M。

(3)当前的日志大小为单个48M,两个组,也就是一共96M。

  1. root@ytt-large:~/sandboxes/msb_5_7_34/data# ls -sihl ib_logfile*
  2. 3277012 48M -rw-r----- 1 root root 48M 7月 29 16:18 ib_logfile0
  3. 3277013 48M -rw-r----- 1 root root 48M 7月 29 16:18 ib_logfile1

2、“关闭”快速停实例参数:innodb_fast_shutdown = 0 以确保 InnoDB 刷新所有脏页到磁盘(需要了解此参数的其他值请参见官方手册):

  1. <mysql:(none):5.7.34-log>set global innodb_fast_shutdown=0;
  2. Query OK, 0 rows affected (0.00 sec)

3、等步骤二执行完后,停掉MySQL实例。

4、删掉数据目录下旧日志文件:

  1. root@ytt-large:~/sandboxes/msb_5_7_34/data# rm -rf ib_logfile*

5、在配置文件 my.cnf 里修改参数 innodb_log_file_size ,由于有两个组,设置这个参数为 1G 即可。

  1. [mysqld]
  2. innodb_log_file_size=1G

6、启动 MySQL 实例(如果没有报错,代表更改成功)。

7、查看新的日志文件大小:

  1. root@ytt-large:~/sandboxes/msb_5_7_34/data# ls -sihl ib_logfile*
  2. 3277898 1.1G -rw-r----- 1 root root 1.0G 7月 29 16:31 ib_logfile0
  3. 3277923 1.1G -rw-r----- 1 root root 1.0G 7月 29 16:31 ib_logfile1

8.0.30 之后,如何更改 REDO 日志文件大小?

最新版本 MySQL 8.0.30 发布后,使用新参数innodb_redo_log_capacity来代替之前的两个参数(目前设置这两个参数依然有效)。使用新参数调整大小非常简单,直接设置为要调整的值就行。比如调整其大小为2G:

调整之前,默认100M:

  1. <mysql:(none):8.0.30>select @@innodb_redo_log_capacity;
  2. +----------------------------+
  3. | @@innodb_redo_log_capacity |
  4. +----------------------------+
  5. | 104857600 |
  6. +----------------------------+
  7. 1 row in set (0.00 sec)

调整其大小为2G:

  1. <mysql:(none):8.0.30>set persist innodb_redo_log_capacity=2*1024*1024*1024;
  2. Query OK, 0 rows affected (0.20 sec)

新增对应的状态变量innodb_redo_log_capacity_resized,方便在 MySQL 侧监控当前 REDO 日志文件大小:

  1. <mysql:(none):8.0.30>show status like 'innodb_redo_log_capacity_resized';
  2. +----------------------------------+------------+
  3. | Variable_name | Value |
  4. +----------------------------------+------------+
  5. | Innodb_redo_log_capacity_resized | 2147483648 |
  6. +----------------------------------+------------+
  7. 1 row in set (0.00 sec)

同时磁盘文件的存储形式不再是类似 ib_logfileN 这样的文件,而是替代为 #ib_redoN 这样新文件形式。这些新的文件默认存储在数据目录下的子目录’#innodb_redo’ 里。

1、这样的文件一共有32个,按照参数 innodb_redo_log_capacity 来平均分配。

  1. root@ytt-large:/var/lib/mysql/#innodb_redo# ls |wc -l
  2. 32

2、有两类文件:一类是不带 _tmp 后缀的,代表正在使用的日志文件;带 _tmp 后缀的代表多余的日志文件,等正在使用的文件写满后,再接着使用它。如下所示: 正在使用的日志文件有15个,未使用的有17个。

  1. root@ytt-large:/var/lib/mysql/#innodb_redo# ls | grep -v '_tmp' |wc -l15
  2. root@ytt-large:/var/lib/mysql/#innodb_redo# ls | grep '_tmp' |wc -l17

同时 performance_schema 库里新增表innodb_redo_log_files:获取当前使用的 REDO 日志文件 LSN 区间、实际写入大小、是否已满等统计数据。例如当前15个 REDO 日志文件的统计数据如下:一目了然!

  1. <mysql:performance_schema:8.0.30>select * from innodb_redo_log_files;
  2. +---------+---------------------------+------------+------------+---------------+---------+----------------+
  3. | FILE_ID | FILE_NAME | START_LSN | END_LSN | SIZE_IN_BYTES | IS_FULL | CONSUMER_LEVEL |
  4. +---------+---------------------------+------------+------------+---------------+---------+----------------+
  5. | 7 | ./#innodb_redo/#ib_redo7 | 552208896 | 619315712 | 67108864 | 1 | 0 |
  6. ...
  7. | 21 | ./#innodb_redo/#ib_redo21 | 1491704320 | 1558811136 | 67108864 | 0 | 0 |
  8. +---------+---------------------------+------------+------------+---------------+---------+----------------+
  9. 15 rows in set (0.00 sec)

新特性解读 | MySQL 8.0 在线调整 REDO作者:杨涛涛 资深数据库专家,专研 MySQL 十余年。擅长 MySQL、PostgreSQL、MongoDB 等开源数据库相关的备份恢复、SQL 调优、监控运维、高可用架构设计等。目前任职于爱可生,为各大运营商及银行金融企业提供 MySQL 相关技术支持、MySQL 相关课程培训等工作。 本文来源:原创投稿 *爱可生开源社区出品,原创...https://opensource.actionsky.com/20220802-mysql8-0/


20221118

ImportBeanDefinitionRegistrar的接口方法void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)的返回类型是void,且多了一个BeanDefinitionRegistry类型的参数,它允许我们直接通过BeanDefinitionRegistry对象注册bean。
 

Spring(33)——ImportBeanDefinitionRegistrar介绍_elim168的博客-CSDN博客_spring importbeandefinitionregistarImportBeanDefinitionRegistrar介绍在上一篇博文http://elim.iteye.com/blog/2428994中介绍了ImportSelector的作用及其用法。本文需要介绍的ImportBeanDefinitionRegistrar的用法和作用跟ImportSelector类似。唯一的不同点是ImportBeanDefinitionRegistrar的接口方法v...https://elim168.blog.csdn.net/article/details/88131712

在@Configuration注解的Class上可以使用@Import引入其它的配置类,其实它还可以引入org.springframework.context.annotation.ImportSelector实现类。ImportSelector接口只定义了一个selectImports(),用于指定需要注册为bean的Class名称。当在@Configuration注解的Class上使用@Import引入了一个ImportSelector实现类后,会把实现类中返回的Class名称都定义为bean。

保姆级教程!2 万字 + 30 张图搞懂 MySQL 是怎么加行级锁的?-51CTO.COMInnoDB 引擎是支持行级锁的,而 MyISAM 引擎并不支持行级锁,所以后面的内容都是基于 InnoDB 引擎 的。所以,在说 MySQL 是怎么加行级锁的时候,其实是在说 InnoDB 引擎是怎么加行级锁的。https://www.51cto.com/article/740013.html


 20221117

维护、识别和路由租户数据源

我们可以提供一个独立的库来存放租户信息,如数据库名称、链接地址、用户名、密码等,这可以统一的解决租户信息维护的问题。租户的识别和路由有很多种方法可以解决,下面列举几个常用的方式:

  • 1.可以通过域名的方式来识别租户:我们可以为每一个租户提供一个唯一的二级域名,通过二级域名就可以达到识别租户的能力,如tenantone.example.com,tenant.example.com;tenantone和tenant就是我们识别租户的关键信息。
  • 2.可以将租户信息作为请求参数传递给服务端,为服务端识别租户提供支持,如saas.example.com?tenantId=tenant1,saas.example.com?tenantId=tenant2。其中的参数tenantId就是应用程序识别租户的关键信息。
  • 3.可以在请求头(Header)中设置租户信息,例如JWT等技术,服务端通过解析Header中相关参数以获得租户信息。
  • 4.在用户成功登录系统后,将租户信息保存在Session中,在需要的时候从Session取出租户信息。

启动Spring Boot应用程序之前,就需要为其提供有关数据源的配置信息(有使用到数据库的情况下),按照一开始的需求,有N个客户需要使用我们的应用程序,我们就需要提前配置好N个数据源(多数据源),如果N<50,我认为我还能忍受,如果更多,这样显然是无法接受的。为了解决这一问题,我们需要借助Hibernate 5 提供的动态数据源特性,让我们的应用程序具备动态配置客户端数据源的能力。简单来说,当用户请求系统资源时,我们将用户提供的租户信息(tenantId)存放在ThreadLoacal中,紧接着获取TheadLocal中的租户信息,并根据此信息查询单独的租户库,获取当前租户的数据配置信息,然后借助Hibernate动态配置数据源的能力,为当前请求设置数据源,最后之前用户的请求。这样我们就只需要在应用程序中维护一份数据源配置信息(租户数据库配置库),其余的数据源动态查询配置。

Spring Boot下如何实现数据库的多租户-51CTO.COM在我们常规开发的SaaS平台中,我们有个很常用的需求是通过多租户将不同用户之间的数据和资源隔离开。https://www.51cto.com/article/720523.html

Spring Boot下如何实现数据库的多租户-51CTO.COM在我们常规开发的SaaS平台中,我们有个很常用的需求是通过多租户将不同用户之间的数据和资源隔离开。https://www.51cto.com/article/720523.html

在配置类上增加MapperScan注解,例如:@MapperScan(basePackages = {"com.test.dao"},annotationClass = Mapper.class);

Spring整合MyBatis之底层原理-51CTO.COM使用起来是很简单的,但是有没有老铁想过,为什么做了这么一个简单的配置,这个Mapper就能操作数据库了?https://www.51cto.com/article/722691.html


20221116

数据表的全量输出
Maxwell默认只能监控MySQL的binlog以实现数据变更的监控,不过我们可以通过修改maxwell数据库中的元数据来将某张数据表全量导入Maxwell,即数据表的全量同步。
只需要把数据库中某张表的数据库名和表名写入maxwell数据库中的bootstrap表中即可:

mysql> insert into maxwell.bootstrap(database_name, table_name) values('test', 'books');
Query OK, 1 row affected (0.00 sec)
 

在这里插入图片描述

Offset Explorerhttps://www.kafkatool.com/index.html

数据库CDC中间件学习之Maxwell_coder_szc的博客-CSDN博客_maxwell数据库文章目录介绍工作原理Maxwell与Canal的对比安装及配置前提条件在MySQL中打开binlog创建maxwell数据库操作Maxwell命令行测试插入数据更新数据删除数据Maxwell连接Kafka普通测试topic分区数据过滤数据表的全量输出介绍Maxwell是Zendesk开源的用java编写的MySQL实时抓取(CDC,Change Data Capture,变更数据读取)软件,通过实时读取MySQL的二进制日志Binlog生成json信息,再作为生产者将信息发给Kafka、控制台、redihttps://blog.csdn.net/qq_37475168/article/details/123763097

打印类的布局信息  org.openjdk.jol.info.ClassLayout

 

 

为什么要有双亲委派机制?

两个原因: 1. 沙箱安全机制, 自己写的java.lang.String.class类不会被加载, 这样便可以防止核心API库被随意修改 2. 避免类重复加载. 比如之前说的, 在AppClassLoader里面有java/jre/lib包下的类, 他会加载么? 不会, 他会让上面的类加载器加载, 当上面的类加载器加载以后, 就直接返回了, 避免了重复加载.

全盘委托机制。比如Math类,里面有定义了private User user;那么user也会由AppClassLoader来加载。除非手动指定使用其他类加载器加载。也就是说,类里面调用的其他的类都会委托当前的类加载器加载。

tomcat为何要打破双亲委派机制?

通常,我们在服务器安装的一个tomcat下会部署多个应用。而这多个应用可能使用的类库的版本是不同的。比如:项目A使用的是spring4,项目B使用的是Spring5。Spring4和Spring5多数类都是一样的,但是有个别类有所不同,这些不同是类的内容不同,而类名,包名都是一样的。假如,我们采用jdk向上委托的方式,项目A在部署的时候,应用类加载器加载了他的类。在部署项目B的时候,由于类名相同,这是应用服务器就不会再次加载同包同名的类。这样就会有问题。所以, tomcat需要打破双亲委派机制。不同的war包下的类自己加载,而不向上委托。基础类依然向上委托。

2.双亲委派机制详细解析及原理 - 山河永慕~ - 博客园写在前面的话:为什么要研究类加载的过程?为什么要研究双亲委派机制? 研究类加载的过程就是要知道类加载的时候使用了双亲委派机制。但仅仅知道双亲委派机制不是目的,目的是要了解为什么要使用双亲委派机制,他的https://www.cnblogs.com/shanheyongmu/p/15932606.htmlhttps://www.cnblogs.com/shanheyongmu/p/15932606.html3.代码实现自定义类加载器 - 山河永慕~ - 博客园手把手叫你写类加载器。 了解了类加载器的双亲委派机制, 也知道了双亲委派机制的原理,接下来就是检验我们学习是否扎实了,来自定义一个类加载器 一. 回顾类加载器的原理 还是这张图,类加载器的入口是c++https://www.cnblogs.com/shanheyongmu/p/15935320.htmlhttps://www.cnblogs.com/shanheyongmu/p/15935320.html4.自定义类加载器实现及在tomcat中的应用 - 山河永慕~ - 博客园了解了类加载器的双亲委派机制, 也知道了双亲委派机制的原理,接下来就是检验我们学习是否扎实了,来自定义一个类加载器 一. 回顾类加载器的原理 还是这张图,类加载器的入口是c++调用java代码创建了Jhttps://www.cnblogs.com/shanheyongmu/p/15936397.htmlhttps://www.cnblogs.com/shanheyongmu/p/15936397.html


http://www.ppmy.cn/news/663550.html

相关文章

maven charset_Maven 依赖冲突踩坑后,将依赖调解、类加载彻底整明白了

作者 | 草捏子 来源 | 草捏子(ID:chaycao) 头图 | CSDN 下载自东方IC 今年年初的时候&#xff0c;阅读过《Maven实战》&#xff0c;当时有了解到Maven可以依赖调解&#xff0c;即当包版本不一致时&#xff0c;会根据一定规则选择相应的包来加载&#xff0c;从而避免冲突。当时…

OpenStack Stein版搭建详解

目录 .基础环境配置 1.1 节点硬件规划 1.2 节点网络规划 1.3 关闭防火墙 1.4 配置yum源 1.5 配置节点IP 1.6 配置主机名 1.7 配置主机名解析 1.8 配置NTP服务 2.安装基础软件包 2.1 安装OpenStack软件包 2.2 安装mariadb数据库 2.3 安装RabbitMQ消息队列 2.4 安装…

OpenStack搭建M版本 (VM安装)

理论基础 1&#xff0e;云计算的起源 早在2006年3月&#xff0c;亚马逊公司首先提出弹性计算云服务。 2006年8月9日&#xff0c;谷歌公司首席执行官埃里克施密特&#xff08;Eric Schmidt&#xff09;在搜索引擎大会上首次提出“云计算”&#xff08;Cloud Computing&#x…

C++八股文 第3弹

1.C常见的排序方法包括&#xff1a; 冒泡排序&#xff08;Bubble Sort&#xff09;&#xff1a;通过不断交换相邻的元素&#xff0c;将较大或较小的元素逐渐冒泡到正确的位置。 选择排序&#xff08;Selection Sort&#xff09;&#xff1a;每次从未排序部分选择最小或最大的元…

高性能分布式缓存Redis(二) 高级应用

一、持久化原理 持久化 Redis是内存数据库&#xff0c;数据都是存储在内存中&#xff0c;为了避免进程退出导致数据的永久丢失&#xff0c;需要定期将Redis中的数据以某种形式(数据或命令)从内存保存到硬盘&#xff1b;当下次Redis重启时&#xff0c;利用持久化文件实现数据恢…

华为手机ADB禁用系统更新(亲测可用)

测试机型&#xff1a;荣耀10 首先下载ADB工具包&#xff0c;百度adb工具包&#xff0c;选择太平洋下载中心那个下载下来。有360等安全卫士先关掉以免提示出错 1、下载后解压得到一个ADB工具包文件夹&#xff0c;把里面的所有文件复制粘贴到E盘&#xff08;可以为其他盘&#…

华为手机系统更新后有什么大的变化?

我有一个习惯&#xff0c;除了华为手机&#xff08;包括荣耀&#xff09;&#xff0c;其他手机的系统更新一律无视&#xff0c;通过我的观察&#xff0c;除了EMUI以外&#xff0c;MIUI、Flyme等等安卓系统&#xff0c;只要更新&#xff0c;系统流畅度就会差一点点&#xff0c;随…

华为手机禁止系统更新

1、先在电脑(win 7 或 Win 10)安装华为手机助手https://consumer.huawei.com/minisite/HiSuite_cn/,然后升级到最新版。2、点击链接在网盘下载ABD工具包pan.baidu.com/s/1R00_eqeD5fDf-oBxXAvejQ,解压缩放在任一分区。 3、在手机的 设置=》关于手机=》版本号那里 用手指连续…