2024/9/21黑马头条跟学笔记(十)

1)今日内容

1.1)定时计算流程

image-20240919224118456

1.不想用户看到的全是最新的,实时计算最火的推送

2.定时计算热度最高,存redis,推送到推荐页面

1.2)使用schedule

image-20240919224329724

多个服务部署,多次执行

硬编码定时时间在cron

任务失败无统计

任务量过大不能分片执行

1.3)xxljob

image-20240919224421736

1.4)目录

image-20240919224512710

  • 概述
  • 案例,linux部署环境
  • 参数修改
  • 定时计算,根据三连+关注计算
  • 接口改,先redis热点,上下拉分页后再数据库查数据

2)xxljob概述

image-20240919224846135

同个项目同个代码,部署多个实例,运行,定时发放优惠券任务重复

image-20240919225057791

美团员工开发

开箱即用

3)环境搭建

3.1)版本

image-20240919225808564

版本调一致

3.2)源码注释

image-20240919225932497

3.3)搭建调度中心步骤

web后台部署本地springboot

image-20240919230032245

image-20240919230223955 image-20240919230319463

启动!

image-20240919230402405

任务调度中心

用户名admin

密码123456

image-20240919230459355

docker部署

image-20240919230625903

1.mysql镜像拉取

docker pull mysql:5.7

2.运行sql容器 密码我习惯123456了,手改一下

docker run -p 3306:3306 --name mysql57 \
-v /opt/mysql/conf:/etc/mysql \
-v /opt/mysql/logs:/var/log/mysql \
-v /opt/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-d mysql:5.7

3.xxl-job拉取镜像

docker pull xuxueli/xxl-job-admin:2.3.0

4.创建容器

自己改mysql地址,username 和pwd

docker run -e PARAMS="--spring.datasource.url=jdbc:mysql://192.168.233.136:3306/xxl_job?Unicode=true&characterEncoding=UTF-8 \
--spring.datasource.username=root \
--spring.datasource.password=123456" \
-p 8888:8080 -v /tmp:/data/applogs \
--name xxl-job-admin --restart=always  -d xuxueli/xxl-job-admin:2.3.0

5.访问

任务调度中心

4)入门案例

4.1)概述

image-20240919232333481

  • 类型
  • 时间
  • 调度类为bean类型

image-20240919232422486

image-20240919232449633

4.2)步骤

①)创建模块,导入依赖

每逢新技术,必在test搞一个新的入门案例一下

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--xxl-job--><dependency><groupId>com.xuxueli</groupId><artifactId>xxl-job-core</artifactId><version>2.3.0</version></dependency>
</dependencies>

②)配置文件yml

server:port: 8881xxl:job:admin:addresses: http://192.168.233.136:8888/xxl-job-adminexecutor:appname: xxl-job-executor-sampleport: 9999

③)配置类

package com.heima.xxljob.config;import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** xxl-job config** @author xuxueli 2017-04-28*/
@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.port}")private int port;@Beanpublic XxlJobSpringExecutor xxlJobExecutor() {logger.info(">>>>>>>>>>> xxl-job config init.");XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();xxlJobSpringExecutor.setAdminAddresses(adminAddresses);xxlJobSpringExecutor.setAppname(appname);xxlJobSpringExecutor.setPort(port);return xxlJobSpringExecutor;}}

addresses 地址, appname 执行器名字, 执行器监听端口后,用来与xxl-admin通信且访问执行其相关接口

④)hello job

package com.heima.xxljob.job;import com.xxl.job.core.handler.annotation.XxlJob;
import org.springframework.stereotype.Component;@Component
public class HelloJob {@XxlJob("demoJobHandler")public void helloJob(){System.out.println("简单任务执行了。。。。");}
}

@xxljob注解后面跟着执行器的名字

⑤)启动引导类,启动任务

image-20240920201807324

image-20240920202044424

4.3)执行器详解

image-20240920202411221

执行器,针对不同任务进行了一个分组

image-20240920202708467

路由策略,感觉和负载均衡差不多

image-20240920202858649

配置

  • 负责人
  • 邮件

4.4)任务详解

image-20240920203011256

4.5)路由策略

image-20240920203044828

5)路由策略(轮询案例)

image-20240920203901591

复制修改端口后启动

image-20240920205212035

6)路由策略(分片广播)

6.1)概述

image-20240920205411322

场景:支付宝,还款提醒

方法,任务项id取模 派发到哪个分片对应的实例上

6.2)新建执行器

