导航:首页 > 源码编译 > 源码笔记23

源码笔记23

发布时间:2023-01-08 08:15:41

㈠ Netty源码笔记

Netty版本4.0.29.Final,以构造客户端连接服务端的角度来追踪源码

NioEventLoopGroup的构造器中会调用父类MultithreadEventLoopGroup的构造器

在父类MultithreadEventExecutorGroup的构造器中

上面已经完成了NioEventLoop的创建,并保存在NioEventLoopGroup的数组属性上。而关于NioEventLoop在具备线程池能力时,在何时启动已经创建的线程呢?在SingleThreadEventExecutor::execute中可以找到答案

而关于NioEventLoop内线程启动后的逻辑,可以在创建该线程时看到有向线程提交一个任务。根据任务内SingleThreadEventExecutor.this.run()可以定位到创建线程提交任务的NioEventLoop::run

NioEventLoop::run是Netty的核心所在。它是NioEventLoop的线程执行的唯一任务。方法内无限循环,阻塞等待IO事件或队列中的任务

关于队列中的任务从哪里来?一是源码内部,启动时会直接提交任务到队列中;二是可以直接取出channel中的NioEventLoop向其提交任务;三是使用Channel写数据时,都是以任务的形式提交到队列中。与Channel绑定的NioEventLoop循环时会消费提交到队列中任务并执行,后续在分析unsafe时会一并提及。

客户端Bootstrap配置引导时,需要指定Channel类型,后续会使用反射创建该Channel类型实例。

客户端完成NioEventLoopGroup和Bootstrap的创建及对Bootstrap进行相关的设置后,使用Bootstrap尝试与服务端建立连接。在同步与异步之间,推荐使用异步来监听连接事件的结果。

AbstractBootstrap是Bootstrap的父类,initAndRegister中完成了通道的创建、初始化以及注册

group()取到开始配置的NioEventLoopGroup,register在父类MultithreadEventLoopGroup中

虽说暂时不引入unsafe类逻辑,但在unsafe::register中,通道注册完成后会调用管道的fireChannelRegistered方法,进而执行自定义的ChannelInitializer,最终形成完整的管道。
目前管道上链表有三个节点:head、自定义ChannelInitializer、tail(规定自头向尾的流向为In,自尾向头的为Out)
它们的类型都是AbstractChannelHandlerContext,每个Context上都持有对应的ChannelHandler

至此,Channel的初始化及注册已经完成。回到Bootstrap::doConnect中,在Channel注册这个异步任务完成后,开始真正的连接服务端

channel连接建立完成后,可以使用channel写数据

写数据不会直接发送数据到服务端,而是会缓存起来,直到调用flush才会完成数据的最终发送。flush逻辑与写数据一样,channel到pipeline,tail到head。最终交由unsafe类来完成

以客户端建立连接发送数据流程为例(服务端大部分逻辑相似),总结Netty的工作流程:

㈡ mmdetection源码阅读笔记(2)--Loss

之前写了模型和网络的创建,这里就主要写下训练过程中具体的loss,主要分为以下几部分

rpn_loss 的实现具体定义在 mmdet/models/anchor_head/rpn_head.py

具体的计算方式定义在其父类 mmdet/models/anchor_heads/anchor_head.py ,主要是 loss 和 loss_single 两个函数。
先看 loss 函数

这个主要做了两个事

首先,在此时 rpn 的输出为 feature map 中每个位置的 anchor 分类的 score 以及该 anchor 的 bbox 的修正值,我们要通过和 gt 计算 loss 来优化我们的网络,但是我们的gt是一堆人工标注的 bbox ,无法直接计算 loss 。所以,我们应该要先获取到 anchor 然后将这些 anchor 和 gt 对比在分别得到正负样本以及对应的 target ,之后我们才能计算得到 loss 。

所以第一步通过 anchor_list, valid_flag_list = self.get_anchors(featmap_sizes, img_metas) 获取到了所有的 anchor 以及一个 是否有效的 flag (根据bbox是否超出图片边界来计算。)
拿到了所有的 anchor 之后就是和gt对比来区分正负样本以及生成 label 了,通过定义在 mmdet/core/anchor/anchor_target.py 的 anchor_target() 实现。
在这个函数中调用 assigner 将 anchor 和 gt 关联起来,得到 正样本 和 负样本 ,并用 sampler 将这些结果进行封装,方便之后使用。
得到了 target 过后,就是计算 loss 了,在 self.loss_single 中,

这里用的 loss 就是常见的 CrossEntropyLoss 和 SmoothL1Loss

