在这里插入图片描述

0.引言

在互联网行业,软件工程师面对的产品需求大都是以具象的现实世界事物概念来描述的,遵循的是人类世界的自然语言,而软件世界里通行的则是机器语言,两者间跨度太大,需要一座桥梁来联通,抽象建模便是打造这座桥梁的关键。基于抽象建模,不断地去粗取精,从现实世界到业务模型,从业务模型到设计模型,最终完成现实世界到软件世界的转换。

事实上,服务端开发工程师在大部分工作时间里并不是在写代码,而是在抽象建模。工程师需将业务需求抽象成领域模型、模块、服务和系统,面向对象开发时需抽象出类和对象,面向过程开发时抽象出方法和函数。
某种意义上,软件的本质就是抽象,建模则是系统地实施抽象的过程。作为一种将事物形象化的有效手段,建模可将现实世界中的事物及事物之间的关系准确地表达出来。


1.抽象思维

抽象在中文里可作为动词,也可作为名词。作为动词的抽象是指一种行为,这种行为的结果,就是作为名词的抽象。百度百科对抽象的定义为:人们在实践的基础上,对于丰富的感性材料通过去粗取精、去伪存真、由此及彼、由表及里的加工制作,形成概念、判断、推理等思维形式,以反映事物的本质和规律的方法。

事实上,抽象作为一种高级思维形式,与日常生活关系密切,例如数字,人类初期并没有数字这一概念,原始人类或许能够理解三个苹果和三只鸭子,但不存在数字 “三” 这个概念,在他们的意识里,三个苹果和三只鸭子是没有任何联系的。当人类文明发展到一定阶段,发现了这两者之间存在的一种共性,即 “三”,于是就逐渐形成了数字这个概念。此后,人们就开始用数字对各类事物进行计数。

2.软件世界中的抽象

软件的本质就是抽象,在软件世界里,抽象无处不在,典型如命名抽象、分层抽象、原则抽象。

2.1 命名抽象

作为一名软件工程师,最令你头疼的事情是什么呢?是写代码,看别人的代码,需求评审,还是修 Bug?Quora 和 Ubuntu Forum 曾经针对这个问题进行过广泛地调研,结果显示, 最令软件工程师头疼的事情是命名,没错,就是命名!应用名、包名、类名、方法名、字段名、变量名等等。如果你不曾为命名苦思冥想、反复权衡,也许你还不能算是真正的软件工程师。

关于命名,Stack Overflow 的创始人 Joel Spolsky 曾言:“起一个好名字很难,但这是理所应当的,因为一个好名字需要把要义浓缩在一到两个词(Creating good names is hard, but it should be hard, because a great name captures essential meaning in just one or two words)。” 其实,这个浓缩的过程便是抽象的过程。

很多时候,业务代码的复杂,并非业务本身复杂,而是人为因素造成的,命名混乱就是最常见的因素。虽然不合理的命名并不影响需求的实现,但却加重了认知负荷,随着时间的推移,理解代码的成本会越来越高。同时,命名不合理本质上是抽象不合理,往往影响可复用性。

2.2 分层抽象

在软件开发中,经常会用到各种分层架构,如经典的三层模型(展现层、业务逻辑层、数据层)和 MVC (Model、View、Controller)模型。如图 1 所示为阿里广泛采用四层模型,它包括 View、Service、Manager、DAO 四部分,通过分层将数据访问、通用处理、业务逻辑、终端展示四者解耦,各司其职。View 与用户交互;Service 依赖多个 Manager 和 DAO 实现具体的业务逻辑;Manager 负责通用业务逻辑处理和封装外部服务,它是对 Service 层通用能力的下沉,注重复用性;DAO 负责与底层数据库进行数据交互。分层架构的核心其实就是抽象的分层,每一层的抽象只需要而且只能关注本层相关的信息,从而简化整个系统的设计。
在这里插入图片描述

2.3 原则抽象

