一、集群、分布式、微服务

【集群,分布式,微服务概念和区别理解:https://blog.csdn.net/qq_37788067/article/details/79250623】

分布式:一个业务分拆多个子业务,部署在不同的服务器上 集群:同一个业务,部署在多个服务器上 集群是个物理形态,分布式是个工作方式。分布式是指将不同的业务分布在不同的地方。而集群指的是将几台服务器集中在一起,实现同一业务。 微服务是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务并很好地完成该任务。在所有情况下,每个任务代表着一个小的业务能力。


二、文件描述符

文件描述符(file descriptor)是内核为了高效管理已被打开的文件所创建的索引,用于指代被打开的文件,对文件所有 I/O 操作相关的系统调用都需要通过文件描述符。内核(kernel)利用文件描述符(file descriptor)来访问文件。 文件描述符是非负整数。 打开现存文件或新建文件时,内核会返回一个文件描述符。 读写文件也需要使用文件描述符来指定待读写的文件。


三、中间件

应用中间件(Application Middleware),又名中间件,一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源。中间件位于客户机/ 服务器的操作系统之上,管理计算机资源和网络通讯。是连接两个独立应用程序或独立系统的软件。相连接的系统,即使它们具有不同的接口,但通过中间件相互之间仍能交换信息。执行中间件的一个关键途径是信息传递。通过中间件,应用程序可以工作于多平台或OS环境。 中间件是为应用提供通用服务和功能的软件。数据管理、应用服务、消息传递、身份验证和 API 管理通常都要通过中间件。


四、同步

1、帧同步:帧同步常被RTS(即时战略)游戏常采用。在游戏中同步的是玩家的操作指令,操作指令包含当前的帧索引。一般的流程是客户端上传操作到服务器, 服务器收到后并不计算游戏行为, 而是转发到所有客户端。这里最重要的概念就是 相同的输入 + 相同的时机 = 相同的输出。 实现帧同步的流程一般是: 1、同步随机数种子。(一般游戏中都设计随机数的使用, 通过同步随机数种子,可以保持随机数一致性) 2、客户端上传操作指令。(指令包括游戏操作和当前帧索引) 3、服务器广播所有客户端的操作。(如果没有操作, 也要广播空指令来驱动游戏帧前进)。

2、状态同步:状态同步简单来说就是同步游戏中的各种状态,当客户端发送游戏动作到服务器,服务器接收到之后,通过计算游戏行为的结果,然后广播下发给客户端游戏中的各种状态数据。客户端接收到状态数据后显示内容。这种做法类似于各个客户端都在远程操作服务器上的软件。 状态同步的流程: 1、客户端上传操作到服务器 2、服务器收到后计算游戏行为的结果(如技能逻辑、战斗计算等) 3、服务器以广播的方式下发游戏中各种状态 4、客户端收到状态后更新本地状态(如动作状态、Buff状态、位置等)


五、fork

fork:复刻(英语:fork,又译作派生、分支)是UNIX或类UNIX中的分叉函数,fork函数将运行着的程序分成2个(几乎)完全一样的进程,每个进程都启动一个从代码的同一位置开始执行的线程。这两个进程中的线程继续执行,就像是两个用户同时启动了该应用程序的两个副本。 一个进程,包括代码、数据和分配给进程的资源。fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。 【相关链接:https://blog.csdn.net/kxjrzyk/article/details/81603049】


六、深拷贝、浅拷贝(深复制、浅复制)

https://zhuanlan.zhihu.com/p/56741046 数据分为基本数据类型(String, Number, Boolean, Null, Undefined,Symbol)和对象数据类型。 基本数据类型的特点:直接存储在栈(stack)中的数据 - 引用数据类型的特点:存储的是该对象在栈中引用,真实的数据存放在堆内存里

引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。

浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。

浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。即默认拷贝构造函数只是对对象进行浅拷贝复制(逐个成员依次拷贝),即只复制对象空间而不复制资源。

相关链接:https://www.cnblogs.com/ysocean/p/8482979.html


七、守护进程

守护进程(Daemon Process),也就是通常说的 Daemon 进程(精灵进程),是 Linux 中的后台服务进程。它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。 守护进程是个特殊的孤儿进程,这种进程脱离终端。它之所以脱离于终端是为了避免进程被任何终端所产生的信息所打断,其在执行过程中的信息也不在任何终端上显示。由于在 Linux 中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端就称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会自动关闭。

Linux Daemon(守护进程)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。它不需要用户输入就能运行而且提供某种服务,不是对整个系统就是对某个用户程序提供服务。Linux系统的大多数服务器就是通过守护进程实现的。 守护进程一般在系统启动时开始运行,除非强行终止,否则直到系统关机都保持运行。守护进程经常以超级用户(root)权限运行,因为它们要使用特殊的端口(1-1024)或访问某些特殊的资源。 一个守护进程的父进程是init进程,因为它真正的父进程在fork出子进程后就先于子进程exit退出了,所以它是一个由init继承的孤儿进程。守护进程是非交互式程序,没有控制终端,所以任何输出,无论是向标准输出设备stdout还是标准出错设备stderr的输出都需要特殊处理。 守护进程的名称通常以d结尾,比如sshd、mysqld、crond等

