一个兼职导师,学生,项目甲方的接单适配平台项目的完结总结

这是一个以甲方发布业务需求项目,由后台管理员审核报名导师,然后由导师审核报名学生的,然后按照需求进行开发并在截止日期前交付的平台。
还兼有内推招聘搜索功能,学生导师作品集,项目评论区功能等。
使用到了较为完整的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;


    @Bean
    public 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: 8081

spring:
  application:
    name: job-server

logging:
  config: classpath:logback.xml

xxl:
  job:
    accessToken:
    admin:
      addresses: localhost:8080/xxl-job-admin
    executor:
      appname: job-server
#我就不在这里写ip地址和端口号了      
      ip: 
      port: 9999
      logpath: /data/applog/xxl-job/jobhandler
      logretentiondays: -1
      address: 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;
    //访问的key
    String accessKey;
    //访问秘钥
    String secretKey;
}

配置类

@Configuration
public class MinioConfig {
    @Autowired
    private Minio minio;

    @Bean
    public MinioClient minioClient () throws InvalidPortException, InvalidEndpointException {
        return new MinioClient(minio.getEndpoint(),minio.getAccessKey(),minio.getSecretKey());
    }
}

配置文件

minio:
  endpoint: http://localhost:端口号 #MinIO服务所在地址,我这里就不写ip和端口号了
  bucketName: images #存储桶名称
  accessKey: admin #访问的key
  secretKey: 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。
在这里插入图片描述

暂时想要归纳的就这些,花了不少时间,但是确实学到不少东西,甚至有点喜欢上了代码批斗环节。开会批斗完,下去改一波代码,瞬间觉得不止代码升级了,我也升级了。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值