记录第一次带后端团队

在过去的一个半月里我第一次作为后端开发组长角色参与公司项目从0到1的开发,记录这一次开发的经历。

1、背景介绍

首先说明一下背景。我所在的公司是做智慧社区相关业务,开发的项目是系统升级工具,方便公司实施同事安装和升级系统。

参与后端开发一共四个人,包括我在内。其他三个同事有一个是应届生、两个做大数据的。按照公司的技术规划,对内项目开发节奏要短平快,用Python语言完成,对外的项目一律用Java语言完成。

项目经过正常开发生命周期,包括需求采集、产品设计、系统设计、详细设计、编码、测试等过程。其中详细设计就是针对接口做的详细设计,一共用时3天完成,设计了45个功能点,包括40个接口和5个初始化准备工作。编码用时计划为3周。最终在时间点之内完成了相关的开发。

我在这次开发过程中担任的是组长的角色,主要的任务包括:

(1)项目框架的搭建。本次开发是一个从0到1的过程,在此之前并没有Python项目的框架。

(2)关键技术的实现。包括通用接口,复杂的技术点。

(3)任务分配。所有接口根据任务量分配给指定的成员,完成最多的接口开发。


2、项目框架搭建

Python做web开发常用的项目框架其实并不是很多,我的候选项有三个:

Django 前后端不分离框架、Flask 最容易上手的框架、FastAPI 异步高性能框架。

对比这三个框架,我从业务逻辑、公司技术栈、复杂度等三个角度出发,选择了Flask。

业务逻辑

业务逻辑对性能并没有特别要求,就是通过接口调用运维的ansible脚本,没有高并发,计算密集等任务,所以三个都能满足。

技术栈

公司技术栈是前后端分离,所以Django这种前后端不分离的框架并不适合,虽然Django也可以做纯后端开发(防杠)。

复杂程度

复杂度来说肯定是Flask最简单。Django号称大而全,配置复杂。FastAPI是异步框架,需要学习异步编程,虽然用来做同步框架也很丝滑,但是学习成本需要增加很多。其他三个同事都没有做过Python项目,所以尽量减少学习成本。

经过这三个方向的衡量,最终确定了Flask框架,搭配peewee orm数据库框架。核心的技术包括:

(1)web框架 Flask

(2)数据库ORM框架 peewee

(3)数据库 sqlite

(4)运维脚本执行模块 subprocess

(5)WSGI服务 Gunicorn

(6)代码检查工具pre-commit

在编码前我已经准备好完整的项目框架,写好了数据库CRUD接口的demo,后续开发过程同事模仿相关接口,一定程度上提高了开发效率。


3、关键技术实现

带团队开发并且是带领成员第一次做Python项目,自然要将有挑战的任务安排给自己。在关键技术的实现上挑选三个有代表性的讲解。三个分别是:系统命令执行通用接口、流式日志、sqlite 多线程写问题解决。

系统命令通用接口

项目主要用于公司开发的其他系统安装和升级,因此需要调用运维人员用ansible编写的相关脚本。调用的ansible脚本格式如下:

ansible-playbook 03.mysql.yml
ansible-playbook 08.zk.yml

需要到指定的路径下执行如上的命令。在详细设计阶段就知道需要使用Python调用系统命令的工具,所以就让应届生同事调研了subprocess模块,输出相关文档。一来是给新人一个学习方向,再则借这个机会熟悉项目需要的技术。

在开发阶段根据对相关模块的理解,完成了通用接口的开发。写通用接口切忌朝令夕改,依赖它的代码也要随之变化。一两次还能接受,次数多估计要被问候祖宗了。所以该接口实现程度不仅仅是写完,而且是自己亲自调用,确认没有问题才宣告完成。

在没有完成之前耐着性子调试,直到没有任何问题才在群里告诉其他开发人员。整个系统中需要大量的调用该命令执行脚本,最终也都比较顺利的完成,没有因为接口造成的bug。

流式日志

按照产品的设计,当一个组件在安装时需要在web页面上展示日志,并且日志的格式要和终端中安装日志一样,也就是一行一行的滚动打印。产品对日志的要求是全量滚动展示,刷新页面要能够再次全量展示出来。为了实现该功能,调研了三个方案:

一、定时刷新。缺点:日志有几万行,每一次读取全部日志给前端,前端会卡顿,而且打印也不连续,体验不好。

二、websocket。可以完成后端向前端的主动推送,但是刷新页面并不会从头开始推送。

三、流式响应。可以将大块文件切分成小块分批传给前端,刷新页面时会再次从头开始推送,符合要求。