之前的 rpn_loss 是对候选框的第一次修正,这里的 bbox_loss 就是第二次修正了,两者的实际差别主要体现在分类上,在 rpn 阶段只分两类(前景和背景),这里分类数为 N+1 (真实类别+背景)
具体定义在 mmdet/models/bbox_heads/bbox_head.py

可以看到和 rpn loss 相比,这里要简单很多,因为这里只包含了 rpn loss 中实际计算 loss 的部分,但是他也同样需要 rpn 中的 assign 和 sample 操作,两者的区别只是 assign 的输入不同, rpn 的 assign 输入是该图所有的 anchor , bbox 部分 assign 的输入就是 rpn 的输出。这里的 loss 和 rpn 中的计算方式完全一样,就不在赘述了。

mask 部分计算 loss 之前也有一个获取 target 的步骤。
mmdet/models/mask_heads/fcn_mask_head.py

这里获取 target 相对之前来说就要简单点了,通过定义在 mmdet/core/mask/mask_target.py 的 mask_target() 取到和 prooisals 相同大小的 mask 就行了。

而 loss 部分也比较简单,也是用的 CrossEntropyLoss 。

总的来说这些 loss 还是算比较好理解的,看起来有三部分的 loss ,但是实际上每个部分的都差不多。
下一篇就准备写下整个的训练流程了,相当于将前面这三篇给连起来,有个更具体的理解。

㈢ consul源码笔记

从本周开始对consul的源码做一个简单的阅读和了解,希望能持续下去吧。
consul是使用go编写的,在阅读过程中可能会涉及到对go语法的相关笔记,这个会分开两个系列文章去更新。

1.agent的定义(agent.go)

agent是一个常驻进程部署在所有机器上,可以分client和server两种模式运行(client模式只负责转发请求,轻量级)。
config为agent的配置,包括nodeID等核心的配置都在里
delegate为Server或者client的对象,取决于进程启动选择的方式
2.程序入口(agent.go)

这里主要是构建一个Server或者client的对象,我们接下来看一个server对象是如何构建的

我们看下server对象的重要属性,跟raft协议相关的对象封装在这里。

这里做的事情很简单,启动服务器并输出日志。

最后我们看起构建一个raft对象具体做了哪些事情。

㈣ springboot 2.x源码笔记- 配置文件加载 ConfigFileApplicationListener

至此,整个environment的配置加载过程就完成了。

配置项的注入是要等到bean的实例化后初始化阶段, 参考这里 .实例化后,会通过org.springframework.beans.factory.annotation.#postProcessProperties-->org.springframework.beans.factory.annotation.InjectionMetadata#inject--->org.springframework.beans.factory.annotation..AutowiredMethodElement#inject--->org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency--->org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency

总结:

㈤ 源码修炼笔记之Dubbo线程池策略

FixedThreadPool

FixThreadPool内部是通过ThreadPoolExecutor来创建线程,核心线程数和最大线程数都是上下文中指定的线程数量threads,因为不存在空闲线程所以keepAliveTime为0,
当queues=0,创建SynchronousQueue阻塞队列;
当queues<0,创建无界的阻塞队列LinkedBlockingQueue;
当queues>0,创建有界的阻塞队列LinkedBlockingQueue。
采用bbo自己实现的线程工厂NamedInternalThreadFactory,将线程置为守护线程(Demon)
拒绝策略为AbortPolicyWithReport,策略为将调用时的堆栈信息保存到本地文件中,并抛出异常RejectedExecutionException

CachedThreadPool

CachedThreadPool与FixedThreadPool的区别是核心线程数和最大线程数不相等,通过alive来控制空闲线程的释放

LimitedThreadPool

LimitedThreadPool与CachedThreadPool的区别是空闲线程的超时时间为Long.MAX_VALUE,相当于线程数量不会动态变化了,创建的线程不会被释放。

EagerThreadPool

与上述三种线程池不同,EagerThreadPool并非通过JUC中的ThreadPoolExecutor来创建线程池,而是通过EagerThreadPoolExecutor来创建线程池,EagerThreadPoolExecutor继承自ThreadPoolExecutor,实现自定义的execute方法,采用的阻塞队列是TaskQueue,TaskQueue继承自LinkedBlockingQueue。

execute方法首先调用ThreadPoolExecutor的execute方法,如果执行失败会重新放入TaskQueue进行重试。

实现自定义的ThreadPool

ThreadPool被定义为一个扩展点,如下所示,

其默认实现是FixedThreadPool,可以通过实现该扩展来实现自定义的线程池策略。

㈥ String类源码笔记(一):成员变量和构造器

