当前位置:   article > 正文

仿牛客论坛项目全面大总结_牛客项目亮点

牛客项目亮点
1.核心功能:

 

     - 发帖、评论、私信、转发;
     - 点赞、关注、通知、搜索;
     - 权限、统计、调度、监控;
2.核心技术:
     - Spring Boot、SSM
     - Redis、Kafka、ElasticSearch
     - Spring Security、Quatz、Caffeine
3.项目亮点:
     - 项目构建在Spring Boot+SSM框架之上,并统一的进行了状态管理、事务管理、异常处理;
     - 利用Redis实现了点赞和关注功能;
     - 利用Kafka实现了异步的站内通知;
     - 利用ElasticSearch实现了全文搜索功能,可准确匹配搜索结果,并高亮显示关键词;
     - 利用Caffeine+Redis实现了两级缓存,并优化了热门帖子的访问。
     - 利用Spring Security实现了权限控制,实现了多重角色、URL级别的权限管理;
     - 利用HyperLogLog、Bitmap分别实现了UV、DAU的统计功能,100万用户数据只需*M内存空间;
     - 利用Quartz实现了任务调度功能,并实现了定时计算帖子分数、定时清理垃圾文件等功能;
     - 利用Actuator对应用的Bean、缓存、日志、路径等多个维度进行了监控,并通过自定义的端点对数据库连接进行了监控。
实现了项目部署上线,日访问量到达200+(很欣慰了)

 开始总结

图中的下方三行是基石。
原图中带下划线的和带@的内容是重点内容。
算法:前缀树过滤敏感词。
数据结构:Redis的数据结构。Redis有许多种数据结构,每种数据结构适合解决什么样的问题,适合缓存什么样的数据。
Kafka:重点是生产者与消费者模式,只有你理解了,才能明白什么时候用哪些功能来解决什么问题。
ElasticSearch:重点是它的数据结构,以索引(表)方式来存。建议找文章自己学习ES的索引。
Caffeine:本地缓存,有一定局限性,把它和Redis一起回顾,因为它们都是缓存。
从运维角度来讲整个项目(就是分布式部署)
静态资源(图片)和动态资源(controller)是部署在两个服务器上的。比如:牛客网的是在域名 nowcoder.com 上,牛客网的图片是在 static.nowcoder.com 上,这两个是不同的域名,会对应到两个不同的服务器。
客户端找nginx请求动态资源,找CDN请求静态资源。
nginx:能对服务器做反向代理,如果你有多个服务器,它能对服务器做负载均衡。nginx会主从备份,即有两台服务器,一台处理客户端请求,一台只是备份。
CDN:把你的资源部署到各地的多个服务器上,用户访问网站时,会从最近的服务器加载资源。
有多台服务器,nginx会把客户端请求发送到某一台服务器,每台服务器中都有项目community和本地缓存。
数据库通常要做读写分离的,一台数据库复制读,一台数据库负责写。负责写的数据库在写入数据以后,会把数据同步到负责读取的数据库里。
为什么Redis、Kafka、ElasticSearch都是部署多个,但是数据库却只进行主从备份?因为数据库部署和它们一样做集群式部署的话的话,那么就要处理分布式事务,这个比较麻烦,所以我们一般尽量避免这种情况。而且,一般的业务也达不到要部署多个数据库,因为在访问数据库前,会先访问本地缓存,再访问Redis,最后都没有才访问数据库。
我们用的文件服务器是七牛云。

咋们就从核心功能处开始捋,一个一个功能点开始总结实现过程:

核心功能:

   发帖:

      点击发布帖子按钮,输入帖子标题内容等信息后发布,以JS异步请求的方式进行提交,首先判断该线程中有无用户信息(在登录成功是会将用户信息与本线程的id进行键值对存储,保证了多线程情况下安全)即判断有无登录,已登录则初始化帖子信息将其添加至DB中,并且触发发帖事件,采用kafka信息队列来完成,将帖子信息添加至ES中,通知再将其存入Redis中计算帖子的分值,用来在最热列表中展示出来:

添加帖子

  1. // 发布帖子
  2. @RequestMapping(path = "/add",method = RequestMethod.POST)
  3. @ResponseBody
  4. public String addDiscussPost(String title,String content){
  5. User users = hostHolder.getUsers();
  6. if(users == null){
  7. return CommunityUtil.getJSONString(403,"你还没有登录!");
  8. }
  9. DiscussPost post=new DiscussPost();
  10. post.setUserId(users.getId());
  11. post.setTitle(title);
  12. post.setContent(content);
  13. post.setCreateTime(new Date());
  14. discussPostService.addDiscussPost(post);
  15. // 触发发帖事件 添加至es中
  16. Event event = new Event()
  17. .setTopic(TOPIC_PUBLISH)
  18. .setUserId(users.getId())
  19. .setEntityType(ENTITY_TYPE_POST)
  20. .setEntityId(post.getId());
  21. eventProducer.fireEvent(event);
  22. // 计算帖子分数
  23. String redisKey= RediskeyUtil.getPostScoreKey();
  24. redisTemplate.opsForSet().add(redisKey,post.getId());
  25. return CommunityUtil.getJSONString(0,"发布成功!");
  26. }
kafak消费者身份,ES同样添加数据
  1. // 消费 发帖事件 es添加数据
  2. @KafkaListener(topics = {TOPIC_PUBLISH})
  3. public void handlePublishMessage(ConsumerRecord record){
  4. if(record == null && record.value() == null){
  5. logger.error("消息的内容为空!");
  6. return;
  7. }
  8. Event event = JSONObject.parseObject(record.value().toString(), Event.class);
  9. if(event == null){
  10. logger.error("消息格式错误!");
  11. return;
  12. }
  13. DiscussPost discussPost =
  14. discussPostService.selectDiscussPostById(event.getEntityId());
  15. elasticsearchService.saveDiscussPost(discussPost);
  16. }

评论:

  评论这一块

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/774646
推荐阅读
相关标签
  

闽ICP备14008679号