在面向对象设计和面向对象编程领域,有一个著名的 SOLID(单一功能、开闭原则、里氏替换、接口隔离以及依赖反转)原则,它是由 Robert Martin 在 21 世纪早期提出。在软件设计和开发中,正确地遵循这些设计原则,有助于提升系统的可维护性和可扩展性。

以依赖倒置原则(Dependency Inversion Principle, DIP)为例,其含义为:抽象不应该依赖于细节,细节应当依赖于抽象。换言之,要针对抽象(接口)编程,而不是针对实现细节编程。这样做有什么好处呢?一个软件系统通常可划分为多个层次,上层调用下层,上层依赖于下层,如果上层依赖的是下层的具体实现,那么,当下层实现细节发生变化时,上层往往也需要同步修改,这就加重了不同层之间的耦合度。但是,如果上层依赖的只是下层的抽象而不是细节,就完全不同了,抽象变化的频率极低,让上层依赖于抽象,实现细节也依赖于抽象,即使实现细节不断变动,只要抽象不变,上层就不需要变化,如此一来大大降低了耦合度。

Java 的 JDBC 是依赖倒置原则的一个典型应用场景 。如图 2 所示,如果没有 JDBC 这一层抽象,软件系统将直接依赖具体的数据库(如 MySQL、Oracle 等),与实现细节耦合,当需要切换到另一种数据库时,就需要修改大量代码来适应细节的变化。若系统依赖的是抽象的 JDBC 接口,那么通过调用 JDBC 即可完成数据库操作,而无须再关注 JDBC 背后的数据库,因为所有关系型数据库的连接库都实现了 JDBC 接口,当需要换数据库时,作为抽象的 JDBC 并不会变化,系统也就无需感知变化。
在这里插入图片描述


3. 经典抽象案例

如图 3 所示,有这样一个关于 “霸屏” 动效的需求,产品文档(Product Requirement Document,PRD)摘要描述如下:

ZFB 会员与 KA(Key Account) 商家合作,升级会员等级特权,因此在会员频道首页通过 “霸屏” 动效提示用户并引导其进入新等级特权页面;

若用户点击 “看我等级特权” 按钮,则自动跳转到新等级特权页面,引导目标达成,“霸屏” 动效不再出现,以免打扰用户;

若用户未点击 “看我等级特权” 按钮,“霸屏” 动效展示 3 秒自动收起。由于引导目标未达成,需继续引导,同时为了防止过度打扰用户,“霸屏” 动效每月最多出现 N 次,N 需支持灵活配置。

在这里插入图片描述
我们来简单分析一下这个需求,核心业务目标在于引导用户进入新等级特权页面,同时兼顾用户体验,避免 “霸屏” 动效过度打扰用户。对于服务端而言,需要实现 “疲劳度” 控制逻辑,即:

若用户点击按钮:持久化用户点击记录,当用户再次访问该页面时,通过查询点击记录就可以判断该用户是否曾点击按钮。若记录存在,则告知前端不要弹出 “霸屏” 动效。

若用户未点击按钮:持久化 “霸屏” 动效对用户的曝光记录,当用户再次访问该页面时,通过查询曝光记录就可以判断该用户是否满足展示 “霸屏” 动效的条件。若当月曝光次数少于 N,则告知前端可弹出 “霸屏” 动效。

3.1 方案一:战术抽象,多快好省,跑步前进

基于上面的需求分析,稍有经验的服务端开发工程师立马就能想出解决方案,如表 1 所示,为每个用户落一条记录即可实现需求。

表 1:点击、曝光记录模型概要
图片
从实现需求的角度来看,上述设计完全可以满足业务当前的需要。如图 4 所示,曝光、点击记录模型几乎完全是由产品文档(PRD)翻译而来,乍看之下,十分的 “信达雅”,简直不要太完美。
图片

图 4 将 PRD 翻译为模型
我们再来仔细分析一下,上面的模型真的好么???显然很一般!!!该模型局限于实现当前业务需求,几乎没有进行抽象建模,因此,建立的模型不能准确地刻画业务的本质。这样的模型可扩展性极差,基本就是一锤子买卖。