image-20240920205751311

6.3)新建任务

image-20240920210353297

6.4)修改配置文件

image-20240920210457118

xxl-job-sharding-executor

6.5)新增方法

@XxlJob("shardingJobHandler")
public void shardingJob() {//分片的参数int shardIndex = XxlJobHelper.getShardIndex();int shardTotal = XxlJobHelper.getShardTotal();List<Integer> integers = genList();for (int i = 0; i < 1000; i++) {if (i%shardTotal==shardIndex){System.out.println("分片"+shardIndex+"执行了"+i);}}
}List<Integer> genList() {List<Integer> integers = new ArrayList<>();for (int i = 0; i < 1000; i++) {integers.add(i);}return integers;
}
image-20240920213831960

对某个值 取模运算,可以得到 小于某个值的所有数,(类似求0~X的随机值)

因此我们可以确定好每一轮应该分配给哪几个分片

假设现在有两个分片 总数为2

任务0%2==0 那就让分片0去执行

任务1%2==1 那就让分片1去执行

任务2%2==0 那就让分片0去执行(新的一轮)

对这个方法起个名字好记一点 叫均分法吧,就是能让所有人均匀的分配所有任务

确定任务分给哪个分片公式为 当前任务索引%总数===当前分片

由于当前分片不可能大于总分片数,因此当前分片无论%总数都等于自己,

结论

总任务取模与总人数,能将所有任务均分给每一个人

  • (任务索引)对比自己大(总人数)的取模,都为(任务索引)本身

相当于每个任务索引向总人数拿了把铲子给自己挖了个1米的坑,将自己的劳动(分片)埋进去

  • 对比自己小的,说明新的一轮了,取模值又重新递增,再往下挖深了1米,直到所有任务结束(坑挖到底了)

取模运算所得值==均匀分配

7)热度计算

7.1)概述

点赞收藏评论阅读数量计算

image-20240920214148563

7.2)需求分析

image-20240920214503269

范围,近五天

分值权重分配

每个频道(省赛)选出前三十的高手 放频道redis里

所有频道(国赛)选出前三十的高手 放推荐redis里

凌晨2点定时计算

7.3)代码

思路

1.查所有

2.根据所有计算分值,成新列表

3.远程拿所有频道(接口+Impl),循环频道,article符合频道id则分为一组

4.分组后在从组里挑前30条,存redis

mapper

/*** 找近5天的文章*/List<ApArticle> findArticleListByLast5Days(@Param("dayParam") Date dayParam);

mapperXML

 <select id="findArticleListByLast5Days" resultType="com.heima.model.article.pojos.ApArticle">select * from `ap_article` aaLEFT JOIN ap_article_config aac ON aa.id=aac.article_id<where>and aac.is_delete!=1and aac.is_down!=1<if test="dayParam!=null">and aa.publish_time <![CDATA[>=]]> #{dayParam}</if></where></select>

思路

//1.查五天前文章//2.计算文章的分支//3.每个频道缓存30条牛逼文章

service

public interface HotArticleService {/*** 计算热点文章*/void computedHotArticle();
}

impl

