某马头条——day10

热文章数据查询

分布式任务调度xxl-job

概述

环境搭建

 

docker化部署

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=root\
-d mysql:5.7
docker pull xuxueli/xxl-job-admin:2.3.0
docker run -e PARAMS="--spring.datasource.url=jdbc:mysql://192.168.200.130:3306/xxl_job?Unicode=true&characterEncoding=UTF-8 \
--spring.datasource.username=root \
--spring.datasource.password=root" \
-p 8888:8080 -v /tmp:/data/applogs \
--name xxl-job-admin --restart=always  -d xuxueli/xxl-job-admin:2.3.0

访问http://127.0.0.1:8888/xxl-job-admin/成功登录。

入门案例

 

<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>
server:port: 8881xxl:job:admin:addresses: http://192.168.200.130:8888/xxl-job-adminexecutor:appname: xxl-job-executor-sampleport: 9999

执行器明层appname必须和调度中心里设置的一样 

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;}}
任务代码,重要注解:@XxlJob(“demoJobHandler”)

这里的demoJobhandler要和调度中心里创建的一样

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("简单任务执行了。。。。");}
}

在调度中心启动之后,就会开始执行了 

任务详解

以下是执行器的属性说明:

属性名称说明
AppName是每个执行器集群的唯一标示AppName, 执行器会周期性以AppName为对象进行自动注册。可通过该配置自动发现注册成功的执行器, 供任务调度时使用;
名称执行器的名称, 因为AppName限制字母数字等组成,可读性不强, 名称为了提高执行器的可读性;
排序执行器的排序, 系统中需要执行器的地方,如任务新增, 将会按照该排序读取可用的执行器列表;
注册方式调度中心获取执行器地址的方式;
机器地址注册方式为"手动录入"时有效,支持人工维护执行器的地址信息;

 

集群下任务路由策略

轮询案例

 修改yml配置文件

server:port: ${port:8881}xxl:job:admin:addresses: http://192.168.200.130:8888/xxl-job-adminexecutor:appname: xxl-job-executor-sampleport: ${executor.port:9999}

3.启动多个微服务

每个微服务轮询的去执行任务

分片广播案例

轮询是一个一个调度,分片是同时调度两个,区别差不多是这样,但是上面这个案例代码实际还是循环了各循环了两万次,只是有一半是对面的,所以没有执行输出。

热文章计算—定时计算

 

实现步骤

频道列表远程接口准备  

计算完成新热数据后,需要给每个频道缓存一份数据,所以需要查询所有频道信息

① 在heima-leadnews-feign-api定义远程接口

import com.heima.model.common.dtos.ResponseResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;@FeignClient("leadnews-wemedia")
public interface IWemediaClient {@GetMapping("/api/v1/channel/list")public ResponseResult getChannels();
}

② heima-leadnews-wemedia端提供接口

import com.heima.apis.wemedia.IWemediaClient;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.wemedia.service.WmChannelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class WemediaClient implements IWemediaClient {@Autowiredprivate WmChannelService wmChannelService;@GetMapping("/api/v1/channel/list")@Overridepublic ResponseResult getChannels() {return wmChannelService.findAll();}
}

在ApArticleMapper.xml新增方法

<select id="findArticleListByLast5days" resultMap="resultMap">SELECTaa.*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>

 修改ApArticleMapper类

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.heima.model.article.dtos.ArticleHomeDto;
import com.heima.model.article.pojos.ApArticle;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;import java.util.Date;
import java.util.List;@Mapper
public interface ApArticleMapper extends BaseMapper<ApArticle> {/*** 加载文章列表* @param dto* @param type  1  加载更多   2记载最新* @return*/public List<ApArticle> loadArticleList(ArticleHomeDto dto,Short type);public List<ApArticle> findArticleListByLast5days(@Param("dayParam") Date dayParam);
}

热文章业务层  

定义业务层接口