在笔者看来,直接 “翻译” PRD 是一种战术编程,或者说战术抽象。John Ousterhout 在《A Philosophy of Software Design》一书中提到:几乎每个软件开发组织都至少有一个将战术编程发挥到极致的开发人员,可称之为战术龙卷风(Almost every software development organization has at least one developer who takes tactical programming to the extreme: a tactical tornado)。战术龙卷风有以下几个特点。

快速。他们常以腐化系统为代价换取当前最快速的解决方案,几乎没有人能比他们更快地完成任务。

高产。他们是高产的程序员,代码量极高,堪称 “卷王”。

坑多。他们往往倾向于简单地进行功能堆积,忽视抽象建模,将成本放到未来,由后来人买单。

从战术龙卷风的特点可以看出,战术编程(抽象)是缺乏或者说忽视抽象建模和系统设计的,聚焦于快速交付,系统能用就行,注重短期收益而非长期价值。当然,这并非完全是软件工程师的问题,不合理的评价体系和行业特点亦难辞其咎。

3.2 方案二:深入分析,透过表象,探寻本质

方案一中 “草率” 地进行抽象建模是不可取的,于开发者自身而言,是一种苟且,无能力提升;于软件项目而言,随意堆积一次性代码,将成本放到未来,是一种不负责任的行为。

如果我们深入分析业务,我们会发现,其实有更好的方案,而且并不复杂。如图 5 所示:首先,忽略 PRD 描述中那些无关紧要的细节,可以发现,PRD 涉及两种场景;然后,针对两种场景,进一步抽取共同特征——场景 S : N 次/周期 Q;最后,洞见共同特征背后的本质——周期维度记账。
图片

图 5 基于业务抽象建立模型

基于【周期维度记账】这一需求本质,我们建立的模型不仅可以满足当前业务的需要:

用户点击按钮:DB 里面落一条记录,其中 scene 可设为 “CLICK”。当用户再次进入对应页面时,先根据 userId 和 scene 查询记录,若存在,则说明用户已经点击过按钮,告知前端无需展示“霸屏”动效。

用户未点击按钮:DB 里面落一条记录,其中 scene 可设为 “EXPOSE”。当用户再次进入对应页面时,先根据 userId 和 scene(CLICK)查询、判断用户是否点击过按钮,如果没有点击,则根据 userId 和 scene(EXPOSE)查询、判断并更新曝光次数 count。

与此同时,基于【周期维度记账】这一需求本质,我们建立的模型具有更好的可复用性、可扩展性。举两个例子:

多周期:基于字段 quantum 和 bizDt,可以支持终身、年、月、周、日等时间维度记账。满足不同业务场景的需要。

多场景:基于字段 scene,可以实现不同业务场景的数据隔离,同时支持多个场景,以及数据分析等附加需求。

  1. 抽象并非一蹴而就!需要不断假设、验证、完善
    如图 6 所示,在人类文明早期,人们基于直观地观测,认为地球是宇宙的中心,因此抽象出了 “地心说” 模型。随着时间的推移和观测手段的进步,人们观察到的天文现象越来越多,逐渐意识到 “地心说” 模型与观测结果存在矛盾,于是,人们开始对 “地心说” 模型进行修正(像极了程序员重构模型),典型如 “本轮-均轮” 模型。

然而,随着更多的天文现象被发现,在 “地心说” 模型的大框架下,无论如何修正都无法自圆其说。在 “地心说” 模型统治人类 “天文世界观” 很长一段时间后,勇敢的先行者推翻了 “地心说” 模型,并提出了在当时看来离经叛道的 “日心说” 模型。

在这里插入图片描述

从 “地心说” 模型被提出,到 “日心说” 模型被广泛接受,跨越了 1400 多年的时间。这一史实表明,人们对事物本质的探索是一个过程,而非一蹴而就!!!对于服务端开发而言,我们对需求的认知也是如此,初见之下,我们往往很难直接洞见其本质,而需要不断假设、反复推演,最终才能抽象出较好的模型。