如何查看守护进程:ps axj a 表示不仅列当前用户的进程,也列出所有其他用户的进程 x 表示不仅列有控制终端的进程,也列出所有无控制终端的进程 j 表示列出与作业控制相关的信息 相关链接:https://cloud.tencent.com/developer/article/1635805


八、CPU时间[linux]

CPU时间(CPU TIME)是指当应用进程启动后,占用CPU进行计算所进行的时间绝对值,或叫时间点。如果进程进入中断、挂起、休眠等行为时,是不占用CPU的,所以CPU时间并不会跟着增加,且进程恢复运行后所获得的CPU时间值与运行中断之前的时间值是连续的,并不会因为运行的暂停而导致CPU时间的跳跃。这是和普通的日常时间值不一样的点。另一个不同的点是CPU时间并不是以秒为单位的,而是处理器的时钟周期为单位。

获取CPU时间的函数#include clock_t clock(void)

该函数返回CPU时间,CPU时间并不一定会从0开始,所以要计算进程的一段代码所消耗的CPU时间记录需要在代码前后获取各自的起始和终止CPU时间,两者之差即为所消耗的CPU时间,即为处理器耗时(Processor Time)。要将clock_t转换为秒数,需要除以宏CLOCKS_PER_SEC生成的值,即为秒数。但要注意的是由于在不同的系统中clock_t或CLOCKS_PER_SEC可能为int也可能为浮点型数值,所以在计算时需要在计算过程中并其强制转换为double以保证计算结果。另外需要注意的是clock()函数所返回的值在32位系统上每72分钟就会恢复原始值一次。clock()如果执行错误,则会返回-1。


九、有状态、无状态

有关状态的文章(ps 等有空了补上概念):https://cloud.tencent.com/developer/article/1620559#


十、设计模式

【总原则】开闭原则:对于原有代码,对扩展开放,对修改关闭(接口、抽象类)
【6大原则】:
1单一职责:一个类应该只有一个发生变化的原因。
2里氏替换:所有引用基类的地方必须能透明地使用其子类的对象(子类可以替换基类),子类对父类的方法尽量不要重写和重载。
3依赖倒置:上层模块不应该依赖底层模块,它们都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象(面向接口编程,依赖于抽象而不依赖于具体。用到具体类时,不与具体类交互,而与具体类的上层接口交互)。
4接口隔离:客户端不应该依赖它不需要的接口;类间的依赖关系应该建立在最小的接口上(每个接口中不存在子类用不到却必须实现的方法;使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好)。
5迪米特法则(最少知道原则):一个类对自己依赖的类知道的越少越好,类的逻辑都应该封装在内部,通过public方法提供给外部。与出现为成员变量、方法参数、方法返回值中的类“交谈”,局部变量、临时变量不是直接的朋友,我们要求陌生的类不要作为局部变量出现在类中。
6合成复用原则:尽量使用对象组合/聚合,而不是继承关系达到软件复用的目的。

创建型模式:对类的实例化过程进行了抽象,将对象的创建和对象的使用分离。

工厂模式:在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行(需要哪个牌子的汽车,就到哪个牌子的工厂提货)。

#缺点:每增加一种产品,就需要增加一个对象的工厂。

            工厂类(生产产品)
工厂A类(生产A产品)   工厂B类(生产B产品)    ......

抽象工厂模式:围绕超级工厂创建其他工厂。接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
                 家具工厂类(生产椅子、桌子...)
家具工厂A类(生产A风格椅子、桌子...) 家具工厂B类(生产B风格椅子、桌子...) ......

单例模式:类负责创建自己的对象,同时确保只有单个对象被创建,并且提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。保证一个类仅有一个实例,并提供一个访问它的全局访问点。
类 --> 对象(唯一一个)

建造者模式:使用多个简单的对象一步一步构建成一个复杂的对象。一个Builder类会一步一步构造最终的对象,该Builder类是独立于其他对象的。将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示(肯德基单品组成各种套餐)。
    主管类(按步骤创造各类车)
汽车生成器类(生成座椅等零件)
汽车类(生成汽车)  电汽车类(生成电汽车) ......

原型模式:用于创建重复的对象,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。实现了一个原型接口,用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式(细胞分裂)。
          形状类(克隆方法)
方形类(克隆方形)  圆形类(克隆圆形)  ......

[结构型模式](7):关注对象的组成和对象之间的依赖关系,描述如何将类或者对象结合在一起形成更大的结构(像搭积木)
适配器模式:
装饰者模式:
代理模式:
外观模式:
桥接模式:
组合模式:
享元模式:
[行为型模式](11):关注对象的行为,对在不同的对象之间划分责任和算法的抽象化;不只关注类和对象的结构,而且重点关注它们之间的相互作用
策略模式:
模板方法模式:
观察者模式:
迭代器模式:
责任链模式:
命令模式:
备忘录模式:
状态模式:
访问者模式:
中介者模式:
解释器模式:

其他

句柄和文件描述符(FD):https://www.jianshu.com/p/0ff9ff1d108e WebSocket的消息格式:https://my.oschina.net/flydean/blog/5268288 http缓存机制: https://www.cnblogs.com/chenqf/p/6386163.html https://www.jianshu.com/p/227cee9c8d15

学会了再看 【c++对象池:https://blog.csdn.net/gx864102252/article/details/81174993】