package com.heima.article.service;public interface HotArticleService {/*** 计算热点文章*/public void computeHotArticle();
}

修改ArticleConstans

public class ArticleConstants {public static final Short LOADTYPE_LOAD_MORE = 1;public static final Short LOADTYPE_LOAD_NEW = 2;public static final String DEFAULT_TAG = "__all__";public static final String ARTICLE_ES_SYNC_TOPIC = "article.es.sync.topic";public static final Integer HOT_ARTICLE_LIKE_WEIGHT = 3;public static final Integer HOT_ARTICLE_COMMENT_WEIGHT = 5;public static final Integer HOT_ARTICLE_COLLECTION_WEIGHT = 8;public static final String HOT_ARTICLE_FIRST_PAGE = "hot_article_first_page_";
}

创建一个vo接收计算分值后的对象


import com.heima.model.article.pojos.ApArticle;
import lombok.Data;@Data
public class HotArticleVo extends ApArticle {/*** 文章分值*/private Integer score;
}

业务层实现类

package com.heima.article.service.impl;import com.alibaba.fastjson.JSON;
import com.heima.apis.wemedia.IWemediaClient;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.service.HotArticleService;
import com.heima.common.constants.ArticleConstants;
import com.heima.common.redis.CacheService;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.vos.HotArticleVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmChannel;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;@Service
@Slf4j
@Transactional
public class HotArticleServiceImpl implements HotArticleService {@Autowiredprivate ApArticleMapper apArticleMapper;/*** 计算热点文章*/@Overridepublic void computeHotArticle() {//1.查询前5天的文章数据Date dateParam = DateTime.now().minusDays(50).toDate();List<ApArticle> apArticleList = apArticleMapper.findArticleListByLast5days(dateParam);//2.计算文章的分值List<HotArticleVo> hotArticleVoList = computeHotArticle(apArticleList);//3.为每个频道缓存30条分值较高的文章cacheTagToRedis(hotArticleVoList);}@Autowiredprivate IWemediaClient wemediaClient;@Autowiredprivate CacheService cacheService;/*** 为每个频道缓存30条分值较高的文章* @param hotArticleVoList*/private void cacheTagToRedis(List<HotArticleVo> hotArticleVoList) {//每个频道缓存30条分值较高的文章ResponseResult responseResult = wemediaClient.getChannels();if(responseResult.getCode().equals(200)){String channelJson = JSON.toJSONString(responseResult.getData());List<WmChannel> wmChannels = JSON.parseArray(channelJson, WmChannel.class);//检索出每个频道的文章if(wmChannels != null && wmChannels.size() > 0){for (WmChannel wmChannel : wmChannels) {List<HotArticleVo> hotArticleVos = hotArticleVoList.stream().filter(x -> x.getChannelId().equals(wmChannel.getId())).collect(Collectors.toList());//给文章进行排序,取30条分值较高的文章存入redis  key:频道id   value:30条分值较高的文章sortAndCache(hotArticleVos, ArticleConstants.HOT_ARTICLE_FIRST_PAGE + wmChannel.getId());}}}//设置推荐数据//给文章进行排序,取30条分值较高的文章存入redis  key:频道id   value:30条分值较高的文章sortAndCache(hotArticleVoList, ArticleConstants.HOT_ARTICLE_FIRST_PAGE+ArticleConstants.DEFAULT_TAG);}/*** 排序并且缓存数据* @param hotArticleVos* @param key*/private void sortAndCache(List<HotArticleVo> hotArticleVos, String key) {hotArticleVos = hotArticleVos.stream().sorted(Comparator.comparing(HotArticleVo::getScore).reversed()).collect(Collectors.toList());if (hotArticleVos.size() > 30) {hotArticleVos = hotArticleVos.subList(0, 30);}cacheService.set(key, JSON.toJSONString(hotArticleVos));}/*** 计算文章分值* @param apArticleList* @return*/private List<HotArticleVo> computeHotArticle(List<ApArticle> apArticleList) {List<HotArticleVo> hotArticleVoList = new ArrayList<>();if(apArticleList != null && apArticleList.size() > 0){for (ApArticle apArticle : apArticleList) {HotArticleVo hot = new HotArticleVo();BeanUtils.copyProperties(apArticle,hot);Integer score = computeScore(apArticle);hot.setScore(score);hotArticleVoList.add(hot);}}return hotArticleVoList;}/*** 计算文章的具体分值* @param apArticle* @return*/private Integer computeScore(ApArticle apArticle) {Integer scere = 0;if(apArticle.getLikes() != null){scere += apArticle.getLikes() * ArticleConstants.HOT_ARTICLE_LIKE_WEIGHT;}if(apArticle.getViews() != null){scere += apArticle.getViews();}if(apArticle.getComment() != null){scere += apArticle.getComment() * ArticleConstants.HOT_ARTICLE_COMMENT_WEIGHT;}if(apArticle.getCollection() != null){scere += apArticle.getCollection() * ArticleConstants.HOT_ARTICLE_COLLECTION_WEIGHT;}return scere;}
}

在ArticleApplication的引导类中添加以下注解

@EnableFeignClients(basePackages = "com.heima.apis")

定时计算

①:在heima-leadnews-article中的pom文件中新增依赖

<!--xxl-job-->
<dependency><groupId>com.xuxueli</groupId><artifactId>xxl-job-core</artifactId><version>2.3.0</version>
</dependency>

② 在xxl-job-admin中新建执行器和任务

新建执行器:leadnews-hot-article-executor

新建任务:路由策略为轮询,Cron表达式:0 0 2 * * ?

③ leadnews-article中集成xxl-job

XxlJobConfig

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.200.130:8888/xxl-job-adminexecutor:appname: leadnews-hot-article-executorport: 9999

④:在article微服务中新建任务类

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("热文章分值计算调度任务结束...");}
}