你可能会问——抽象建模如此麻烦,开发时间往往又不充裕,何必苦苦探寻所谓的本质呢?能用不就行了么?

如果你确有上述疑问,不妨换个角度,想一下 “核心竞争力” 的内涵。很多时候,我们并不缺乏解决问题的办法、能力和资源,而缺乏的是对问题的识别、理解、抽象。当一个问题被抽象为足以刻画业务本质的模型,并拆解到软件项目维度的时候,面对确定的任务、清晰的目标,可以解决问题的人就非常多了。

某种程度上,解决问题的能力是重要的基础,但若仅仅是解决问题还远远不足以称为核心竞争力。对于服务端开发工程师而言,抽象建模能力比编程落地能力更重要,因为编程解决问题只是一种普通技能而已,而对具象事物(如业务需求)的高度抽象,探索事物的本质,需要我们从新的角度审视旧的问题,需要有创造性的想象力,这才是真正的难点,当然也是核心竞争力所在。

最后,不要苟且,不要应付。我们每一次对事物的深入思考、对表象背后本质的探寻,都是一次自我提升。

5. 推荐一本书

PS:本文内容节选自业界首部体系化、全景式解读服务端开发的著作——《服务端开发:技术、方法与实用解决方案》。

在这里插入图片描述

《服务端开发:技术、方法与实用解决方案》一书取材自阿里和蚂蚁集团的精品内训课程,由资深服务端技术专家、技术讲师、阿里第二届技术讲师课程大赛年度冠军得主、CSDN 博客专家撰写。该书理论与实践结合,全景式、体系化地阐述了服务端开发,核心内容包括以下两个部分。

第一部分:服务端开发的技术和方法

首先介绍服务端开发的职责、技术栈、核心流程和进阶路径;然后从需求分析、抽象建模、系统设计、数据设计和非功能性设计 5 个方面展开,结合案例深入讲解了服务端开发的实操方法和重难点,为读者呈现服务端开发的全景图,帮助读者快速、体系化地掌握服务端开发的知识和方法。

第二部分:服务端典型问题的解决方案

针对高并发、高性能、高可用、缓存、数据一致性、幂等、秒杀等服务端开发实践中的典型问题,给出了对应的解决方案和开发规范,同时还结合案例深入分析了不同方案的优缺点。此外,还总结了接口设计、日志打印、异常处理、代码编写、代码注释等落地层面的行业案例和规范。

读者对象

IT 从业人员:服务端开发工程师、客户端开发工程师、产品经理、测试开发工程师等。

高校学生:计算机、软件、自动化、电气、通信等专业有志于进入 IT 行业的在校学生。

在这里插入图片描述

目前,本书已经在京东、淘宝、当当、拼多多等电商平台发售。在电商 APP 搜索关键词 “服务端开发”、“服务端开发技术”,即可搜索到该书。

🍔彩蛋

⭐ 《阿里后端开发:抽象建模经典案例》免费包邮送3本!
⭐活动时间:截止到 2023-09-15 20:00:00
⭐ 抽奖方式:利用程序进行抽奖。
⭐参与方式:关注博主、点赞、收藏、评论区进行高质量评论(不少于10个字),即可参加抽奖活动
⭐本次活动一共赠3本,评论区抽取3位小伙伴免费送出!!

相关文章

使用Go Validator在Go应用中有效验证数据

Go Validator是一个开源的包,为Go结构体提供强大且易于使用的数据验证功能。该库允许开发者为其数据结构定义自定义验证规则,并确保传入的数据满足指定的条件。Go Validator支持内置验证器、自定义验证器,甚至允许您链式多个验证规则以满足更复杂的数据验证需求。如果内置验证器无法满足您的需求,您可以通过定义自己的验证函数来创建自定义验证器。这个功能允许您实现特定于应用程序需求的验证逻辑。