String类表示字符串,所有类似"abc"形式的字符串(或魔法字符串)都被看作是这个类的实例。String是不可变的,当一个字符串在常量池中被创建时,他的值就不会被改变。

所在路径:javalangString.java

为了保证String类是一个不可变类,String类的成员变量多为私有和不可变的。

其中serialPersistentFields在序列化时使用:

JDK8的String类一共有16个构造器,其中两个是@Deprecated,一个是私有构造器,剩下的13个是可以调用的。

无参构造器直接将""的value赋值给当前类的value。""的value是一个空的char[],其length为0。调用使用了无参构造器的String对象的isEmpty()方法会得到true,调用length()方法会得到0,判断其==null会得到false。

入参为String对象时,构造器会对其进行直接取值。

入参为字符串数组时,构造器调用的是Arrays.Of()方法。

其中Arrays.Of()方法是为了将入参的字符串序列深拷贝到this.valuie中,他的源码为:

其中System.array()方法的源码为:

这个方法支持直接传入想要生成的String的母串,通过偏移量和有效长度找出需要赋值给this.value的部分,然后调用Arrays.OfRange()方法进行深拷贝。

当需要将一个Unicode编码序列转换为String时,可以使用以下构造器:

当需要将一个bytes[]转换为String时,可以使用以下构造器:

此外,还有一些将上述构造器进一步封装的构造器,其本质都是简化入参。另外,String类的构造器同样支持传入StringBuffer和StringBuilder。如果传入的是StringBuffer,构造器会为其加锁。如果传入的是StringBuilder则不会加锁。

事实上,StringBuffer和StringBuilder的toString()方法调用的也是String类的构造器,他们最终的底层实现都是Arrays.Of()。

最后,String类还提供了一个保护类型的构造方法。该方法相比入参为char[]的构造器多了一个share参数,这个参数并没有实际作用,只是用来和其他构造器进行区分。当String类内部调用该构造器时:

该构造器不能对外暴露的原因是需要保持String类的不可变性。

㈦ Eureka源码浅读---自我保护机制

Eureka源码采用1.7.2版本

本人小白,此文为本人阅读源码笔记,如果您读到本文,您需要自己甄别是否正确,文中的说明只代表本人理解,不一定是正确的!!!

自我保护机制设计的初衷是防止服务注册服务因为本地网络故障,长时间未接受到心跳请求,造成错误的移除大量服务实例,其实调用服务还是可用的

自我保护机制是和自动故障移除联系在一起的,针对的移除实例也是自动故障移除

在服务故障移除的方法中有这样一个判断,当返回false时候,直接返回,不进行故障实例的摘除
进入该方法

关于获取上一分钟心跳总数,Eureka Server内部采用的是定时线程进行统计,使用两个AtomicLong进行保存当前和上一分钟的心跳总数

该方法初始化了运行了定时调度的线程进行统计,默认执行间隔为1min,执行流程:

那么当前的心跳总数是怎么计算的呢,直接看心跳的renew()方法,是否嵌入了计数器累计操作

如上所示,当接收到心跳时,当前心跳计数器进行了递增操作

而getNumOfRenewsInLastMin()获取上一分钟心跳总数就是获取lastBucket数量,再找下该定时任务启动的入口

和自动故障移除的定时同时启动的,那么lastBucket代表了上一分钟的心跳总数

接下来,我们需要看看期望每分钟最小心跳总数的由来:

numberOfRenewsPerMinThreshold最开始的初始化计算是在Eureka Server初始化计算的,使用当前Server拉取到的服务实例总数 * 0.85

在openForTraffic()方法中使用初始化拉取的服务实例总数作为基数标准进行计算,(int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold()) -> count * 2 * 0.85,
集群模式下,count为其他节点中已注册的服务实例总数,单节点就为0

下面我们看看在注册中心接收到注册,下线等请求执行时,维护numberOfRenewsPerMinThreshold

注册,当前实例数量+2,下线,当前实例数量-2,然后再次*0.85,计算期望每分钟最小心跳数



在Eureka Server中有专门的定时任务进行更新numberOfRenewsPerMinThreshold,默认每15min执行一次

主要流程如下:

注意,自动服务故障移除没有进行numberOfRenewsPerMinThreshold的更新

<font color= 'blue'>服务故障实例的摘除需要判断当前是否处于自我保护模式,而自我保护模式的默认是开启(isSelfPreservationModeEnabled),需要判断上一分钟的心跳总数是否大于期望每分钟最小心跳数,如果在15分钟内,累计丢失了15%以上的节点心跳,那么Eureka Server就会认为当前所处的网络环境异常,从而处于自动保护模式,故障实例将不会移除,再等待15min后,进行expectedNumberOfRenewsPerMin的基于当前服务实例的重新计算后,自我保护模式才会关闭!</font>