查询文章接口改造

在ApArticleService中新增方法

/*** 加载文章列表* @param dto* @param type  1 加载更多   2 加载最新* @param firstPage  true  是首页  flase 非首页* @return*/
public ResponseResult load2(ArticleHomeDto dto,Short type,boolean firstPage);

实现方法

/*** 加载文章列表* @param dto* @param type      1 加载更多   2 加载最新* @param firstPage true  是首页  flase 非首页* @return*/
@Override
public ResponseResult load2(ArticleHomeDto dto, Short type, boolean firstPage) {if(firstPage){String jsonStr = cacheService.get(ArticleConstants.HOT_ARTICLE_FIRST_PAGE + dto.getTag());if(StringUtils.isNotBlank(jsonStr)){List<HotArticleVo> hotArticleVoList = JSON.parseArray(jsonStr, HotArticleVo.class);ResponseResult responseResult = ResponseResult.okResult(hotArticleVoList);return responseResult;}}return load(type,dto);
}

修改控制器

/*** 加载首页* @param dto* @return*/
@PostMapping("/load")
public ResponseResult load(@RequestBody ArticleHomeDto dto){//        return apArticleService.load(dto, ArticleConstants.LOADTYPE_LOAD_MORE);return apArticleService.load2(dto, ArticleConstants.LOADTYPE_LOAD_MORE,true);
}

测试成功

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

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

相关文章

尝试给docker ubuntu22.04镜像添加远程访问桌面

实在时不愿折腾&#xff0c;但是ubuntu 镜像没有桌面&#xff0c;有些操作实在太难受了&#xff0c;效率也不高。硬着头皮上吧。幸亏这是个docker的镜像。要是个虚拟机&#xff0c;这折腾来去&#xff0c;直接崩溃了。docker的好处就是立马就能从头来过&#xff0c;秒级的删除安…

分辨率 时钟频率 lane速率计算