C语言中strstr函数的使用!

这里要进行分析,有一个重要的点就是,成勋会返回abc及其后面的字符,如上图所示p2代表abc,而abc在p1中能够找到,所以返回abc和p1中abc后面的所有字符,这是一个需要注意的地方。//判断p2字符串是不是在p1中,如果在就是子字符串,否则不是。if (ret == NULL) //函数返回值是保存在ret这个字符指针变量中的,为空说明不是子字符串。printf("子字符串不在\n");具体直接看下面的这段代码我相信你必明白。

ubuntu20.04安装实时内核补丁PREEMPT_RT

下载实时内核补丁,我下载patch-5.15.148-rt74.patch.sign和patch-5.15.148-rt74.patch.xz。通过以下指令看具体报错并输出日志到make.log:make -j1 deb-pkg 2>&1 | tee ~/make.log。比较幸运没遇到问题,重启进入后,启动页面没有变化,还是进入ubuntu,但是查看内核版本已经自动变到5.15.148。我下载linux-5.15.148.tar.xz和linux-5.15.148.tar.sign。

Linux 目录磁盘满了,怎么查找大文件

如果你不确定某个文件或目录的用途,最好先进行调查或咨询专业人士,而不是直接删除它们。,这是一个基于文本的磁盘使用分析器,非常适合于查找大文件。如果它没有预装,你可以通过你的包管理器安装它(例如,在Ubuntu上使用。会分析根目录的磁盘使用情况,并提供一个交互式界面来浏览最大的文件和目录。请注意,运行这些命令可能需要一些时间,因为它们会检查许多文件。)磁盘满了,你可以使用以下方法来查找占用空间最大的文件和目录。这个命令会搜索根目录下所有的文件,并显示它们的大小。为了找到最大的文件,你可以使用。

如何在 Debian 12 上安装 Microsoft SQL Server?

在安装 Microsoft SQL Server 之前,我们需要确保系统是最新的,并安装一些必要的软件和依赖项。以下是详细的步骤:这将更新软件包列表并升级已安装的软件包。这将安装 curl 用于下载文件,gnupg 用于导入 GPG 密钥,以及 apt-transport-https 用于通过 HTTPS 访问软件包。

服务器与电脑的区别?

服务器是指一种专门提供计算和存储资源、运行特定软件服务的物理或虚拟计算机。服务器主要用于接受和处理来自客户端(如个人电脑、手机等)的请求,并向客户端提供所需的服务或数据。服务器在网络环境中扮演着中心节点的角色,负责存储和管理数据、提供网络服务、处理计算任务等。

windows下ngnix自启动(借助工具winSw)

在windows下安装nginx后,不想每次都手动启动。本文记录下windows下ngnix自启动(借助工具winSw)的操作流程提示:以下是本篇文章正文内容,下面案例可供参考本文记录下windows下ngnix自启动(借助工具winSw)的操作流程。

linux docker 部署mysql8以上版本时弹出Access denied for user root @ localhost (using password: YES)的解决方案

mysql8登录第一次遇到MYSQL_ROOT_PASSWORD时会自动把该密码尽兴登录,生成一个秘钥放在mysql的数据文件里面,命令里带的MYSQL_ROOT_PASSWORD密码是个参数,除了第一次运行mysql带上会设置密码生成秘钥,其他次启动而不是设置mysql的密码,而是作为参数去验证这个最初的秘钥是否核对正确,于是我进入挂载的data目录,发现我的猜想是对的。通过docker将服务部署完后,navicat连接报错,密码错误,于是我尝试进入mysql容器登录 发现也报错。

Linux 磁盘空间占用率100%的排查

max-size 最大数值 , max-file 最大日志数,但一两个容器还好,但是如果有很多容器需要管理,这样就很不方便了,最好还是可以统一管理(全局修改)结果显示多条如下数据,这里最关键的指标就是使用百分比,这个值较高一般需要处理,或者明确知道自己项目或工作目录是哪个,就只要找对应的位置去处理即可。/var/lib/docker/overlay2 【文件系统】基于容器文件系统保存的数据会写到本机的此目录下,进行限制,以减少日志文件对存储空间的占用,以下配置分别为日志文件最大容量、最大日志文件数。