自我保护服务开启模拟:

㈧ InteractionManager源码阅读笔记

InteractionManager的直接翻译是交互管理器,在react-native的文档里,其作用描述为:"Interactionmanager 可以将一些耗时较长的工作安排到所有互动或动画完成之后再进行。这样可以保证 JavaScript 动画的流畅运行。"

我们最常用这个类的场景是:从A页面跳转到B页面,然后想让B页面的网络请求或者页面刷新工作放到过场动画结束后再去做,这时可以用InteractionManager的runAfterInteractions函数来实现。

那么问题来了,如果A页面有一个循环不停止的动画,这时候再跳转B页面,B页面为了转场动画的顺畅使用了runAfterInteractions,但由于A页面的循环动画而永远无法进入回调闭包,这个问题怎么解决呢?

react-native官方已经考虑到了,在Animated类里面的 loop 方法,有这么一段话:"In addition, loops can prevent VirtualizedList-based components from rendering more rows while the animation is running. You can pass isInteraction: false in the child animation config to fix this."。虽然这段话不是在解决我们说的问题,但是所提到的isInteraction属性,我们可以通过Animated的源码,看到这个属性是用来干嘛的。

由此可见,这个isInteraction属性是用来控制是否创建句柄的。

那么关键的来了,InteractionManager.createInteractionHandle()和InteractionManager.runAfterInteractions()之间的具体关系是什么样的呢?

我们可以看看InteractionManager的 源码 :

先看这一对函数:

一个是创建句柄一个是清除句柄,其实创建句柄很简单,所谓的句柄就是全局变量_inc自增后的结果,然后加入了_addInteractionSet的集合。清除句柄,就是把handle从_addInteractionSet中移除,加入_deleteInteractionSet。那么整个InteractionManager是如何运作起来的呢?runAfterInteractions中的回调是如何被调用的?这其实最核心的部分是在_scheleUpdate里面:

_scheleUpdate主要是处理了InteractionManager的deadline,然后调用了_processUpdate:

如上图所示,第一个红框里面其实就是InteractionManager最核心的部分。还记得刚才的createInteractionHandle和clearInteractionHandle么,其实整个InteractionManager就是实现了生产者消费者模型。第二个红框部分,其实就是去执行runAfterInteractions里面的闭包回调。我们最后再看runAfterInteractions:

参数task最终加入了_taskQueue中,而这个_taskQueue会在_processUpdate中被遍历执行。

用一个很通俗易懂的方法来解释InteractionManager,比如我们去面馆吃面,跟老板说我要一碗面(createInteractionHandle),然后我们就找个位子等老板把面端上来了(runAfterInteractions(()=>{console.log('吃面')})),过了一阵子老板面做好了,于是端上面(clearInteractionHandle),我们就吃到面了。那么又有个疑问了,为啥InteractionManager要设计的这么复杂呢?直接存一下回调,然后触发回调不就好了么。这就好比我们出去吃面,不可能吃光面一样。比如我们要吃一碗雪菜肉丝面,那么流程就得这样了:

最后,我们看一下react-native里面会有哪些地方默默的为我们createInteractionHandle呢?

一共就这两处,第一处就是创建动画的时候,官方文档上也说了可以用来延迟耗时操作,保证转场动画流畅。第二处是这个 PanResponder ,官方文档也做了解释,保证手势响应顺畅。但其实大家在理解了上面吃面的例子后,也可以扩展一下自己的思维,灵活的运用InteractionManager。

㈨ MyBatis­Plus快速入门源码笔记共享,拿走吧你

为什么要学习它呢?

答:MyBatisPlus可以节省我们大量工作时间,所有的CRUD代码它都可以自动化完成!

优点:
1. 易于上手和掌握。
2. sql写在xml里,便于统一管理和优化。
3. 解除sql与程序代码的耦合。
4. 提供映射标签,支持对象与数据库的orm字段关系映射
5. 提供对象关系映射标签,支持对象关系组建维护
6. 提供xml标签,支持编写动态sql。

MyBatis Plus(简称 MP)是一个 MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。

特性:

无侵入 :只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑。

损耗小 :启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作 强大的 CRUD 操作 :内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求 支持 Lambda 形式调用 :通过 Lambda 表达式,方便地编写各类查询条件,无需再担心字段写错。

