本文主要是介绍一个兼职导师,学生,项目甲方的接单适配平台项目的完结总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
这是一个以甲方发布业务需求项目,由后台管理员审核报名导师,然后由导师审核报名学生的,然后按照需求进行开发并在截止日期前交付的平台。
还兼有内推招聘搜索功能,学生导师作品集,项目评论区功能等。
使用到了较为完整的springColud分布式架构。使用到的微服务组件有:nacos,job,knife4j-gateway,search,mbg-plus,monitor等。
● 技术选型包括但不限于:
JDK 1.8,mysql, redis, mongdb, Elasticsearch, logstash, kibana, nginx, RabbitMq;
springCloud, mybatis-plus, minio, seata, portainer, jenkins, kubemetes,docker;
vue,vue-router,vuex,axios,element, v-charts;
● 人员分组分为架构组和业务组,业务组分为三组。架构和业务我都有参与,普通组实际编写代码的人约为五人。
我既参与了技术架构代码编写也参与了业务代码编写,就做个学习总结。
分为两个部分:
一个是日常习惯,或者说常识,或者说内功心法的总结。
一个是技术实现,或者说中间件,或者说武功招式的总结。
本次学习中,我被纠正的一些很重要的点有:
● 不要再dao层进行多表联查,首先是容易形成屎山代码,更重要的是,你一个查询就占有多个表锁,这就太霸道了些,显然不利大流量的查表性能,更不利于多数据源查表性能。
查表多多少少是要查多表的,但是可以扔到server层调用着来查。
● 业务需求的分析写的好,基本业务代码不涉及技术的,就都不用发愁了。
● 不止代码编写的时候要注意阿里公约的规范,数据库建表的时候也应该注意。
● 代码无论是前后端都应该该验空,验证数据可用否,都应该设置异常处理的处理方法,哪怕是抛出,也要处理。用比较通俗的话来讲就是,前端验证是防用户瞎输入,后端验证是为了防止错误的数据占用户,一来防前端bug,而来防恶意攻击。
● 验空这种比较简单的验证功能,尽可能使用hutool-all依赖包里的,比如StriUtil,ObjectUtil,ArrayUtil里的各种验空工具来验。
首要的,当然是去除重复代码的编写,以及消除常数类代码的编写。
但重要的是,这些Util里面会有类似isNotBlank这种防空异常,除去空格的个性化验空功能。大大提升了代码的复用性的同时简化了代码的冗余。
● 通过多组合作,我更深刻的理解了多分支下,通过gitee管理项目,PR分支到master中去的过程。
● 使用ApiFox这个软件,共同管理接口,这样你需要什么接口,别人需要什么接口,都能清楚很多,前后端返回参数也能更好协调,组员分工追责也能更清楚。
● 上传代码之前,好好检查代码能不能运行。我自从下载了别人的代码一直异常,错都不知道错在哪,也走不了测试,只能等对方修改,之后我就对不测试便上传代码的行为深恶痛绝。
技术功能要点归纳:
● job-server是一个定时的代码执行器,我能想到的各类应用场景有,比如股票的定时刷新,不想要在前端写后端代码的,可以通过这个实现。还有就是打印日志功能,可以通过admin服务去可视化客户端化的在网页部署各种job的执行器。
最后我实现使用的是2.3.0版本的,期间我发现如果admin和executor版本号不同的话,注解是无效的,也就是说高版本的没有低版本里的注解,也就是不能向下兼容,2.1都兼不了。说实话有点坑。
2.3.0版本在完成初始的admin和executor里的XxlJobConfig的编写后,就只需考虑yml文件和执行器的业务代码编写了。代码写完了在方法上写个@XxlJob就可以解决了,相当的方便。老版本还要在类上面写东西,以至于我的记忆已经淘汰了它。(实际上就是忘了,哈哈)
需要记录一下的是XxlJobConfig的配置类和yml文件格式
@Configuration
public class XxlJobConfig {private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);@Value("${xxl.job.admin.addresses}")private String adminAddresses;@Value("${xxl.job.executor.appname}")private String appName;@Value("${xxl.job.executor.ip}")private String ip;@Value("${xxl.job.executor.port}")private int port;@Value("${xxl.job.accessToken}")private String accessToken;@Value("${xxl.job.executor.logpath}")private String logPath;@Value("${xxl.job.executor.logretentiondays}")private int logRetentionDays;@Beanpublic XxlJobSpringExecutor xxlJobExecutor() {logger.info(">>>>>>>>>>> xxl-job config init.");XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();xxlJobSpringExecutor.setAdminAddresses(adminAddresses);xxlJobSpringExecutor.setAppname(appName);xxlJobSpringExecutor.setIp(ip);xxlJobSpringExecutor.setPort(port);xxlJobSpringExecutor.setAccessToken(accessToken);xxlJobSpringExecutor.setLogPath(logPath);xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);return xxlJobSpringExecutor;}
}
server:port: 8081spring:application:name: job-serverlogging:config: classpath:logback.xmlxxl:job:accessToken:admin:addresses: localhost:8080/xxl-job-adminexecutor:appname: job-server
#我就不在这里写ip地址和端口号了 ip: port: 9999logpath: /data/applog/xxl-job/jobhandlerlogretentiondays: -1address: localhost:8081/
●minio是一个对象式存储上传文件的中间件,功能和代码编写两个方面我觉得都比fastdfs好,看来我很快也会遗忘fastdfs。
实现起来还是在关系数据库内存文件地址,然后到中间件的数据存储里找这个地址下的文件。但minio在分布式部署上采用了纠错码和集群的方法,保证了数据的高可用和一致性,同时由于有了可视化的操作终端,检查管理起来也更方便。
实现的时候我使用的是7.0.2的版本,没有使用8.0。首先就是8.0由于分离了调度中心和功能本体,导致linux里部署要部两个端口,然后是默认的用户名和密码的名称export的是 MINIO_ROOT_USER和MINIO_ROOT_PASSWORD。而不是accessKey和secretKey,需要注意。
在代码编写方面,7.0.2的编写方法也比较简短,只需要注入配置文件内容后,在工具类中写代码就好了,写的过程中也是以调用方法的形式居多。而8.0则是要先创建实体类之后才能进行后续方法的方法调用(至少在写法上,我感觉是多次一举)
性能上我没感觉出差距,所以个人感觉选择7.0.2比较好。
在此记录一下7.0.2的配置写法:
实体类
@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class Minio {//minio的地址String endpoint;//访问桶的名称String buketName;//访问的keyString accessKey;//访问秘钥String secretKey;
}
配置类
@Configuration
public class MinioConfig {@Autowiredprivate Minio minio;@Beanpublic MinioClient minioClient () throws InvalidPortException, InvalidEndpointException {return new MinioClient(minio.getEndpoint(),minio.getAccessKey(),minio.getSecretKey());}
}
配置文件
minio:endpoint: http://localhost:端口号 #MinIO服务所在地址,我这里就不写ip和端口号了bucketName: images #存储桶名称accessKey: admin #访问的keysecretKey: admin123456 #访问的秘钥
#默认图片url,没有图片时使用此图片地址
defaultImageUrl: http://localhost:9000/images/defaultImage.jpg
●Logstash + Elasticsearch + Kibana
其实就是管理日志的,Logstash 收集日志,Elasticsearch做数据处理查询,Kibana辅助可视化管理
Elasticsearch 使用了倒排索引查找关键字,可以理解为是查value,而不是查key的关系型数据库,整体结构和mysql相差不大(Type这层要是淘汰了差别就大一点点)。
在springboot的框架下,使用springdata里的工具类@Repository标注Dao类,然后像用mysql时那样,创建一个要有对应数据的注解的ES实体类,之后照常写server和controller,实现起来的效果和mybatis那套差不多。
(我已经把他的基础语句忘的差不多了,经典内存筛选后永久化到磁盘后清理缓存。这波啊,这波是人脑追求实用高效。)
●redis缓存里,我学到了很多新东西,比如:
●布隆过滤器:
通过x个hash算法(crc32,crc16)把要处理的数据进行算法计算后,变成多个,放到长度为Y的数组中的不同点位去。
然后通过同样的多套算法在查找数据的时候,通过算法把要查的值算出成多个不同的hash值,然后去查这些值在数组中的点位是1还是0,如果有一个不为1,即有一个为0,则这个数据就一定不存在,就不需要在查数据库了。如果所有计算后的值的位点都是1,则可能存在,再去查数据库里到底存不存在这个值。
上图比较好理解,在此记录一下:
●setbit实现点赞功能(bitmaps):
这是一个很巧的方法,但是实现起来的要求条件也比较苛刻,想实现微信朋友圈这种点赞功能就不太好实现了,但是只是单纯的统计数量,用户Id又比较简单的点赞功能,这种方法性能确实不错。(毕竟是内存容嘛,不寒碜,不寒碜)
原理就是利用存储时数据是二进制的10101这种东西,然后根据位数去设置是或否。比如id为1和为3的用户点赞了,id为2和4的用户没点赞,bit位的数据就是0101,因为是动态扩容的,所以所占空间极小。最多存到42亿个不同用户点赞,也才占512MB。
暂时想要归纳的就这些,花了不少时间,但是确实学到不少东西,甚至有点喜欢上了代码批斗环节。开会批斗完,下去改一波代码,瞬间觉得不止代码升级了,我也升级了。
这篇关于一个兼职导师,学生,项目甲方的接单适配平台项目的完结总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!