经过对比最终使用了流式响应,也就是ChatGPT那种响应的方式。但是需要解决一个问题:什么时候结束推送?因为安装一边向文件中写入日志,流式日志一边读出日志,如果日志已经读完了安装还没结束,那这个时候肯定需要等待而不是停止响应。

解决办法是在安装完成之后插入标记字符,当流式日志读取到标记字符时就表明结束了,没有读取到标记字符则等待。核心代码如下:

def log_flow():query = request.valueslog_path = query["log_path"]def generate():with open(log_path, "r") as f:while True:chunk = f.read(800)if not chunk or chunk.isspace():time.sleep(0.1)if chunk == 800 * "-":breakcontent = json.dumps({"content": chunk})yield f"event: message\ndata: {content}\n\n"time.sleep(0.05)return Flask_response(generate(), mimetype="text/event-stream"

效果:

sqlite3 多线程写问题

在数据库存储这一块,领导钦定用sqlite3,咱也据理力争过用MySQL,but无效。领导说该项目只需要一个轻量的数据库即可,sqlite3轻量,所以就很合适。而且其他项目中已经使用的非常成熟了。好吧,既然领导坚持,我也只能硬着头皮上了。

开始还没问题,到了项目开发中后期就发现问题了,接口经常报错:

File "/home/ljk/.virtualenvs/idt_dev/lib/Python3.8/site-packages/peewee.py", line 3246, in execute_sql
cursor.execute(sql, params or ())
File "/home/ljk/.virtualenvs/idt_dev/lib/Python3.8/site-packages/peewee.py", line 3014, in __exit__
reraise(new_type, new_type(exc_value, *exc_args), traceback)
File "/home/ljk/.virtualenvs/idt_dev/lib/Python3.8/site-packages/peewee.py", line 192, in reraise
raise value.with_traceback(tb)
File "/home/ljk/.virtualenvs/idt_dev/lib/Python3.8/site-packages/peewee.py", line 3246, in execute_sql
cursor.execute(sql, params or ())
peewee.OperationalError: database is locked

查询之后发现是sqlite3不支持多线程写。sqlite3支持事务,是用库锁来完成的。当一个写入开始后,整个数据库都加锁了,再次有写操作就会报错。

这个问题首先从技术上是不好解决的,sqlite3的架构设计就是如此,还能让它支持多线程写吗?只能通过业务逻辑解决。经过一次会议讨论之后,得出几个解决方法:

  • 分库。将写操作分到不同的库里完成。既然写操作会锁库,那就分出不同的库,就能避免锁库的问题。
  • 全局写队列。将所有的写放到一个消息队列里面,将多线程的写变成串行的写。
  • 全局写标识。所有的写操作开始前判断是否有可写标识,能写入就写入,否则接口返回,告诉前端数据库繁忙。

经过投票,大家一致决定用第三种方式实现,技术难度最小,代码侵入性最少。因为第三种方案是我提出来的,所以最终由我来完成。具体的过程可参见另一篇文档《peewee操作sqlite锁表问题分析》。

最终是解决了该问题,虽然不是优雅,但是在目前的时间成本和风险控制上局部是最优解了。后续将调研peewee这个ORM框架提供的sqliteQueueDatabase实现写队列。

摘录于peewee扩展插件playhouse:

SqliteQueueDatabase可作为常规SqliteDatabase。如果你想简单点 read and write 从访问sqlite数据库多线程.

SQLite在任何给定的时间只允许一个连接写入数据库。因此,如果您有一个多线程应用程序(例如Web服务器)需要写入数据库,当一个或多个尝试写入的线程无法获取锁时,您可能会偶尔看到错误。

SqliteQueueDatabase 旨在通过一个长期存在的连接发送所有写查询,从而简化操作。好处是,您可以看到多个线程在向数据库写入时没有冲突或超时。但是,缺点是您不能发出包含多个查询的写事务——本质上,所有写操作都在自动提交模式下运行。


4、个人感受

第一次带团队开发,才明白很多事情。

做项目的主人公

第一真正理解什么叫主人公意识。各种文章都说要对项目有主人公意识才能成长更快。我感觉只有站在这样一个位置上才能感受到这种意识。

项目进度的第一责任人就是你,项目中出现了大大小小的问题都是找你。领导会问题项目进度如何,有没有阻塞,能不能按期完成?队员会问这个校验框架是否ok?这个语法有没有问题?测试会找你说这个bug该给谁的?所以你必须对这个项目了如指掌,小到代码的一个配置项,大到工程进度的把控。开发过程中有任何问题都得及时顶上,组长就是一块砖,哪里需要哪里搬~

团队和谐

再说说团队的和谐。以前做一个小开发,只要完成自己的任务就可以了,团队的氛围影响我写代码的速度吗?带团队开发就不一样。团队中有各种特点的同事,有埋头苦干不汇报进度的、有能力强脾气差的、有脾气好进度慢的。总之各种性格的人都会存在。

本次开发中就遇到了一个能力强脾气差的,看到技术上小问题就直接群里开怼,谁不是热血小青年?第一次遇到这种情况可想而知。领导不得不为此找我们谈话一两次,甚至惊动了大部门领导。那段时间团队氛围特别差,没有人说话。我也不敢多说什么,害怕气氛更差,项目不能如期完成,到那个时候不是我的问题也变成我的问题了。所以只能选择忍一忍,尽量回避分歧。好在领导的谈话起到很大的作用,该安抚的安抚,该批评的批评,后来也没有发生语言的冲突,顺利按期完成项目。


5、总结

第一次带团队做项目对我来说是一次挑战和提高。从技术层面讲让我以后面对技术选型时能以更高的角度看待问题;从个人角度讲这是一次难得的机会让我负责开发团队,对接测试团队、前端团队、运维团队等。这对我的沟通交流都是一次锻炼。

最后,希望下一次做的更好,让所有组员都能有一些进步。

开发工具推荐

JNPF,很多人都用过它,它是功能的集大成者,任何信息化系统都可以基于它开发出来。

原理是将开发过程中某些重复出现的场景、流程,具象化成一个个组件、api、数据库接口,避免了重复造轮子。因而极大的提高了程序员的生产效率。

官网:www.jnpfsoft.com/?csdn,如果你有闲暇时间,可以做个知识拓展。

这是一个基于Java Boot/.Net Core构建的简单、跨平台快速开发框架。前后端封装了上千个常用类,方便扩展;集成了代码生成器,支持前后端业务代码生成,满足快速开发,提升工作效率;框架集成了表单、报表、图表、大屏等各种常用的Demo方便直接使用;后端框架支持Vue2、Vue3。

为了支撑更高技术要求的应用开发,从数据库建模、Web API构建到页面设计,与传统软件开发几乎没有差异,只是通过低代码可视化模式,减少了构建“增删改查”功能的重复劳动

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/130289.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

借助ChatGPT使用Pandas实现Excel数据汇总

一、问题的提出 现在有如下一个Excel表: 上述Excel表中8万多条数据,记录的都是三年以来花菜类的销量,现在要求按月汇总实现统计每个月花菜类的销量总和,如果使用Python的话要给出代码。 二、问题的解决 1.首先可以用透视表的方…

冒泡排序、选择排序、插入排序、希尔排序

冒泡排序 基本思想 代码实现 # 冒泡排序 def bubble_sort(arr):length len(arr) - 1for i in range(length):flag Truefor j in range(length - i):if arr[j] > arr[j 1]:temp arr[j]arr[j] arr[j 1]arr[j 1] tempflag Falseprint(f第{i 1}趟的排序结果为&#…

ElasticSearch入门

一、基本命令_cat 1、查看节点信息 http://192.168.101.132:9200/_cat/nodes2、查看健康状况 http://192.168.101.132:9200/_cat/health3、查看主节点的信息 http://192.168.101.132:9200/_cat/master4、查看所有索引 http://192.168.101.132:9200/_cat/indices二、索引一…

思科的简易配置

vlan 划分配置 1. 拓扑连接 2. 终端设备配置,vlan(v2, v3)配置,模式设置 然后设置交换机 fa 0/5 口为 trunk 模式,使得不同交换机同一 vlan 下 PC 可以互连 3.测试配置结果 用 ip 地址为 192.168.1.1 的主机(PC0)向同一 vlan(v2)下的 192.…

PN结解释

基本原理 PN结由P和N组成 硅掺杂硼,缺少电子,显正电,就是P(Positive) 硅掺杂磷,多出电子,显负电,就是N(Negative) 将P和N拼接 左边代表游离的电子&#xf…

想要精通算法和SQL的成长之路 - 课程表II

想要精通算法和SQL的成长之路 - 课程表 前言一. 课程表II (拓扑排序)1.1 拓扑排序1.2 题解 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 课程表II (拓扑排序) 原题链接 1.1 拓扑排序 核心知识: 拓扑排序是专…

AI是风口还是泡沫?

KlipC报道:狂热的人工智能追捧潮有所冷静,投资者在“上头”的追涨之后,开始回归到对基本面的关注。 KlipC的合伙人Andi D表示:“近日,有关英伟达二季度“破纪录”财报涉嫌造假的话题正在社交媒体和投资者论坛中甚嚣尘上…

XShell7 + Xftp7 + IDEA 打包MapReduce程序到集群运行

参考博客 【MapReduce打包成jar上传到集群运行】http://t.csdn.cn/2gK1d 【Xshell7/Xftp7 解决强制更新问题】http://t.csdn.cn/rxiBG IDEA打包MapReduce程序 这里的打包是打包整个项目,后期等学会怎么打包单个指定的mapreduce程序再来更新博客。 1、编译打包 …

vscode 画流程图

文章目录 1、安装插件 draw2、新建文件3、开始画图4、另存为图片 vscode可以画流程图了,只需要安装插件就可以了。 1、安装插件 draw 2、新建文件 3、开始画图 4、另存为图片

Linux编辑器vim

目录 一、vim的几种模式 1、命令模式 2、编辑/插入模式 3、底行模式 ①增加行号 ②分屏操作 ③不退出vim执行命令 4、替换模式 二、vim的常见命令 1、yy命令 2、p命令 3、dd命令 4、u命令 5、Ctrl r命令 6、shirtg命令 7、gg命令 8、shirt6命令 9、shirt4命…

(其他) 剑指 Offer 61. 扑克牌中的顺子 ——【Leetcode每日一题】

❓剑指 Offer 61. 扑克牌中的顺子 难度:简单 从若干副扑克牌中随机抽 5 张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大…

Qt应用开发(基础篇)——组合框容器 QGroupBox

一、前言 QGroupBox继承于QWidget,是一个带有标题的组合框架容器控件。 QGroupBox组合框容器自带一个顶部标题,一个面板。面板内部展示各种各样的部件,标题用来解释这些部件为什么集合在一起,并且支持键盘快捷方式切换部件焦点。比…

Android逆向——脱壳解析

“壳”是一种对程序进行加密的程序,“壳”形象地表现了这个功能。我们可以把被加壳的程序当成食物,而加壳程序就是在外面加上一层坚硬的外壳,防止别人去窃取其中的程序。加壳后的程序依然可以被直接运行。在程序运行时壳的代码先运行&#xf…

【C++】怎么接受未知数量的参数?

2023年9月8日,周五下午 目录 第一种方式:可变参数函数(Variadic Function)头文件使用方法详解va_start宏详解va_arg宏示例程序 第一种方式:可变参数函数(Variadic Function) 可变参数函数(Variadic Function)是一种可以接受不定数量参数的函…

静态代理和动态代理笔记

总体分为: 1.静态代理: 代理类和被代理类需要实现同一个接口.在代理类中初始化被代理类对象.在代理类的方法中调 用被代理类的方法.可以选择性的在该方法执行前后增加功能或者控制访问 2.动态代理: 在程序执行过程中,实用JDK的反射机制,创建代理对象,并动态的指定要…

STM32-HAL库07-软件SPI驱动0.96寸OLED

STM32-HAL库07-软件SPI驱动0.96寸OLED 一、所用材料: STM32VGT6自制控制板 STM32CUBEMX(HAL库软件) MDK5 二、所学内容: 通过HAL库配置四个GPIO输出口,对其进行软件模拟SPI发送规则,进而驱动OLED进行数…

C#__文件操作之FileInfo和DirectoryInfo

// 代码(含注释) class Program{static void Main(string[] args){// FileInfo 文件操作FileInfo myFile new FileInfo("D:\C#编程\文件操作之FileInfo和DirectoryInfo\TextFile1.txt");// 实例方法// myFile.CopyTo("D:\C#编程\文件操作…

企业电子招标采购系统源码Spring Boot + Mybatis + Redis + Layui + 前后端分离 构建企业电子招采平台之立项流程图

功能模块: 待办消息,招标公告,中标公告,信息发布 描述: 全过程数字化采购管理,打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力,为外部供…

OpenCV(三十六):霍夫直线检测

1.检测直线的霍夫变换原理 2.检测直线函数HoughLines() 检测直线流程: Step1:将参数空间的坐标轴离散化。 Step2:将图像中每个非0像素通过映射关系求取在参数空间通过的方格 Step3:统计参数空间内每个方格出现的次数,选取次数大于某一值的方格作为表示直线的方格…

Prompt Tuning训练过程

目录 0. 入门 0.1. NLP发展的四个阶段: Prompt工程如此强大,我们还需要模型训练吗? - 知乎 Prompt learning系列之prompt engineering(二) 离散型prompt自动构建 Prompt learning系列之训练策略篇 - 知乎 ptuning v2 的 chatglm垂直领域训练记…