@Service
@Slf4j
public class HotArticleServiceImpl implements HotArticleService {@Autowiredprivate ApArticleMapper apArticleMapper;@Autowiredprivate IWemediaClient wemediaClient;/*** 计算热点文章*/@Overridepublic void computedHotArticle() {// 1.查五天前文章Date date = DateTime.now().minusDays(1935).toDate();List<ApArticle> articleListByLast5Days = apArticleMapper.findArticleListByLast5Days(date);List<HotArticleVo> hotArticleVoList = computeScoredArticle(articleListByLast5Days);// 3.每个频道缓存30条牛逼文章cache30Redis(hotArticleVoList);}private void cache30Redis(List<HotArticleVo> hotArticleVoList) {// 3.远程拿所有频道,循环频道,article符合频道id则分为一组ResponseResult result = wemediaClient.getChannels();if (result.getCode().equals(200)) {String jsonString = JSON.toJSONString(result.getData());List<WmChannel> wmChannels = JSON.parseArray(jsonString, WmChannel.class);for (WmChannel wmChannel : wmChannels) {List<HotArticleVo> collectGroupByChannelId = hotArticleVoList.stream().filter(x -> x.getChannelId().equals(wmChannel.getId())).collect(Collectors.toList());// 4.分组后在从组里挑前30条,存redissortAndCache(collectGroupByChannelId, ArticleConstants.HOT_ARTICLE_FIRST_PAGE + wmChannel.getId());}}//6.最后是推荐页面也就是最牛逼的也就是国赛的前30sortAndCache(hotArticleVoList,ArticleConstants.HOT_ARTICLE_FIRST_PAGE+ArticleConstants.DEFAULT_TAG);}@Autowiredprivate CacheService cacheServicel;private void sortAndCache(List<HotArticleVo> collectGroupByChannelId, String key) {collectGroupByChannelId = collectGroupByChannelId.stream().sorted(Comparator.comparing(HotArticleVo::getScore).reversed()).collect(Collectors.toList());// 5. 如果大于30条,保留前30,设置缓存if (collectGroupByChannelId.size() > 30) {collectGroupByChannelId.subList(0, 30);}cacheServicel.set(key, JSON.toJSONString(collectGroupByChannelId));}private List<HotArticleVo> computeScoredArticle(List<ApArticle> articleListByLast5Days) {List<HotArticleVo> hotArticleVos = new ArrayList<>();if (articleListByLast5Days != null) {for (ApArticle articleListByLast5Day : articleListByLast5Days) {// 2.计算文章的分值Integer score = computedGoal(articleListByLast5Day);HotArticleVo hotArticleVo = new HotArticleVo();BeanUtils.copyProperties(articleListByLast5Day,hotArticleVo);hotArticleVo.setScore(score);hotArticleVos.add(hotArticleVo);}}return hotArticleVos;}private Integer computedGoal(ApArticle apArticle) {Integer score = 0;if(apArticle.getLikes() != null){score += apArticle.getLikes() * ArticleConstants.HOT_ARTICLE_LIKE_WEIGHT;}if(apArticle.getViews() != null){score += apArticle.getViews();}if(apArticle.getComment() != null){score += apArticle.getComment() * ArticleConstants.HOT_ARTICLE_COMMENT_WEIGHT;}if(apArticle.getCollection() != null){score += apArticle.getCollection() * ArticleConstants.HOT_ARTICLE_COLLECTION_WEIGHT;}return score;}
}

7.4)定时任务

执行器

image-20240921092620847

任务

依赖

article服务新增

<!--xxl-job-->
<dependency><groupId>com.xuxueli</groupId><artifactId>xxl-job-core</artifactId><version>2.3.0</version>
</dependency>
配置类
package com.heima.article.config;import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** xxl-job config** @author xuxueli 2017-04-28*/
@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.port}")private int port;@Beanpublic XxlJobSpringExecutor xxlJobExecutor() {logger.info(">>>>>>>>>>> xxl-job config init.");XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();xxlJobSpringExecutor.setAdminAddresses(adminAddresses);xxlJobSpringExecutor.setAppname(appname);xxlJobSpringExecutor.setPort(port);return xxlJobSpringExecutor;}}
配置文件(nacos)
xxl:job:admin:addresses: http://192.168.233.136:8888/xxl-job-adminexecutor:appname: xxl-job-hotArticle-exectuorport: 9999
任务类
package com.heima.article.job;import com.heima.article.service.HotArticleService;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
@Slf4j
public class ComputeHotArticleJob {@Autowiredprivate HotArticleService hotArticleService;@XxlJob("computeHotArticleJob")public void handle(){log.info("热文章分值计算调度任务开始执行...");hotArticleService.computeHotArticle();log.info("热文章分值计算调度任务结束...");}
}

image-20240921093618795

image-20240921094128017

8)查询接口改造

8.1)思路

1.每个频道第一次进入,默认redis前30,后续下滑刷新更多,就从数据库里找(好家伙这不会重复吗)

2.写一个loadHotOrMore 根据

8.2)代码

再ApArticleService里

service
  /*** 加载文章列表* @param dto* @param type      1 加载更多   2 加载最新* @return*/ResponseResult loadFirstPage(ArticleHomeDto dto, Short type);