chatchat部署在ubuntu上的坑

2. 安装后把代理关闭,全局的代理改为手动,重新打开一个新的控制台。1. 安装前要开代理,注意要下载很多东西,流量大。

Kafka常见生产问题详解

比如,在原有Topic下,可以调整Producer的分区策略,让Producer将后续的消息更多的发送到新增的Partition里,这样可以让各个Partition上的消息能够趋于平衡。思路是可行的,但是重试的次数,发送消息的数量等都是需要考虑的问题。PageCache缓存中的消息是断电即丢失的。因为如果业务逻辑异步进行,而消费者已经同步提交了Offset,那么如果业务逻辑执行过程中出现了异常,失败了,那么Broker端已经接收到了消费者的应答,后续就不会再重新推送消息,这样就造成了业务层面的消息丢失。

Zookeeper分布式队列实战

ZooKeeper实现队列步骤1.创建队列根节点:在Zookeeper中创建一个持久节点,用作队列的根节点。所有队列元素的节点将放在这个根节点下。2.实现入队操作:当需要将一个元素添加到队列时,可以在队列的根节点下创建一个临时有序节点。节点的数据可以包含队列元素的信息。3.实现出队操作:当需要从队列中取出一个元素时,先获取根节点下的所有子节点。再找到具有最小序号的子节点,获取该节点的数据,删除该节点,然后返回节点的数据。

内网穿透、远程桌面、VPN的理解

针对不同的场景可能咱们可以选择不同的方法,局域网远程桌面这种其实也不是很常用,为什么呢,因为如果就在局域网的话,那么你本人直接过去操作就可以了,不需要远程桌面,而且远程桌面还需要给你的登录账户和密码,这些都是隐私的东西,一般最好不对外泄露。VPN其实是比较适合在家远程办公的场景的,电脑带回家,然后连接VPN,就可以实现办公了,但是也有一些问题,就是公司必须要一个固定的IP,还必须要配一个VPN服务器,固定IP这个是越来越少了,很多宽带都不是固定外网IP了。

Web 安全之点击劫持(Clickjacking)攻击详解

点击劫持(Clickjacking)攻击,又称为界面伪装攻击,是一种利用视觉欺骗手段进行攻击的方式。攻击者通过技术手段欺骗用户点击本没有打算点击的位置,当用户在被攻击者攻击的页面上进行操作时,实际点击结果被劫持,从而被攻击者利用。这种攻击方式利用了用户对网站的信任,通过覆盖层(通常是透明的iframe)覆盖在另一个网页之上,使受害者无法察觉。

浅谈ARM嵌入式中的根文件系统rootfs

