让开发回归简单模式-组件封装
对于工作年限不长的程序员来说,知识储备是非常关键的。在开发中各种技术的应用已经非常普遍了,例如常见的各种ORM,各种中间件如Redis,MQ等等,又如WebApi路由配置等等,对于常常做开发的程序员来说,都是小事,我们就从小事说起。
在微服务中,常用到MQ作为微服务之间通讯的桥梁,以RabbitMQ为例,其转发的方式有direct、fanout、topic,而在微服务中的应用,几乎不会使用direct这种交换模式。对于程序员来说,具体使用哪一种交换模式,需要开发时候双方去协商和沟通通讯的数据结构,还要处理通讯过程出现异常的情况,这样下来,从发送和校验到接收和处理,一系列下来,代码少说也有一百几十行,还要话费沟通成本,还需要程序员对mq的掌握。对于组织开发者来说,就是一大堆的培训工作,不培训就要花费时间成本。
fanout这种交换模式,就如大喇叭,发出去的消息,只要愿意,都能够接收到,是一种比较开放的消息发布模式。例如一个员工的基础信息发生了改变,其他微服务需要更新这个员工的显示信息,那么都来接收就好了,至于接收到怎么处理,那是接收方的事情了,只要接收成功,回应一个ack信号就可以了。
topic这种交换模式,是具有指定性的,只有匹配到topic字符串的接收方,才能收到消息,就向路由一样。例如做一个系统的内部通知消息,要通知到岗位或者个人,可以使用通配符:
# 匹配多个多个单词,例如message.pos1.emp1 使用message.# 所有消息都能成功匹配上;
* 匹配单个单词,例如message.pos1.* 在pos1下的所有人都能收到这个消息。
程序员是否需要了解这些?我感觉不需要,我们把发送消息封装成一组类,一个是用于发送,一个是用于接收,例如:
生产者接口
public interface MQProducer
{void Publish<T>(T body);}
消费者接口
public interface MQConsumer
{//使用topic订阅消息void Consume(QueueDeclare queue, string topic,Action<string> action);//使用fanout订阅消息void Consume(QueueDeclare queue,Action<string> action);
}
上述方法,只要稍微了解MQ的,都知道这么封装,在微服务中的消息传递相对比较简单的,可以进一步封装。生产者这一端,可以使用AOP方法制作一个发布消息的标签,例如:
public class SaleSerivce : ServiceBase<SaleHdr,SaleDtl>
{//当成功保存单据后,当前微服务ID为AppId,以Sale为资源,SaveBill为action标记发送SaleHdr对象[MQPublish]public RValue<SaleHdr> SaveBill(SaleHdr hdr,List<SaleDtl> dtls){}//这里解释一下RValue<T>这个结构//当方法体出现异常,RValue<T>接收Exception对象,并设置Success=false;//当方法体返回字符串,RValue<T>.Message接收字符串值,并设置Success=false;//当方法体返回SaleHdr对象,RValue<T>.Value接收对象,并设置Success=true;//MQPublish标签,在Success==true时候把SaleHdr对象包装成一个标准的通讯数据格式后,转成json发送出去
}
接收端就有点复杂了,对不同交换方式,要开发一套对应的数据接收和转发机制。 首先,接收到的消息,否存到一个消息对象中,然后塞到一个Queue对象中,只要向Queue中加元素,则触发出队列的方法,直到读取Queue完成才终止。
public class PurService : SeriveBase<PurHdr,PurDtl>
{[MQConsume("saleApp","sale","savebill")] //appid,resource,actionpublic RValue<PurHdr> MQSaleSave(SaleHdr saleHdr){//当新建销售单的时候,采购查询一下是否需要补货}
}
建立一个MQStarter来订阅MQ消息,并根据MQConsume标签上的参数,匹配到方法,可能会匹配到多个方法,没有关系,通通调用一次就可以了。如果RValue<PurHdr>.Success==false ,则做日志,并把消息方到另外一个容器中,允许重试规定次数后再手动重发。
上述生产者和订阅者,都没有接触到MQ的具体对象和相关代码,只用了两个标签就完成了两个微服务之间的数据交互,只要框架的开发者能够在这个封装中充分考虑到各种情况和处理好各种异常,那么对于程序员来讲是非常轻松的事情,不用考虑通讯协议、结构、方法等等,集中精力编写业务逻辑代码。即使出现通讯问题,只需要反馈就可以了,让开发回归到本质。
在微服务中,用得最多的就是httpClient、redis这两个组件。
HttpClient可以根据封装好的WebApi标准接口进行封装,程序员只需要直接调用方法和给参数就可以完成api调用且方便处理好api返回值,转换成所需要的数据结构。
Redis同理,可以封装成MemoryCache这样的操作方式,分别多String,Hash等数据结构操作。
为了然程序员最大程度减少对技术依赖,把一些常用或者复杂的工作进行封装,转化为简单的操作方式,例如ORM,特别是使用EF的,往往需要程序员开发时候直接操作EF读写数据,带来的问题,往往没有处理读写时候的异常,导致程序在特定情况下卡死或者报错。这里建议把ORM用一层数据访问层包起来,而这个ORM对象只是一个protected层级的,把常规的读写操作都封装成方法,派生出来的对象,都是使用方法,而不使用ORM对象。即使那天把ORM换掉了,对原来的程序也没有一点影响,例如原来程序使用mysql,后面发现结构很简单,用mongo可能更合适,只要改变一下数据层的实现类就可以了,一般数据层都是注入到系统的,对于部署来说,就只是换了一个dll文件,对于程序员来说,几乎没有影响,除非操作了ORM。
程序员连最基本的数据库操作对象都不需要了解,甚至可以不知道用了哪种ORM,程序员就纯粹写业务逻辑,可以把业务中的各种复杂情况都考虑仔细。让程序开发真正回归简单化。
这样带来一个问题,非常不利于程序员的成长,这个就需要程序员在工作过程中注意细节、更多思考,从别人的案例中学习技术技巧,多尝试,转变成真正自己的知识。
在我的框架中,把事务处理也封装成一个标签,这个是参照java中的写法,只是加了更多自己的想法,把事务嵌套、分布式事务都考虑进去了,例如:
[Transaction] //事务标签,若当前没有在事务中,则发起事务,否则这个标签相当于透明
publice RValue<StoreInHdr> SaveStoreIn(StoreHdr,List<StoreDtl> dtls)
{//这里要处理进仓的操作,同时发起分布式事务标记到货单和采购单//完成库存的更新
}
这样让程序员完全不用考虑事务过程的处理,至于是提交还是回滚,那就看RValue的返回值。
对于企业来说,用人是一个很大的风险,找水平高的,不愿意带人,写的代码一般程序员还不一定能看懂,自己还有自己的一套风格,换个人维护就很难了。找水平低的,又不按规则来,考虑问题不仔细,会出很多乱子。通过封装,除了简化了开发难度,也制定了开发规则,使用统一标准,有利于项目的持久迭代和发展。
相关文章:
让开发回归简单模式-组件封装
对于工作年限不长的程序员来说,知识储备是非常关键的。在开发中各种技术的应用已经非常普遍了,例如常见的各种ORM,各种中间件如Redis,MQ等等,又如WebApi路由配置等等,对于常常做开发的程序员来说,都是小事&…...