PCLK: pixel clock(像素频率) 计算方法如下&#xff1a; 以1920x1080p/60hz为例&#xff0c;total pixel&#xff1a;2200&#xff0c;total line&#xff1a;1125&#xff0c;filed rate&#xff1a;60Hz&#xff0c;那么&#xff1a;PCLK 2200*1125*60 148.5MHz&#xff1b…

ATF(TF-A)安全通告TF-V11——恶意的SDEI SMC可能导致越界内存读取(CVE-2023-49100)

目录 一、ATF(TF-A)安全通告TFV-11 (CVE-2023-49100) 二、透过事务看本质SDEI是干啥的呢&#xff1f; 三、CVE-2023-49100 1、GICv2 systems 2、GICv3 systems 四、漏洞修复 一、ATF(TF-A)安全通告TFV-11 (CVE-2023-49100) Title 恶意的SDEI SMC可能导致越界内存读取&am…

Spring Security架构

文章目录 过滤器回顾DelegatingFilterProxyFilterChainProxySecurityFilterChainSecurity Filters打印Security Filters将自定义过滤器添加到过滤器链 Handling Security ExceptionsSaving Requests Between AuthenticationRequestCachePrevent the Request From Being Saved R…

Mysql的备份以及恢复

第五章 MySQL的备份及恢复 5.1 MySQL日志管理 在数据库保存数据时&#xff0c;有时候不可避免会出现数据丢失或者被破坏&#xff0c;这样情况下&#xff0c;我们必须保证数据的安全性和完整性&#xff0c;就需要使用日志来查看或者恢复数据了 数据库中数据丢失或被破坏可能原…

Spring SpEL在Flink中的应用-与Filter结合实现数据动态分流

文章目录 前言一、POM依赖二、主函数代码示例三、FilterFunction实现总结 前言 SpEL表达式与Flink fiter结合可以实现基于表达式的灵活动态过滤。有关SpEL表达式的使用请参考Spring SpEL在Flink中的应用-SpEL详解。 可以将过滤规则放入数据库&#xff0c;根据不同的数据设置不…

【c++学习】数据结构中的顺序表

c顺序表 数据结构中的顺序表代码 数据结构中的顺序表 顺序表强调数据的存储结构&#xff0c;表示数据在内存中连续存储。&#xff08;线性表与链表相对&#xff0c;链表数据在内存中的存储空间是不连续的&#xff09; 代码 下述代码实现了线性表及其接口 包括增、删、查、改…

《游戏-01_3D-开发》之—人物动画控制器

创建变量&#xff0c; 创建线&#xff0c; 连接&#xff0c; 选中线会变为蓝色&#xff0c;新增变量&#xff0c; 设置线&#xff0c; 双击子层进入子层&#xff0c; 创建变量&#xff0c; 双击SkillPanel 拖拽好之后返回上一层&#xff0c; 依次连接&#xff0c; 设置线&#…

解释LoRA参数

目录 LoRA参数含义 LoRA在深度学习中的作用 示例代码中的LoRA应用 结论 LoRA参数含义 LoRA (lora_r): LoRA代表"Low-Rank Adaptation"&#xff0c;是一种模型参数化技术&#xff0c;用于在不显著增加参数数量的情况下调整预训练模型。lora_r参数指的是LoRA中的秩&…

[Tomcat] [从安装到关闭] MAC部署方式

安装Tomcat 官网下载&#xff1a;Apache Tomcat - Apache Tomcat 9 Software Downloads 配置Tomcat 1、输入cd空格&#xff0c;打开Tomca目录&#xff0c;把bin文件夹直接拖拉到终端 2、授权bin目录下的所有操作&#xff1a;终端输入[sudo chmod 755 *.sh]&#xff0c;回车 …