这里设置 console 为 ttymxc0,因为 linux启动以后 I.MX6ULL 的串口 1 在 linux 下的设备文件就是/dev/ttymxc0,在 Linux 下,一切皆文件。/dev/mmcblk1、/dev/mmcblk0p1、/dev/mmcblk0p2、/dev/mmcblk1p1 和/dev/mmcblk1p2 这样的文件,其中/dev/mmcblkx(x=0~n)表示 mmc 设备,而/dev/mmcblkxpy(x=0。有这个“根”,其他的文件系统或者软件就别想工作。

linux配置DNS主从服务器

主服务器:OpenElur Linux IP地址为192.168.188.129。从服务器:RedHat Linux IP地址为192.168.188.128。2.配置主服务器的`解析配置文件。3.进行从服务器的基础配置。1.进行主服务器的基础配置。

SpringBoot:详解Bean生命周期和作用域

前面我们讲诉了将Bean正确地装配到IoC容器,却未讲诉IoC如何装配和销毁Bean。本篇文章主要讲诉一下Bean的生命周期和作用域。以上就是Bean生命周期和作用域的讲解。

Docker之nacos的安装和使用

在上一期的博客分享中我们分享了有关Nginx的安装和使用,当然我们知道上一期的博客分享的是使用Nginx实现负载均衡。本期的博客文章基于上一期的Docker之Nginx安装的基础上,本期的。

MySQL数据库主从复制集群原理概念以及搭建流程

主从复制是指将主数据库的 DDL 和 DML 操作通过二进制日志传到从库服务器中,然后在从库上对这些日志重新执行(也叫重做),从而使得从库和主库的数据保持同步。MySQL支持一台主库同时向多台从库进行复制, 从库同时也可以作为其他从服务器的主库,实现链状复制。主库出现问题,可以快速切换到从库提供服务。实现读写分离,降低主库的访问压力。可以在从库中执行备份,以避免备份期间影响主库服务。

计算机组成原理 CPU的功能和基本结构和指令执行过程

根据指令执行过程中的数据和地址的流动方向安排连接线路,避免使用共享的总线,性能较高,但硬件量大。(PC)->Bus->MAR   PCout 和 MARin 有效,现行指令地址->MAR。(MDR)->Bus->IR   MDRout 和 IRin有效,现行指令->IR。每个指令时间可能不同,但是在单指令周期下,所有指令选用相同的执行时间,指令间串行。MEM(MAR)->数据线->MDR   操作数从存储器->数据线->MDR。MDR->Bus->Y   MDRout 和 Yin 有效,操作数->Y。

HarmonyOS4.0系统性深入开发19进程模型概述

HarmonyOS通过CES(Common Event Service,公共事件服务)为应用程序提供订阅、发布、退订公共事件的能力。公共事件从系统角度可分为:系统公共事件和自定义公共事件。系统公共事件:CES内部定义的公共事件,只有系统应用和系统服务才能发布,例如HAP安装,更新,卸载等公共事件。目前支持的系统公共事件详见系统公共事件列表。自定义公共事件:应用自定义一些公共事件用来实现跨进程的事件通信能力。公共事件按发送方式可分为:无序公共事件、有序公共事件和粘性公共事件。

Linux(Ubantu)交叉编译生成windows(32位,64位)可执行程序和库

与 mingw32 相比,mingw-w64 提供了对 64 位 Windows 应用程序的支持,并且通常被认为是更现代和更新的工具。这个选项通常用于 Unix-like 系统的编译器,用以指导链接器在生成可执行文件时保留符号信息,以便支持运行时的符号解析(例如用于动态加载库).该选项对于 Windows 下的编译是无效的,通过。(能够解析windows平台的可执行程序) 则能直接允许直接在linux环境中运行我们生成的win32的可执行程序(包括验证win32平台的动态库).

如何使用可视化管理工具DockerUI远程管理docker容器

DockerUI是一个docker容器镜像的可视化图形化管理工具。DockerUI可以用来轻松构建、管理和维护docker环境。它是完全开源且免费的。基于容器安装方式,部署方便高效,浏览和维护docker单节点或集群节点worker和manager。DockerUI具有易于使用的界面。它不需要记住 docker 指令。只需下载镜像即可立即加入并完成部署。使用DockerUI并结合cpolar内网穿透可以更加轻松的管理docker和swarm,实现后台公网访问并管理,视觉性更加直观,后台开发更加便利。

如何使用Docker将.Net6项目部署到Linux服务器(三)

尤其在测试环境,多个项目公用一个nginx的情况很多,这个时候,如果多个项目的nginx配置都放在一个conf配置文件中,会特别混乱。按照nginx配置,它应该监听4012端口,然后找到根目录/usr/local/publish_2023/forum_manage_vue,访问我们的vue网站,可是却提醒我们,该网页无法显示。# 注意,还可以写域名,但是需要额外的配置,后面示例会介绍,这个实例是简单的测试服务器的nginx配置、不过多说明。在nginx下的conf中,找到配置文件nginx.conf。
返回
顶部