LED显示屏安全亮度参数设置方法和防护
随着LED显示屏应用领域越来越广,但其高亮度造成的光污染,常受到的人们的诟病。为了更好的避免光污染,我整理了一些关于LED显示安全亮度参数设置方法和安全防护措施。你知道LED广告牌是如何工作的吗? 设置LED显示屏的安全亮度参数和…...
数据库sql--关于计算方圆5公里点位编写
当我们计算两个地球上任意两点之间的距离时,可以使用Haversine公式。 下面是每个函数和数值的详细解释: RADIANS(target_latitude):将目标纬度值转换为弧度制。这是因为Haversine公式以弧度为单位计算角度。RADIANS(latitude):将…...

嵌入式基础知识-DMA
本篇来介绍DMA的一些基础知识。 1 DMA简介 DMA(Direct Memory Access),中文名为直接内存访问,它是一些计算机总线架构提供的功能,能使数据从附加设备(如磁盘驱动器)直接发送到计算机主板的内存上。对应嵌…...

STM32 软件IIC 控制OLED 显示屏
1. 硬件IIC 实在是太难用了,各种卡死,各种发不出来数据,没那么多时间折腾了,还是用软件IIC 先吧,初始化 void OLED_Software_IIC_Init(void) {GPIO_InitTypeDef GPIO_InitStruct;RCC_AHBPeriphClockCmd(OLED_SOFTWARE…...

【系统设计系列】 DNS和CDN
系统设计系列初衷 System Design Primer: 英文文档 GitHub - donnemartin/system-design-primer: Learn how to design large-scale systems. Prep for the system design interview. Includes Anki flashcards. 中文版: https://github.com/donnemarti…...

thinkphp中使用Elasticsearch 7.0进行多表的搜索
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、thinkphp中使用Elasticsearch 7.0进行多表的搜索二、使用步骤1.引入库2.读入数据 总结 前言 提示:thinkphp中使用Elasticsearch 7.0进行多表的…...

说说 TCP的粘包、拆包
分析&回答 拆包和粘包是在socket编程中经常出现的情况, 在socket通讯过程中,如果通讯的一端一次性连续发送多条数据包,tcp协议会将多个数据包打包成一个tcp报文发送出去,这就是所谓的粘包。如果通讯的一端发送的数据包超过一…...
PowerToys安装
PowerToys 是微软开发者开发的免费实用工具集,可以用于高级用户调整和简化 Windows 操作,以提高效率。 官网安装方法: https://learn.microsoft.com/zh-cn/windows/powertoys/install 目前安装文件路径: https://github.com/m…...

Unity——LitJSON的安装
一、LitJSON介绍 特点 LitJSON是一个轻量级的C# JSON库,用于在Unity游戏开发中进行JSON数据的序列化和反序列化操作。它提供了简单而高效的接口,帮助开发者处理JSON数据。 以下是LitJSON库的一些主要特点和功能: 1. 高性能:Lit…...

YOLOv5:对yolov5n模型进一步剪枝压缩
YOLOv5:对yolov5n模型进一步剪枝压缩 前言前提条件相关介绍具体步骤修改yolov5n.yaml配置文件单通道数据(黑白图片)修改models/yolo.py文件修改train.py文件 剪枝后模型大小 参考 前言 由于本人水平有限,难免出现错漏,…...
大数据(八):Pandas的基础应用详解(五)
专栏介绍 结合自身经验和内部资料总结的Python教程,每天3-5章,最短1个月就能全方位的完成Python的学习并进行实战开发,学完了定能成为大佬!加油吧!卷起来! 全部文章请访问专栏:《Python全栈教程(0基础)》 再推荐一下最近热更的:《大厂测试高频面试题详解》 该专栏对…...

【算法】归并排序 详解
归并排序 详解 归并排序代码实现1. 递归版本2. 非递归版本 排序: 排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 稳定性: 假定在待排序的记录序列中,存在多个具有相…...

linux 进程隔离Namespace 学习
一、linux namespace 介绍 1.1、概念 Linux Namespace是Linux内核提供的一种机制,它用于隔离不同进程的资源视图,使得每个进程都拥有独立的资源空间,从而实现进程之间的隔离和资源管理。 Linux Namespace的设计目标是为了解决多个进程之间…...

【MySQL】事务 详解
事务 详解 一. 为什么使用事务二. 事务的概念三. 使用四. 事务的特性原子性(Atomicity)一致性(Consistency)隔离性(Isolation)持久性(Durability) 五. 事务并发所带来的问题脏读问题…...

爬虫到底难在哪里?
目录 爬虫到底难在哪里 怎么学习爬虫 注意事项 爬虫工具 总结 学习Python爬虫的难易程度因人而异,对于具备编程基础的人来说,学习Python爬虫并不困难。Python语言本身比较简单易学,适合初学者使用。 爬虫到底难在哪里 爬虫的难点主要包…...
linux常用命令行整理
1、linux的以及目录 bin 二进制可执行文件sbin 二进制可执行文件(root用户权限)etc 系统管理和配置文件,例如常见host文件home 用户文件的根目录usr 用户存放系统应用程序(共享系统资源)opt 可选的应用程序proc 虚拟文件系统root 超级用户dev 存放设备文件mnt 系统管理员安装临…...
python字符串相关
python字符串相关 一、reverse() 函数 只能反转 列表二、reversed() 反转元组字符串等等 返回迭代器三、join和reversed反转字符串四、join串联字符串(join连接对象仅限字符串、储存字符串的元组、列表、字典)数字对象可通过str()转化为字符串⭐对象为字…...

JavaScript学习笔记01
JavaScript笔记01 什么是 JavaScript JavaScript 是一门世界上最流行的脚本语言,它是一种弱类型的脚本语言,其代码不需要经过编译,而是由浏览器解释运行,用于控制网页的行为。 发展历史 参考:JavaScript的起源故事…...

golang 通用的 grpc http 基础开发框架
go-moda golang 通用的 grpc http 基础开发框架仓库地址: https://github.com/webws/go-moda仓库一直在更新,欢迎大家吐槽和指点 特性 transport: 集成 http(echo、gin)和 grpc。tracing: openTelemetry 实现微务链路追踪pprof: 分析性能config: 通用…...

网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...

网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

Linux部署私有文件管理系统MinIO
最近需要用到一个文件管理服务,但是又不想花钱,所以就想着自己搭建一个,刚好我们用的一个开源框架已经集成了MinIO,所以就选了这个 我这边对文件服务性能要求不是太高,单机版就可以 安装非常简单,几个命令就…...

沙箱虚拟化技术虚拟机容器之间的关系详解
问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西,但是如果把三者放在一起,它们之间到底什么关系?又有什么联系呢?我不是很明白!!! 就比如说: 沙箱&#…...

ArcGIS Pro+ArcGIS给你的地图加上北回归线!
今天来看ArcGIS Pro和ArcGIS中如何给制作的中国地图或者其他大范围地图加上北回归线。 我们将在ArcGIS Pro和ArcGIS中一同介绍。 1 ArcGIS Pro中设置北回归线 1、在ArcGIS Pro中初步设置好经纬格网等,设置经线、纬线都以10间隔显示。 2、需要插入背会归线…...