支持组件自动生成 :支持多达 4 种主键策略(内含分布式唯一 ID 生成器 Sequence),可自由配置,完美解决主键问题。

支持 ActiveRecord 模式 :支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作。

支持自定义全局通用操作 :支持全局通用方法注入( Write once, use anywhere )。

内置代码生成器 :采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用 内置分页插件 :基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List查询。

分页插件支持多种数据库 :支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库。

内置性能分析插件 :可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询。

内置全局拦截插件 :提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作。

1.1 、引入mybatis-plus相关maven依赖


引入mybatis-plus在spring boot中的场景启动器


ps:切记不可再在pom.xml文件中引入mybatis与mybatis-spring的maven依赖,这一点,mybatis-plus的官方文档中已经说明的很清楚了.

1.2、创建数据表

(1)SQL语句



(2) 数据表结构

1.3、 创建java bean

根据数据表新建相关实体类

1 package com.example.demo.pojo



1.4、 配置application.proprties

数据源使用druid



ps:在进行crud实验之前,简单对mybatis与mybatis-plus做一个简单的对比

2.1、mybatis与mybatis-plus实现方式对比

(1)提出问题: 假设我们已存在一张 tbl_employee 表,且已有对应的实体类 Employee,实现 tbl_employee 表的 CRUD操作我们需要做什么呢?

(2)实现方式: 基于 Mybatis 需要编写 EmployeeMapper 接口,并手动编写 CRUD 方法 提供 EmployeeMapper.xml 映射文件,并手动编写每个方法对应的 SQL 语句. 基于 Mybatis-plus 只需要创建 EmployeeMapper 接口, 并继承BaseMapper 接口.这就是使用 mybatis-plus 需要完成的所有操作,甚至不需要创建 SQL 映射文件。

2.2、BaseMapper接口介绍

(1)如何理解核心接口BaseMapper?

在使用Mybatis-Plus时,核心操作类是BaseMapper接口,其最终也是利用的Mybatis接口编程的实现机制,其默认提供了一系列的增删改查的基础方法,并且开发人员对于这些基础操作不需要写SQL进行处理操作(Mybatis提供的机制就是需要开发人员在mapper.xml中提供sql语句),那样我们可以猜测肯定是Mybatis-Plus完成了BaseMapper接口提供的方法的SQL语句的生成操作。

(2)BaseMapper接口为我们定义了哪些方法?

BaseMapper接口源码:





(3) mybatis-plus中常用的注解 1


由于我们的数据表名于实体类的类名不一致,并且实体类于数据表还存在字段名不对应的情况,因此我们需要引入mybatis-plus的注解.



编写EmployeeMapper接口继承BaseMapper接口



准备考试环境:



(1)插入



(2)修改



控制台打印出的sql语句

如果我们不设置实体类的email与gender属性,结果是怎样的呢?



控制台sql语句:

显然,mybatis-plus为我们做了非空判断,空值的话,默认不更新对应的字段.想一想,这是不是类似于mybatis中的动态sql呢?

这种处理效果又会带来什么好处呢?

(3)查询



selectById方法



selectBatchIds方法



ps:发现该方法底层使用的竟然是sql的in关键字

selectByMap方法



(4)删除



3、不得不提的条件构造器---Wrapper

3.1.wrapper及其子类介绍

(1)Wrapper :条件构造抽象类,最顶端父类,抽象类中提供3个方法以及其他方法.

㈩ suricata源码笔记:main函数

main()函数位于suricata.c文件,其主要流程如下:

24. 执行PostConfLoadedSetup,即运行那些需要在 配置载入完成 后就立马执行的函数。这里面涉及的流程和函数非常多:

阅读全文

与源码笔记23相关的资料

热点内容
str中python 浏览:87
java的equals用法 浏览:843
奥维云服务器怎么开通 浏览:167
js取得服务器地址 浏览:810
起点中文网小说缓存在哪个文件夹 浏览:214
java疯狂讲义pdf 浏览:296
推有钱app在哪里 浏览:739
宁波鲍斯压缩机 浏览:93
新建文件夹电影2完整版演员表 浏览:988
空调压缩机为什么不能放到冷库用 浏览:89
江西云服务器节点虚拟主机 浏览:997
新氧app如何测试脸型 浏览:688
个税app如何查询社保 浏览:495
安卓设备快充什么时候开启的 浏览:13
ipad怎么用安卓手机传文件 浏览:584
编辑程序员视频 浏览:633
极光app的云助手在哪里 浏览:777
信合有什么ApP 浏览:958
android绝对位置 浏览:79
阿里巴巴校招程序员在哪个园区 浏览:905