impl
/*** 加载文章列表** @param dto* @param type 1 加载更多   2 加载最新* @return*/@Overridepublic ResponseResult loadFirstPage(ArticleHomeDto dto, Short type) {// 1.从redis里查出来对应频道的首页30条String jsonString = cacheService.get(ArticleConstants.HOT_ARTICLE_FIRST_PAGE + dto.getTag());List<HotArticleVo> hotArticleVoList = JSON.parseArray(jsonString, HotArticleVo.class);return ResponseResult.okResult(hotArticleVoList);}
controller
 /*** 加载首页* @param dto* @return*/@PostMapping("/load")public ResponseResult load(@RequestBody ArticleHomeDto dto) {// return apArticleService.load(dto, ArticleConstants.LOADTYPE_LOAD_MORE);return apArticleService.loadFirstPage(dto, ArticleConstants.LOADTYPE_LOAD_MORE);}

image-20240921101121062

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

群晖使用Docker部署WPS Office并实现异地使用浏览器制作办公文档

文章目录 前言1. 本地环境配置2. 制作本地分享链接3. 制作公网访问链接4. 公网ip地址访问您的分享相册5. 制作固定公网访问链接 前言 想象一下这个场景&#xff1a;如果遇到周末紧急需要改方案&#xff0c;但团队成员都在各自家中&#xff0c;这个时候如果大家能够轻松访问这个…

海洋大地测量基准与水下导航系列之二国外海底大地测量基准和海底观测网络发展现状(上)

海底大地控制网建设构想最先由美国斯克里普斯海洋研究所(Scripps Institution of Oceanography,SIO)提出&#xff0c;目前仅有少数发达国家具备相应技术条件。美国、日本、俄罗斯和欧盟等发达国家通过布测先进的海底大地控制网&#xff0c;不断完善海洋大地测量基准基础设施&am…

SpringCloud Alibaba五大组件之——Sentinel

SpringCloud Alibaba五大组件之——Sentinel&#xff08;文末附有完整项目GitHub链接&#xff09; 前言一、什么是Sentinel二、Sentinel控制台1.下载jar包2.自己打包3.启动控制台4.浏览器访问 三、项目中引入Sentinel1.在api-service模块的pom文件引入依赖&#xff1a;2.applic…

一堆让你眼界大开的实用工具网站——搜嗖工具箱

和图书 https://www.hetushu.com/ 一个好用的免费看小说网站。和图书是一个提供各种热门电子书,书籍,小说免费在线阅读的网站&#xff0c;涵盖网游、玄幻、穿越、科幻、仙侠、都市、武侠、历史、竞技、军事灵异等多个种类的小说。在这个网站看小说最大的感触简单干净&#xff…

C++速通LeetCode中等第15题-搜索二维矩阵II(两种方法)

方法一&#xff1a;二分法按行遍历查找&#xff1a; class Solution { public:bool searchMatrix(vector<vector<int>>& matrix, int target) {for (const auto& row: matrix) {auto it lower_bound(row.begin(), row.end(), target);if (it ! row.end()…

【C++掌中宝】在正式学习C++之前,你还应该了解哪些东西?

文章目录 前言1. C发展历史1.1 C版本更新1.2 关于C23的一个小故事 2. C参考文档3. C的重要性3.1 编程语言排行榜3.2 C在工作领域中的应用 4. C学习建议和书籍推荐4.1 C学习难度4.2 C学习建议4.3 学习书籍推荐 5. C第一个程序结语 前言 在正式学习C之前&#xff0c;我觉得应该先…

Linux:make,Makefile

hello&#xff0c;各位小伙伴&#xff0c;本篇文章跟大家一起学习《Linux&#xff1a;make&#xff0c;Makefile》&#xff0c;感谢大家对我上一篇的支持&#xff0c;如有什么问题&#xff0c;还请多多指教 &#xff01; 如果本篇文章对你有帮助&#xff0c;还请各位点点赞&…

Java面试篇-AOP专题(什么是AOP、AOP的几个核心概念、AOP的常用场景、使用AOP记录操作日志、Spring中的事务是如何实现的)

文章目录 1. 什么是AOP2. AOP的几个核心概念3. AOP的常用场景4. 使用AOP记录操作日志4.1 准备工作4.1.1 引入Maven依赖4.1.2 UserController.java4.1.3 User.java4.1.4 UserService.java 4.2 具体实现&#xff08;以根据id查询用户信息为例&#xff09;4.2.1 定义切面类&#x…

基于uni-app的计算机类面试宝设计与实现(毕业论文)

目 录 1 前言 1 1.1 研究目的与意义 1 1.2 研究现状 1 1.3 论文结构 2 2 可行性分析 3 2.1 经济可行性 3 2.2 法律可行性 3 2.3 技术可行性 4 2.4 市场可行性 4 2.5 可行性分析结论 4 3 系统需求分析 4 3.1 用户需求分析 4 3.2 系统功能分析 5 3.3 系统性能需求分析 6 4 概要设…

【网络安全 | 靶机搭建】修改镜像源、更新软件源、安装git、更改python版本等

文章目录 0x00、必要准备0x01、修改镜像源0x02、更新软件源并清除缓存0x03、安装git0x04、更改默认Python版本为python30x05、安装增强功能0x06、vmware虚拟机导出iso0x00、必要准备 安装虚拟机时必须保存用户名、密码,用于后续操作,可以截图保存: 以下内容按个人需要进行配…

重生奇迹MU 强化玩法套路多 极品装备由你打造

欢迎来到重生奇迹MU的强化玩法指南&#xff01;想要打造极品装备吗&#xff1f;不可错过这篇文章&#xff0c;我们将为您揭开最多套路的强化技巧和窍门&#xff0c;帮您节省时间和资源&#xff0c;并带来最高效的升级结果。无论您是新手还是老玩家&#xff0c;本文适合所有级别…

AI浪潮新崛起:借助AI+实景/视频直播创新魅力,开启无人自动直播新时代!

AI浪潮新崛起&#xff1a;借助AI实景/视频直播创新魅力&#xff0c;开启无人自动直播新时代&#xff01; 在科技日新月异的今天&#xff0c;人工智能&#xff08;AI&#xff09;已不再仅仅是科幻电影中的桥段&#xff0c;它正以不可阻挡之势渗透到我们生活的方方面面&#xff…

工业物联网的海量数据如何呈现,可视化设计来助力

工业物联网产生的海量数据需要通过可视化设计来呈现&#xff0c;以帮助用户更好地理解和分析数据。 数据汇总和聚合&#xff1a; 对于大量的数据&#xff0c;可以通过汇总和聚合的方式来减少数据的数量&#xff0c;同时保留关键的信息。例如&#xff0c;将时间序列数据按照小…

Excel 冻结多行多列

背景 版本&#xff1a;office 2021 专业版 无法像下图内某些版本一样&#xff0c;识别选中框选的多行多列。 如下选中后毫无反应&#xff0c;点击【视图】->【冻结窗口】->【冻结窗格】后自动设置为冻结第一列。 操作 如下&#xff0c;要把前两排冻结起来。 选择 C1&a…

2024华为杯研赛D题保姆级教程思路分析+教程

2024年中国研究生数学建模竞赛D题保姆级教程思路分析 D题&#xff1a;大数据驱动的地理综合问题&#xff08;数学分析&#xff0c;统计学&#xff09; 关键词&#xff1a;地理、气候、统计&#xff08;细致到此题&#xff1a;统计指标、统计模型、统计结果解释&#xff09; …

视频压缩篇:适用于 Windows 的 10 款最佳视频压缩器

视频压缩器现在对许多想要减小视频大小的视频编辑者来说非常有名。但是&#xff0c;并非所有可以在网上找到的视频压缩器都能产生最佳输出。因此&#xff0c;我们搜索了可以无损压缩视频的最出色的视频压缩器应用程序。本文列出了您可以在离线、在线和手机上使用的十大最佳视频…

FastAdmin列表用echats渲染,使用表格的templateView实现一个图表渲染的功能

前言 FastAdmin中Bootstrap-table表格参数templateView拥有强大的自定义功能&#xff0c;这里我们使用templateView来实现一个图表渲染的功能。 首先我们itemtpl模板中的数据需要填充为一个JSON数据&#xff0c;包含column和data两列 ,chartdata为我们服务器返回的行中的数据。…

力扣-1035不相交的线(Java详细题解)

题目链接&#xff1a;力扣-1035不相交的线 前情提要&#xff1a; 因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。 dp五部曲。 1.确定dp数组和i下标的含义。 2.确定递推公式。 3.dp初始化。 4.确定dp的遍历顺序。 5.如果没有ac打印dp数组 利于debug。 每一…

nginx模块篇(四)

文章目录 四、Nginx的扩展模块4.1. Lua4.1.1 概念4.1.2 特性4.1.3 应用场景4.1.4 Lua的安装4.1.5 Lua的语法4.1.5.1 第一个Lua程序4.1.5.2 Lua的注释4.1.5.3 标识符4.1.5.4 关键字4.1.5.5 运算符4.1.5.6 全局变量&局部变量4.1.5.7 Lua数据类型nilbooleannumberstringtablef…

串口助手的qt实现思路

要求实现如下功能&#xff1a; 获取串口号&#xff1a; foreach (const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()) {qDebug() << "Port: " << serialPortInfo.portName(); // e.g. "COM1"qDebug() <<…