暂时未有相关云产品技术能力~
记录知识积累过程
依赖倒置原则的定义:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。
接口隔离原则 Interface Segregation Principle,ISP - 客户端不应该依赖它不需要的接口 - 类间的依赖关系应该建立在最小的接口上
里氏替换原则 Liskov Substitution Principle,LSP Inheritance should ensure that any property proved about supertype objects also holds for subtype objects 继承必须确保超类所拥有的性质在子类中仍然成立。
开闭原则 Open Closed Principie ,OCP 软件实体的行为应当不是修改实体,而是对实体进行扩展。
架构设计另一个编程范式—函数式编程,其主要关心数据到数据之间的映射关系,即将计算过程抽象描述成一种表达式求值。先看下以下实现数组转换成数组对象的函数代码:
编程范式:范式是编程的方式,和语言无关。主要有三种方式:结构化编程、面向对象编程、函数式编程。
设计:实现业务时的详细的设计,比如模块的依赖设计,业务逻辑设计,前端页面的设计。更偏向于细节内容的设计 - 架构:类似搭建房子一样,先有房子的形状、布局等,一个项目的架构那就是各个模块依赖关系,或者说结构。未来设计方向的一个框架。
装饰模式又称为包装模式,对象被包装后,还可以继续包装添加新的功能,从而扩展对象的功能,通过装饰模式可以使系统更具有弹性,且其遵循了面向对象原则:对外开放,对修改关闭。
适配器模式 将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。 比如,某对象需访问目标对象,但由于某种情况,不适合或不能直接访问目标对象,通过一个中介进行访问,这个中介就是代理对象。
建造者模式 也叫做 生成器模式
工厂,是创建产品的地方。在软件设计中的工厂模式,就是封装和管理对象的创建。工厂模式,具体划分的话,有简单工厂模式和工厂方法模式,根据抽象程度划分,有工厂方法模式和抽象工厂模式
原型模式 用一个已经创建的实例为原型,通过复制该原型实例来创建一个和原型相同或类似的新对象。简单说,通过克隆对象来实现一个新的对象。
本来想通过koa快速搭建一个简单的服务时并测试文件上传的过程,然后使用postman请求时,获取上传的form-data中文件的水,ctx.request.body却一直是undefined?
遇到这样的业务场景:一张图片,传递给第三方(第三方以接口形式接收),且图片是二进制数据,是binary类型。 在我的初印象中,对于图片的操作都会转化成 stream或者base64,如果传递二进制数据是不是应该传递的是一些二进制字符串?还是buffer类型?还是Stream?
以前部署项目时候总会遇到本地环境和线上环境不一致产生排查困难的问题。在使用window系统的电脑开发学习时,但想要学习linux系统的一些操作或者项目的部署时,还需要一台服务器或者一个虚拟机,而Docker不仅部署方便而且更安全,Docker容器是个比较轻量的,占用资源少,成本低等等众多优势。所以,Docker 势必是程序员必会的一个工具之一。
本文首先谈到单例模式,顾名思义,就是在整个系统中只有一个对象,且该对象应当是全局性的。在架构设计的过程,可以想想哪些内容是需要考虑一个全局唯一的,像系统的回收站,只能打开一个;再比如,日志应用,是都可以考虑使用单例模式?
设计模式是软件开发过程中总会涉及到一部分知识,是程序员必备的知识点。准备使用Type Script边巩固typescript边学习设计模式。
使用MQ的目的:对系统进行解耦,流量控制(高可用和高性能问题)
说到消息中间件,我使用比较多的就是RabbitMQ。在分布式系统中,不同模块之间的通信,除了可以使用 RPC方式进行调用外,MQ也是另外一种方式,也是进程之间进行通信的一种方法。 消息队列:传递消息的队列。参与传递消息的双方称为生产者、消费者。生产者和消费者可以只有一个实例,也可以集群部署。
MySQL的慢查询日志是MySQL提供的一种日志记录,用来记录在MySQL中响应时间超过阀值的语句,具体指运行时间超过long_query_time值(默认值10s)的SQL,则会被记录到慢查询日志中。
JavaScript引擎本身不实现事件循环机制。浏览器中的事件循环由浏览器实现的,NodeJS中事件循环主要是由底层Libuv库实现的。 Libuv库是事件驱动的,其封装和统一了不同平台的API实现。NodeJS的跨平台和事件循环机制都是通过Libuv库实现的。
RDB快照,将某一时刻的内存数据生成快照(二进制的形式)写入磁盘。 AOF是记录操作,RDB是某一时刻的数据快照。所以,在数据恢复时,只需直接把RDB文件读入内存,完成快速恢复
- AOF日志:记录所有的操作命令,并以文本的形式追加到文件中 - RDB快照 :将某一时刻的内存数据,以二进制方式写入磁盘 - 混合持久化:Redis4.0版本后新增混合持久化方式,集成RDB和AOF的优点
缓存是架构设计中一个重要的手段。缓存的主要特点是技术比较简单,同时对性能提升的效果又很显著,所以缓存在很多业务场景中被使用到。
PM2是node进程管理工具。简化node应用管理的繁琐任务,如性能监控,自动重启,负载均衡
锁,主要是用来解决并发情况时对共享资源的使用时互斥控制。
etcd的整体架构 - 客户端层 - Clientv3/etcdctl客户端。用户通过命令行或者客户端调用api方式调用使用 - 客户端层提供负载均衡和节点间故障转移等特性
前面我们将功能性的需求几乎都已经都陈列出来,这些几乎是从外部因素考虑的。但对于运行系统的环境,以及系统的并发能力也是我们需要考虑的,这部分可称为非功能需求。 非功能性需求包括:可用性、并发能力、性能、安全防护能力、水平扩容缩容能力、运维/运营成本等
近期在接触的新项目中在使用Etcd,但是在使用的过程中公司对其的使用仅使用服务注册的功能,并未将其发挥真正的用处。学习一波,将来可以在项目中使用进行改进。
资源竞争:多个goroutine同时竞争同一块内存时,就无法知晓谁先访问,结果也无法预料。 所以,我们需要确保共享内存资源,只有一个协程执行能够操作。
go 调用 c/c++ 函数的实现方式有: - 直接嵌套在go文件中使用,最简单直观的 - 直接引用 c/c++ 文件的形式,层次分明,容易随时修改看结果的 - 导入动态库 .so 或 dll 的形式,最安全但是相对会比较慢的
在操作系统中,对进程的解释:进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体。 - 是应用程序的一次运行过程(动态概念) - 是系统分配和调度资源的基本单位(进程是一般由程序、数据集合和进程控制块三部分组成) - 每个进程有自己独立的空间地址,数据栈(各进程间数据不共享,可通过其他方式进行通信)进程一般有初始态,执行态,等待状态,就绪状态,终止状态五种状态
Buffer对象,是Node的核心模块,在面试中也是会频繁被问到一个考题,如果没有对其深入探究,可能就跟我一样只会用,一旦面试官扩展问些问题可能就不会了。反正,当时我也只能回答说:目前涉及到的业务对Buffer模块用的比较少,但是Buffer对象可以对于一些字符串传输无法满足业务功能和性能上得到有效的优化。
因工作需求原因导致我的技术栈一直都在变化,从大学到现在,语言从Java 到 C# 到 Node,再到现在的Go。朋友都会虚假客套你一句赞叹:很厉害,会的语言很多。其实,只有我知道,我属于会而不精系列。所以我这种P民,我还是觉得我应该专注做一件事,深入研究,做好,做到极致。但唯一庆幸的是我一直都在做后端开发。“语言只是工具”。是的,但我还是觉得应该专精一种,再扩展其他旁系。 废话不闲聊,今日话题主要是想聊下我对Node 和Go的一些认识和理解。
在需求评审前,提前了解上下游业务逻辑 产品提供可用于了解的账号&环境 与人沟通时 和其他团队或第三方对需求内容或接口需求时,追问是否达成一致(方式:让对方复述) 会后将会议结论同步至群内
并发场景在所有的开发过程中都是会遇到的。像面向对象语言 C#、Java 经常都是使用多线程的技术来解决并发的场景。但是 Node 是单线程的,对于解决并发基本是通过异步方式。还有使用 node 提供的 Cluster 模块来完成多进程的。 注意点:Node 中的异步是为了解决不堵塞主线程,而不是为了解决并发问题。
设计好了数据库表之后最烦的就是又要在代码中建一层实体层然后一个个创建对应表的结构体。关键那么多项目每次都是需要创建一份,所以就使用 go 实现一个简单的将数据库的表转化为结构体。
之前看到 RunCat 一只可以在电脑上奔跑猫,其主要的功能是监控电脑的CPU、内存的使用情况,使用越多跑的越快。所以准备做一只在任务栏里的兔子,主要使用 Go 语言实现一个简单的到点拜年的兔子。 基本需求: - 打开应用时可以在任务栏里显示 - 实现动态兔子生成
实现一个零点定时推送祝福的需求其实很简单,关键点是零点定时和推送消息出去两个功能。 - 零点定时推送,可以使用 corn 包实现定时任务 - 推送消息,调用飞书和企业微信提供的 webhook 接口,就可以实现消息的推送
新春佳节到来了,各种 APP 的开启首页图片和皮肤样式都会发生变化,它们都将会更新成和新春有关系的图片广告或者新春相关的背景图片。当一个运营负责这项工作时,只需要开发一个可配置的功能,运营只需进行设置就可以完成新春首页替换和新年红皮肤更新。
软件架构设计的最终目标是能够用最小的人力成本来满足构建和维护该系统的需求。软件是为业务服务的,所以一个软件的好坏我想应该就是能够让开发者低成本学习和维护,并利用其帮助业务创造更大的利益。 所以感觉这句话很对:“**软件架构师必须创建出一个可以让功能实现起来更容易、修改起来更简单、扩展起来更轻松的软件架构。”**
Go 在 goroutine 的通信经常会提及的设计思想是:不要通过共享内存的方式进行通信,而应该通过通信的方式共享内存。这和 Java 语言不通,Java 中多个线程传递数据的方式一般都是通过共享内存或者其他共享资源的方式解决线程竞争问题。
设计数据库时经常要做的就是给字段设置数据类型,但是对于一些字段是需要设置长度的,那么需要设置多少长度才算是合适的?
经常遇到这样的场景:几个模块的都有相同的方法,但会因为不同的类型的需要调用不同模块的方法。使用一个 switch 可以很方便的解决问题。但是当你遇到的场景是几个模块的方法都是需要的执行,同时它需要在不同的配置下执行相对应的方法。
在使用 for range 时会出现让人意想不到的结果,比如输出的结果并非是每次的更新结果。到底是什么原因,可以详细看下其中的内容。
在 SaaS 系统中多租户是一个很重要的架构,在服务上仅需运行一个软件实例就能够支持每个租户的功能,它们之间的数据互相隔离。就比如 Gitee ,每个用户或组织都拥有自己的空间。它们自己的数据仅在自己的空间内流通,彼此之间互不影响。多租户其实就是一种软件设计结构。 所以。租户模型其实就是分离数据的方式: • 单租户:一个应用一个数据库。其实就是应用分离,数据分离。 • 多租户:一个应用多个数据库。就是同一个应用不同数据库。