springboot(ssm干洗店预约洗衣系统 衣物清洗预约系统Java系统

springboot(ssm干洗店预约洗衣系统 衣物清洗预约系统Java系统 开发语言&#xff1a;Java 框架&#xff1a;springboot&#xff08;可改ssm&#xff09; vue JDK版本&#xff1a;JDK1.8&#xff08;或11&#xff09; 服务器&#xff1a;tomcat 数据库&#xff1a;mysql 5.7…

docker: 搭建 harbor 镜像仓库

harbor 企业级内网镜像管理软件&#xff0c;加速拉取镜像速度&#xff0c;web 页面管理方便。 系统优化 systemctl stop NetworkManager systemctl disable NetworkManager iptables -F systemctl restart docker安装docker [roottest05 ~]# yum install -y docker-compose…

【GitHub项目推荐--不错的 Go 学习项目】【转载】

开源实时性能分析平台 Pyroscope 是基于 Go 的开源实时性能分析平台&#xff0c;在源码中添加几行代码 pyroscope 就能帮你找出源代码中的性能问题和瓶颈、CPU 利用率过高的原因&#xff0c;调用树展示帮助你理解程序&#xff0c;支持 Go、Python、Ruby 语言。 Pyroscope 可以…

nestjs之适配器模式的应用

NestJS 是一个用于构建高效、可靠和可扩展的服务器端应用程序的框架。在 NestJS 中&#xff0c;适配器模式&#xff08;Adapter Pattern&#xff09;主要体现在其对不同类型的 HTTP 服务端框架的适配上。NestJS 本身是建立在 Express 或者 Fastify 这样的底层 HTTP 框架之上的&…

openssl3.2/test/certs - 033 - time stamping certificates

文章目录 openssl3.2/test/certs - 033 - time stamping certificates概述笔记END openssl3.2/test/certs - 033 - time stamping certificates 概述 openssl3.2 - 官方demo学习 - test - certs 笔记 /*! \file my_openssl_linux_log_doc_033.txt\note openssl3.2/test/ce…

《解释与话语权》——西游真假美猴王是自导自演吗

解读与话语权 引言 一旦有人或者组织垄断了话语权&#xff0c;那么什么都可以被重新定义和解读&#xff0c;本篇旨在让读者有更多视角的思考。 为什么一个耶和华能分裂成天主教&#xff0c;东正教&#xff0c;新教等&#xff0c;都是对于圣经和圣经故事的不同解读。 红学那…

解析GPT-3、GPT-4和ChatGPT关系-迈向自然语言处理的新高度“

Hello&#xff0c;小索奇&#xff01;很高兴为你拓展关于GPT-3、GPT-4、ChatGPT之间关系的信息&#xff0c;以及解释自然语言模型和Transformer的区别。 首先&#xff0c;GPT-3、GPT-4、ChatGPT都是建立在GPT系列技术基础上的自然语言处理模型。它们在不同的代数、性能和应用场…

k8s的图形化工具---rancher

rancher是一个开源的企业级多集群的k8s管理平台。 rancher和k8s的区别&#xff1a;都是为了容器的调度和编排系统。但是rancher不仅可以调度还可以管理整个k8s集群。 rancher自带监控(普罗米修斯) 实验部署 master01 20.0.0.32 node01 20.0.0.34 node02 20.0.0.35 test …

linux系统mysql8单机多实例+主从复制部署

一、解压mysql压缩包 参考我的另一篇博文&#xff0c;tag.gz解压完并且配置完环境变量即可&#xff0c;暂时不要初始化 linux单机部署mysql(离线环境解压即可)-CSDN博客 二、修改配置文件 可能因为版本不同&#xff0c;我的这个配置可能不是通用的&#xff0c;我安装的是my…

【Java Kubernates】Java调用kubernates提交Yaml到SparkOperator

背景 目前查询框架使用的是trino&#xff0c;但是trino也有其局限性&#xff0c;需要准备一个备用的查询框架。考虑使用spark&#xff0c;spark operator也已经部署到k8s&#xff0c;现在需要定向提交spark sql到k8s的sparkoperator上&#xff0c;使用k8s资源执行sql。 对比 …