- 引言
- 2023.01.03
- 2023.01.04
- 2023.01.05
- 2023.01.06
- 2023.01.09
- 2023.01.11
- 2023.01.13
- 2023.01.15
- 2023.01.17
- 2023.01.30
- 2023.03.01
- 2023.09.29
- 2023.10.08
引言
在学习技术的过程中,看一篇材料,会觉得自己理解了,也做了记录, 但过段时间却不知道曾经看过什么,在解决一个问题时要用什么技术了。
所以有了这篇IT心得整理,旨在时时提醒自己和随时查阅学习心得。
这里只记录心得,具体技术内容翻阅记录文档。
2023.01.03
TCP、UDP,从本质上来说,都是把信息发送到对端,TCP也并没有持续占用网线一说, 只是在系统软件层面来说,TCP实现了下一次发送是基于上一次信息接受成功的基础上。 从这个角度而言,我们也完全可以用UDP实现TCP的特性:发送端发送信息,接收端接受信息; 当接收端接受到信息时,发送接受成功通知给发送端;如果持续一段时间,发送端还没有收到接收端接受成功的通知,就再发送一次; 同理,三次握手、四次挥手也可以用这种方式实现。
记录一个区别:TCP报文段可以分多次发送,UDP数据报需要一次发完。
2023.01.04
提前说一下开闭原则:软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的。
下面说一下四种工厂模式的异同。
简单工厂模式:一个工厂用来生产同一等级结构中的多款产品。不符合开闭原则,无法新增产品。 如在工厂中传入参数获取电视、手机。
静态工厂模式:和简单工厂相似,只是产品获取方法换成了静态方法。获取产品时,不需要实例化工厂了。
工厂方法模式:多个工厂获取对应工厂的一个产品(同一等级结构)。符合开闭原则,但无法在旧工厂中增删产品。 支持增加产品,新增产品时也新建该产品的生产工厂。 如奥克斯空调厂只能生产奥克斯空调,格力空调厂只能生产格力空调; 从工厂来说,奥克斯空调厂和格力空调厂都是空调厂; 从产品来说,奥克斯空调和格力空调都是空调。 如果新增了海尔空调,就需要新建海尔空调厂。
抽象工厂模式:多个工厂获取对应工厂的一族产品。符合开闭原则,但无法在旧工厂中新增产品, 不过可以新增一族产品,然后组建相应的新工厂。 如奔驰厂生产带格力空调的奔驰车,宝马厂生产带海尔空调的宝马车。 格力空调 + 奔驰车 是一个产品族,海尔空调 + 宝马车 是一个产品族; 格力空调和海尔空调都是空调,奔驰车和宝马车都是车; 奔驰厂和宝马厂就是相应的工厂。 如果新增了奥克斯空调,不能换到奔驰厂中去,不过如果新增了奥迪车, 可以新建一个奥迪厂,用来生产带奥克斯空调的奥迪车。 一个工厂中不一定非要获取一条流水线上出来的产品,如最终的成品车, 也可以获取不同的产品,如获取这个工厂用了什么空调、轮胎等。 当然上面的车厂不一定非要生产汽车,也可以同时生产轮船。
工厂方法模式与抽象工厂模式的区别
工厂方法模式:
- 一个抽象产品类,可以派生出多个具体产品类。
- 一个抽象工厂类,可以派生出多个具体工厂类。
- 每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:
- 多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
- 一个抽象工厂类,可以派生出多个具体工厂类。
- 每个具体工厂类可以创建多个具体产品类的实例。
https://ibaiyang.github.io/blog/php/2019/07/30/PHP-创建型模式.html#简单工厂模式simple-factory
建造者模式:建造者可以说就是工厂,只是对比工厂模式多了一个导演类(依赖注入一个建造者类)。 工厂模式是将对象的全部创建过程封装在工厂类中,由工厂类向客户端提供最终的产品。 而建造者模式中,建造者类一般只提供产品类中各个组件的建造,而将完整建造过程交付给导演类。
2023.01.05
同步:我去询问交代的事是否处理完成。阻塞:我不去做其他事。
异步:交代的事情处理完后通知我。非阻塞:我去做其他事了。
IO多路复用:多路是指多个客户端的连接,复用就是指复用少数几个进程。 多路复用本身依然隶属于同步通信方式,只是表现出的结果看起来像异步。
异步并不能提高性能,只是能提高QPS,性能该是多少就是多少,只不过异步可以更好的挖掘和压榨。
多路复用三种常用的方案:
- select,最早的解决方案,同步的。
- poll,算是select的升级版。
- epoll,目前的最终解决版,解决c10k问题的功臣,epoll是同步的,而不是异步。
select,socket_select()
,在内核态监听socket动态,当监听到有信息可读可写时,从用户态把socket连接集合copy到内核态,
在内核态轮询查看是哪个socket可读可写,然后把可读、可写、异常的socket连接放入对应集合返回给用户态,时间复杂度为O(n),
用户再对返回的相应集合进行相应的逻辑处理。因为每次都要从用户态copy到内核态,再从内核态copy给用户态,所以效率低。
poll 和 select 一样,不同之处 select 是数组方式,poll 是 单向链表。
epoll,直接把socket连接集合维护在内核态,监听时免去了copy。epoll使用的是 红黑树,当有fd发生IO事件时, 把事件socket放入双向链表中,时间复杂度为0(1)。epoll_wait()循环查看事件socket双向链表中是否有数据, 如果有就把就绪的所有事件copy到用户空间,然后进行逻辑处理。
监听socket,还有后来的各个连接socket都分别进行进行独立监听,有信息可读时,直接进行相应处理。
https://ibaiyang.github.io/blog/php/2020/07/01/PHP-Socket初探.html
2023.01.06
异步可以更好的挖掘和压榨系统性能,但代码书写会有大量的回调函数,代码不好写,日后不好维护。 同步阻塞代码写起来简洁,维护起来也方便,但性能一般。
有没有用同步阻塞风格写的背后又是异步方式的方法?那就是协程。
PHP 用 yield 来实现协程。yield返回的是一个叫做Generator(中文名就是生成器)的object对象, 而这个生成器是实现了Iterator(迭代器)接口。
yield 只能用在函数中,从过程A到过程B,再从过程B到过程A,可以记住刚才运行到A的哪了,然后继续向下运行。
yield 返回的是 Generator,输出当前值用 Generator->current()
,要向下继续执行需要用 Generator->next()
。
用了yield,Generator->current()
时会主动让出CPU控制权,在Generator->next()
时重新找回CPU控制权继续向下执行。
yield和Generator->send()
可以双向通信,在恢复中断的同时可以携带信息回去,这里可操作空间很大。
https://ibaiyang.github.io/blog/php/2020/07/01/PHP-Socket初探.html#17-php中的yield上
2023.01.09
ReactPHP是事件驱动的,非阻塞I/O的PHP,它和Node.js都是采用单进程和单线程的方式,适用于I/O密集型,不适用于计算密集型。
客户端请求时,使用异步模式发起请求,然后继续向下执行,等服务端返回处理结果后再对这个结果做处理; 一个文件中客户端可以先后发起多个请求。
服务端处理时,接收到一个客户端请求,然后把这个请求移交给处理函数,接下来继续等待下一个客户端请求, 处理函数处理完成后直接把处理结果发送给客户端。
https://ibaiyang.github.io/blog/php/2020/06/22/ReactPHP实践.html
2023.01.11
在依赖注入和依赖注入容器中会讲到:依赖倒置原则、控制反转、依赖注入、控制反转容器、服务定位器。
依赖倒置原则是说上层定义接口,下层实现这个接口,这样所依赖的下层类就必须按照上层类定义的接口来编程。
但什么叫控制反转呢?里面说到控制反转的核心是将类(上层)所依赖的单元(下层)的实例化过程交由第三方来实现。 过去一直没想明白,突然一下有感觉了:控制反转就是说上层类只管从第三方来获取依赖类(下层类), 而不用去不管下层类具体怎样实现。原来的过程是从下层类开始一步一步实例化类,然后注入到上层类中, 由下层决定提供什么给上层。
依赖注入指的是把依赖的对象注入目标对象中去,但这与上面的那几个词有什么关系呢? 在没有依赖注入时,我们要在目标对象中直接实例化所依赖的类,这样就破坏了控制反转,或者说不存在控制反转这个词了: 控制反转讲的就是上层类要去获取所依赖的类,而不是在自己内部实例化。
控制反转容器,提供了动态地创建、注入依赖单元,映射依赖关系等功能。 里面用到了Reflection,具体看一下 https://ibaiyang.github.io/blog/php/2023/02/14/PHP-Reflection.html
服务定位器,核心是把所有可能用到的依赖单元交由服务定位器进行实例化和创建、配置, 把类对依赖单元的依赖,转换成类对服务定位器的依赖,通过控制反转容器,实现服务定位器。
https://ibaiyang.github.io/blog/yii2/2019/06/28/深入理解Yii2.0-依赖注入和依赖注入容器.html#有关概念
一个多月后,再看上面内容时,有两个需要补充的地方。
一个是控制反转的理解:当调用者需要被调用者的协助时,在传统的程序设计过程中,通常由调用者来创建被调用者的实例, 但在这里,创建被调用者的工作不再由调用者来完成, 而是将被调用者的创建移到调用者的外部,从而反转被调用者的创建, 消除了调用者对被调用者创建的控制,因此称为控制反转(或者叫控制转移,会更好理解)。
一个是依赖注入的理解:在调用者中注入被调用者(通过构造器/方法注入实现), 这样我们就实现了调用者与被调用者的解耦,该过程被称为依赖注入。 依赖注入(Dependency Injection)是控制反转(Inversion of Control)的一种实现方式。
https://ibaiyang.github.io/blog/php/2019/07/30/PHP-结构型模式.html#依赖注入dependence-injection
2023.01.13
在面向对象编程中,属性和成员变量并不是一个概念,成员变量是一个“内”概念,反映的是类的结构构成。 属性是一个“外”概念,反映的是类的逻辑意义。
一般要让成员变量对外不可见。如果成员变量对外可见,就失去了类的封装性。 现在图一时痛快,但以后项目代码的修改会是个麻烦事。
https://ibaiyang.github.io/blog/yii2/2019/06/19/深入理解Yii2.0-属性.html
2023.01.15
在PHP项目开发中,碰到一个封装好的HTTP客户端:guzzlehttp/guzzle 包,可以轻松发送 HTTP 请求并轻松与 Web 服务集成。
用于构建查询字符串、POST 请求、流式传输大型上传、流式传输大型下载、使用 HTTP cookie、上传 JSON 数据等的简单界面…
可以使用相同的接口发送同步和异步请求。
对请求、响应和流使用 PSR-7 接口,允许在 Guzzle 中使用其他 PSR-7 兼容库。 支持 PSR-18,允许其他 PSR-18 HTTP 客户端之间的互操作性。
在开发中可以用这个包很好的替换掉Curl函数族。
https://ibaiyang.github.io/blog/php/2022/05/12/guzzle包使用.html
2023.01.17
在一次回顾“服务器最多能支持多少个TCP连接”的内容时,想到两个问题:
- 为什么TCP连接中要有服务器的临时端口?
- TCP/IP连接中的源IP/源端口是什么,与服务器的临时源端口有什么区别?
第1个问题,因为Linux中一切皆文件,连接也是文件,如果没有服务器的临时端口, 怎样把同一个客户端同时对服务器同一个服务的多个不同请求区分开呢(这是错误的观点,并不存在服务器的临时端口, 应该是客户端连接服务器时的临时端口)。
第2个问题,TCP/IP是操作系统实现的,TCP/IP连接中的源IP/源端口也是操作系统处理的,服务器服务回复数据时发到这个源IP/源端口; 服务器的临时源端口只作为连接的文件描述符中存在。
另外,对不同的 目标IP地址:目标端口号
,同一个 源IP地址
可以建立无数的连接;
对同一个 目标IP地址:目标端口号
,同一个 源IP地址
可以建立65535个连接(具体看客户端对端口范围的限制范围配置)。
https://ibaiyang.github.io/blog/网络协议/2021/09/16/最多能创建多少个-TCP-连接.html
还是年轻啊,这里需要特别指出,上面说到的服务器的临时端口是并不存在的,应该是客户端的临时端口。 客户端请求服务器时,会随机分配一个 16位(0-65535) 内的源端口号,服务器通过客户端IP和客户端端口号可以把TCP连接标识出来。
https://ibaiyang.github.io/blog/网络协议/2021/09/23/网络基础知识总结.html
2023.01.30
非转发调用(non-forwarding call):明确指定类名的静态调用和非静态调用
转发调用(forwarding call):进行静态调用时未指名类名的调用(static,self,parent,forward_static_call()
)
static 后期静态绑定(延迟静态绑定)的工作原理是存储了上一个非转发调用(non-forwarding call)的类名。
$this 会先到所在定义范围内(如在父类中则在父类)寻找私有方法,再到它指向的对象所属的类中(当前子类)寻找私有方法, 然后(当前子类)寻找公有方法,最后到所在定义范围内(如在父类中)寻找公共方法。只要找到了匹配的方法,就调用,并停止查找。
static 是先到它指向的类中(当前子类)寻找私有方法(找到则报错),再(当前子类)寻找共有方法; 然后到方法体定义所在范围内(如在父类中)寻找私有方法, 再(如在父类中)寻找共有方法。 只要找到了匹配的方法,就调用,并停止查找。
外部调用子类的静态方法,该静态方法中又转发调用一个方法,则 static、self、parent等 会一直向上追溯,直到遇到非转发调用的形式。
static:可以用于访问类的静态属性、静态方法和常量,static 指向的是实际调用时的类, 在实际调用时的类中找不到调用对象时,会一直向上追溯,直到遇到非转发调用的形式。
self:可以用于访问类的静态属性、静态方法和常量,但 self 指向的是当前定义所在的类, 在当前类找不到调用对象时,会一直向上追溯,直到遇到非转发调用的形式。
parent:可以用于访问类的静态属性、静态方法和常量,但 parent 指向的是当前定义所在类的父类, 在定义所在类的父类找不到调用对象时,会一直向上追溯,直到遇到非转发调用的形式。
根据上面可知调用本类方法可以使用self关键字,调用父类方法可以使用parent关键字,但是如果想在父类中调用子类方法呢? 这就是static关键字设计出来的原因:根据延迟静态绑定,父类调用子类方法。
https://ibaiyang.github.io/blog/php/2019/07/23/PHP-$this-static-self-const的区别和联系.html
https://ibaiyang.github.io/blog/php/2017/09/12/PHP-static延迟静态绑定.html
2023.03.01
单例模式 —— 单例模式的作用就是保证在整个应用程序的生命周期中,任何一个时刻,单例类的实例都只存在一个。
多例模式 —— 除了单例模式的作用外,容器提供多个单例。
注册模式 —— 把实例化好的类放在一个注册的容器中,使用时从容器中获取。
https://ibaiyang.github.io/blog/php/2019/07/30/PHP-结构型模式.html#注册模式registry
享元模式 —— 没有注册这一步,使用时直接从Factory类获取,Factory类决定怎么创建对象和返回。 享元是重点,为了最大限度地减少内存使用,Flyweight尽可能多地与类似对象共享内存。 当使用大量状态差别不大的对象时,就需要它(如Character{a}对象,与另一个Character{a}对象,里面只有个别属性不同,就可以共享内存, 把这几个属性都写在一个类中,实例化时给相应属性赋值,获取时获取指定的对象结构,不必单独保存两个对象浪费内存)。 通常的做法是在外部数据结构中保存状态,并在需要时将它们传递给flyweight对象。
https://ibaiyang.github.io/blog/php/2019/07/30/PHP-结构型模式.html#享元模式flyweight
对象池模式 —— 对象池是一组已经初始化过且可以直接使用的对象集合,使用对象时可以从对象池中获取对象并进行操作,在不需要时归还给对象池。 常见的使用对象池模式的技术包括线程池、数据库连接池、任务队列池、图片资源对象池等。
https://ibaiyang.github.io/blog/php/2019/07/30/PHP-创建型模式.html#对象池模式object-pool
服务定位器模式 —— 把服务在服务定位器中注册好,使用时可以由服务定位器或返回新的实例、或返回实例化好的实例。
2023.09.29
学习要有一个模式,特别是规律性很强的学科。
碰到IT方面的问题:
- 首先,在网络上搜索查看相应的多部视频,用于快速并准确理解(视频材料信息密度大,不容易失真,利于快速吸收)
- 其次,翻阅相关文字资料,更深一层总结内容(泛泛而谈的就没有必要读了,需要的是深度刨析的文字资料)
- 再次,不断实践,加深理解(实际使用,会发现其中潜在的问题,回顾时可以更有目的的查阅)
- 最后,在进行上面每一步过程时,记得写文字把自己理解的内容逻辑写下来,有疑问时回顾寻找答案。
2023.10.08
门面模式 —— 为一组接口提供一个一致的界面,用户只需要直接与门面角色交互,从而降低了系统的耦合度。 关键点是为调用对象提供一个一致的界面。
https://ibaiyang.github.io/blog/php/2019/07/30/PHP-结构型模式.html#门面模式facade
命令模式 —— 将调用者与被调用者之间进行解耦,调用者中注入命令对象,命令对象中注入被调用者并进行相应命令调用。 关键点是将具体命令对象化,如将打招呼或者握手分别封装为命令对象。
https://ibaiyang.github.io/blog/php/2019/07/30/PHP-行为型模式.html#命令模式command
中介者模式 —— 用一个中介对象来封装一系列的对象交互,每一个对象中都注入中介,对象只与中介交互。 关键点是将同事类封装在一个中介对象中,解耦同事类之间的依赖,都只与中介对象发生交互,中介对象再决定具体调用哪个同事类, 包括外部类调用一个同事类方法时,同事类调用中介对象。
https://ibaiyang.github.io/blog/php/2019/07/30/PHP-行为型模式.html#中介者模式mediator