java八股-Redis Stream和RocketMQ实现的解决方案
文章目录
- Redis Stream方案:
- ShortLinkStatsSaveProducer.java
- ShortLinkStatsSaveConsumer.java
- RocketMQ方案
- ShortLinkStatsSaveProducer.java
- ShortLinkStatsSaveConsumer.java
Redis Stream方案:
ShortLinkStatsSaveProducer.java
package com.nageoffer.shortlink.project.mq.producer;import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;import java.util.Map;import static com.nageoffer.shortlink.project.common.constant.RedisKeyConstant.SHORT_LINK_STATS_STREAM_TOPIC_KEY;/*** 短链接监控状态保存消息队列生产者* 公众号:马丁玩编程,回复:加群,添加马哥微信(备注:link)获取项目资料*/
@Component
@RequiredArgsConstructor
public class ShortLinkStatsSaveProducer {private final StringRedisTemplate stringRedisTemplate;/*** 发送延迟消费短链接统计*/public void send(Map<String, String> producerMap) {stringRedisTemplate.opsForStream().add(SHORT_LINK_STATS_STREAM_TOPIC_KEY, producerMap);}
}
ShortLinkStatsSaveConsumer.java
package com.nageoffer.shortlink.project.mq.consumer;import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.Week;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.nageoffer.shortlink.project.common.convention.exception.ServiceException;
import com.nageoffer.shortlink.project.dao.entity.LinkAccessLogsDO;
import com.nageoffer.shortlink.project.dao.entity.LinkAccessStatsDO;
import com.nageoffer.shortlink.project.dao.entity.LinkBrowserStatsDO;
import com.nageoffer.shortlink.project.dao.entity.LinkDeviceStatsDO;
import com.nageoffer.shortlink.project.dao.entity.LinkLocaleStatsDO;
import com.nageoffer.shortlink.project.dao.entity.LinkNetworkStatsDO;
import com.nageoffer.shortlink.project.dao.entity.LinkOsStatsDO;
import com.nageoffer.shortlink.project.dao.entity.LinkStatsTodayDO;
import com.nageoffer.shortlink.project.dao.entity.ShortLinkGotoDO;
import com.nageoffer.shortlink.project.dao.mapper.LinkAccessLogsMapper;
import com.nageoffer.shortlink.project.dao.mapper.LinkAccessStatsMapper;
import com.nageoffer.shortlink.project.dao.mapper.LinkBrowserStatsMapper;
import com.nageoffer.shortlink.project.dao.mapper.LinkDeviceStatsMapper;
import com.nageoffer.shortlink.project.dao.mapper.LinkLocaleStatsMapper;
import com.nageoffer.shortlink.project.dao.mapper.LinkNetworkStatsMapper;
import com.nageoffer.shortlink.project.dao.mapper.LinkOsStatsMapper;
import com.nageoffer.shortlink.project.dao.mapper.LinkStatsTodayMapper;
import com.nageoffer.shortlink.project.dao.mapper.ShortLinkGotoMapper;
import com.nageoffer.shortlink.project.dao.mapper.ShortLinkMapper;
import com.nageoffer.shortlink.project.dto.biz.ShortLinkStatsRecordDTO;
import com.nageoffer.shortlink.project.mq.idempotent.MessageQueueIdempotentHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.connection.stream.MapRecord;
import org.springframework.data.redis.connection.stream.RecordId;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.stream.StreamListener;
import org.springframework.stereotype.Component;import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;import static com.nageoffer.shortlink.project.common.constant.RedisKeyConstant.LOCK_GID_UPDATE_KEY;
import static com.nageoffer.shortlink.project.common.constant.ShortLinkConstant.AMAP_REMOTE_URL;@Slf4j
@Component
@RequiredArgsConstructor
public class ShortLinkStatsSaveConsumer implements StreamListener<String, MapRecord<String, String, String>> {private final ShortLinkMapper shortLinkMapper;private final ShortLinkGotoMapper shortLinkGotoMapper;private final RedissonClient redissonClient;private final LinkAccessStatsMapper linkAccessStatsMapper;private final LinkLocaleStatsMapper linkLocaleStatsMapper;private final LinkOsStatsMapper linkOsStatsMapper;private final LinkBrowserStatsMapper linkBrowserStatsMapper;private final LinkAccessLogsMapper linkAccessLogsMapper;private final LinkDeviceStatsMapper linkDeviceStatsMapper;private final LinkNetworkStatsMapper linkNetworkStatsMapper;private final LinkStatsTodayMapper linkStatsTodayMapper;private final StringRedisTemplate stringRedisTemplate;private final MessageQueueIdempotentHandler messageQueueIdempotentHandler;@Value("${short-link.stats.locale.amap-key}")private String statsLocaleAmapKey;@Overridepublic void onMessage(MapRecord<String, String, String> message) {String stream = message.getStream();RecordId id = message.getId();if (messageQueueIdempotentHandler.isMessageBeingConsumed(id.toString())) {// 判断当前的这个消息流程是否执行完成if (messageQueueIdempotentHandler.isAccomplish(id.toString())) {return;}throw new ServiceException("消息未完成流程,需要消息队列重试");}try {Map<String, String> producerMap = message.getValue();ShortLinkStatsRecordDTO statsRecord = JSON.parseObject(producerMap.get("statsRecord"), ShortLinkStatsRecordDTO.class);actualSaveShortLinkStats(statsRecord);stringRedisTemplate.opsForStream().delete(Objects.requireNonNull(stream), id.getValue());} catch (Throwable ex) {// 某某某情况宕机了messageQueueIdempotentHandler.delMessageProcessed(id.toString());log.error("记录短链接监控消费异常", ex);throw ex;}messageQueueIdempotentHandler.setAccomplish(id.toString());}public void actualSaveShortLinkStats(ShortLinkStatsRecordDTO statsRecord) {String fullShortUrl = statsRecord.getFullShortUrl();RReadWriteLock readWriteLock = redissonClient.getReadWriteLock(String.format(LOCK_GID_UPDATE_KEY, fullShortUrl));RLock rLock = readWriteLock.readLock();rLock.lock();try {LambdaQueryWrapper<ShortLinkGotoDO> queryWrapper = Wrappers.lambdaQuery(ShortLinkGotoDO.class).eq(ShortLinkGotoDO::getFullShortUrl, fullShortUrl);ShortLinkGotoDO shortLinkGotoDO = shortLinkGotoMapper.selectOne(queryWrapper);String gid = shortLinkGotoDO.getGid();Date currentDate = statsRecord.getCurrentDate();int hour = DateUtil.hour(currentDate, true);Week week = DateUtil.dayOfWeekEnum(currentDate);int weekValue = week.getIso8601Value();LinkAccessStatsDO linkAccessStatsDO = LinkAccessStatsDO.builder().pv(1).uv(statsRecord.getUvFirstFlag() ? 1 : 0).uip(statsRecord.getUipFirstFlag() ? 1 : 0).hour(hour).weekday(weekValue).fullShortUrl(fullShortUrl).date(currentDate).build();linkAccessStatsMapper.shortLinkStats(linkAccessStatsDO);Map<String, Object> localeParamMap = new HashMap<>();localeParamMap.put("key", statsLocaleAmapKey);localeParamMap.put("ip", statsRecord.getRemoteAddr());String localeResultStr = HttpUtil.get(AMAP_REMOTE_URL, localeParamMap);JSONObject localeResultObj = JSON.parseObject(localeResultStr);String infoCode = localeResultObj.getString("infocode");String actualProvince = "未知";String actualCity = "未知";if (StrUtil.isNotBlank(infoCode) && StrUtil.equals(infoCode, "10000")) {String province = localeResultObj.getString("province");boolean unknownFlag = StrUtil.equals(province, "[]");LinkLocaleStatsDO linkLocaleStatsDO = LinkLocaleStatsDO.builder().province(actualProvince = unknownFlag ? actualProvince : province).city(actualCity = unknownFlag ? actualCity : localeResultObj.getString("city")).adcode(unknownFlag ? "未知" : localeResultObj.getString("adcode")).cnt(1).fullShortUrl(fullShortUrl).country("中国").date(currentDate).build();linkLocaleStatsMapper.shortLinkLocaleState(linkLocaleStatsDO);}LinkOsStatsDO linkOsStatsDO = LinkOsStatsDO.builder().os(statsRecord.getOs()).cnt(1).fullShortUrl(fullShortUrl).date(currentDate).build();linkOsStatsMapper.shortLinkOsState(linkOsStatsDO);LinkBrowserStatsDO linkBrowserStatsDO = LinkBrowserStatsDO.builder().browser(statsRecord.getBrowser()).cnt(1).fullShortUrl(fullShortUrl).date(currentDate).build();linkBrowserStatsMapper.shortLinkBrowserState(linkBrowserStatsDO);LinkDeviceStatsDO linkDeviceStatsDO = LinkDeviceStatsDO.builder().device(statsRecord.getDevice()).cnt(1).fullShortUrl(fullShortUrl).date(currentDate).build();linkDeviceStatsMapper.shortLinkDeviceState(linkDeviceStatsDO);LinkNetworkStatsDO linkNetworkStatsDO = LinkNetworkStatsDO.builder().network(statsRecord.getNetwork()).cnt(1).fullShortUrl(fullShortUrl).date(currentDate).build();linkNetworkStatsMapper.shortLinkNetworkState(linkNetworkStatsDO);LinkAccessLogsDO linkAccessLogsDO = LinkAccessLogsDO.builder().user(statsRecord.getUv()).ip(statsRecord.getRemoteAddr()).browser(statsRecord.getBrowser()).os(statsRecord.getOs()).network(statsRecord.getNetwork()).device(statsRecord.getDevice()).locale(StrUtil.join("-", "中国", actualProvince, actualCity)).fullShortUrl(fullShortUrl).build();linkAccessLogsMapper.insert(linkAccessLogsDO);shortLinkMapper.incrementStats(gid, fullShortUrl, 1, statsRecord.getUvFirstFlag() ? 1 : 0, statsRecord.getUipFirstFlag() ? 1 : 0);LinkStatsTodayDO linkStatsTodayDO = LinkStatsTodayDO.builder().todayPv(1).todayUv(statsRecord.getUvFirstFlag() ? 1 : 0).todayUip(statsRecord.getUipFirstFlag() ? 1 : 0).fullShortUrl(fullShortUrl).date(currentDate).build();linkStatsTodayMapper.shortLinkTodayState(linkStatsTodayDO);} finally {rLock.unlock();}}
}
RocketMQ方案
<rocketmq-spring-boot-starter.version>2.2.3</rocketmq-spring-boot-starter.version><dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><version>${rocketmq-spring-boot-starter.version}</version>
</dependency>
yaml配置
rocketmq:name-server: 127.0.0.1:9876producer:group: short-link_project-service_stats-save_pgtopic: short-link_project-service_topicsend-message-timeout: 2000retry-times-when-send-failed: 1retry-times-when-send-async-failed: 1consumer:group: short-link_project-service_stats-save_cg
ShortLinkStatsSaveProducer.java
package com.nageoffer.shortlink.project.mq.producer;import com.alibaba.fastjson2.JSON;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.MessageConst;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;import java.util.Map;
import java.util.UUID;/*** 短链接监控状态保存消息队列生产者* 公众号:马丁玩编程,回复:加群,添加马哥微信(备注:link)获取项目资料*/
@Slf4j
@Component
@RequiredArgsConstructor
public class ShortLinkStatsSaveProducer {private final RocketMQTemplate rocketMQTemplate;@Value("${rocketmq.producer.topic}")private String statsSaveTopic;/*** 发送延迟消费短链接统计*/public void send(Map<String, String> producerMap) {String keys = UUID.randomUUID().toString();producerMap.put("keys", keys);Message<Map<String, String>> build = MessageBuilder.withPayload(producerMap).setHeader(MessageConst.PROPERTY_KEYS, keys).build();SendResult sendResult;try {sendResult = rocketMQTemplate.syncSend(statsSaveTopic, build, 2000L);log.info("[消息访问统计监控] 消息发送结果:{},消息ID:{},消息Keys:{}", sendResult.getSendStatus(), sendResult.getMsgId(), keys);} catch (Throwable ex) {log.error("[消息访问统计监控] 消息发送失败,消息体:{}", JSON.toJSONString(producerMap), ex);// 自定义行为...}}
}
ShortLinkStatsSaveConsumer.java
package com.nageoffer.shortlink.project.mq.consumer;import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.Week;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.nageoffer.shortlink.project.common.convention.exception.ServiceException;
import com.nageoffer.shortlink.project.dao.entity.LinkAccessLogsDO;
import com.nageoffer.shortlink.project.dao.entity.LinkAccessStatsDO;
import com.nageoffer.shortlink.project.dao.entity.LinkBrowserStatsDO;
import com.nageoffer.shortlink.project.dao.entity.LinkDeviceStatsDO;
import com.nageoffer.shortlink.project.dao.entity.LinkLocaleStatsDO;
import com.nageoffer.shortlink.project.dao.entity.LinkNetworkStatsDO;
import com.nageoffer.shortlink.project.dao.entity.LinkOsStatsDO;
import com.nageoffer.shortlink.project.dao.entity.LinkStatsTodayDO;
import com.nageoffer.shortlink.project.dao.entity.ShortLinkGotoDO;
import com.nageoffer.shortlink.project.dao.mapper.LinkAccessLogsMapper;
import com.nageoffer.shortlink.project.dao.mapper.LinkAccessStatsMapper;
import com.nageoffer.shortlink.project.dao.mapper.LinkBrowserStatsMapper;
import com.nageoffer.shortlink.project.dao.mapper.LinkDeviceStatsMapper;
import com.nageoffer.shortlink.project.dao.mapper.LinkLocaleStatsMapper;
import com.nageoffer.shortlink.project.dao.mapper.LinkNetworkStatsMapper;
import com.nageoffer.shortlink.project.dao.mapper.LinkOsStatsMapper;
import com.nageoffer.shortlink.project.dao.mapper.LinkStatsTodayMapper;
import com.nageoffer.shortlink.project.dao.mapper.ShortLinkGotoMapper;
import com.nageoffer.shortlink.project.dao.mapper.ShortLinkMapper;
import com.nageoffer.shortlink.project.dto.biz.ShortLinkStatsRecordDTO;
import com.nageoffer.shortlink.project.mq.idempotent.MessageQueueIdempotentHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;import static com.nageoffer.shortlink.project.common.constant.RedisKeyConstant.LOCK_GID_UPDATE_KEY;
import static com.nageoffer.shortlink.project.common.constant.ShortLinkConstant.AMAP_REMOTE_URL;@Slf4j
@Component
@RequiredArgsConstructor
@RocketMQMessageListener(topic = "${rocketmq.producer.topic}",consumerGroup = "${rocketmq.consumer.group}"
)
public class ShortLinkStatsSaveConsumer implements RocketMQListener<Map<String, String>> {private final ShortLinkMapper shortLinkMapper;private final ShortLinkGotoMapper shortLinkGotoMapper;private final RedissonClient redissonClient;private final LinkAccessStatsMapper linkAccessStatsMapper;private final LinkLocaleStatsMapper linkLocaleStatsMapper;private final LinkOsStatsMapper linkOsStatsMapper;private final LinkBrowserStatsMapper linkBrowserStatsMapper;private final LinkAccessLogsMapper linkAccessLogsMapper;private final LinkDeviceStatsMapper linkDeviceStatsMapper;private final LinkNetworkStatsMapper linkNetworkStatsMapper;private final LinkStatsTodayMapper linkStatsTodayMapper;private final MessageQueueIdempotentHandler messageQueueIdempotentHandler;@Value("${short-link.stats.locale.amap-key}")private String statsLocaleAmapKey;@Overridepublic void onMessage(Map<String, String> producerMap) {String keys = producerMap.get("keys");if (!messageQueueIdempotentHandler.isMessageProcessed(keys)) {// 判断当前的这个消息流程是否执行完成if (messageQueueIdempotentHandler.isAccomplish(keys)) {return;}throw new ServiceException("消息未完成流程,需要消息队列重试");}try {String fullShortUrl = producerMap.get("fullShortUrl");if (StrUtil.isNotBlank(fullShortUrl)) {String gid = producerMap.get("gid");ShortLinkStatsRecordDTO statsRecord = JSON.parseObject(producerMap.get("statsRecord"), ShortLinkStatsRecordDTO.class);actualSaveShortLinkStats(fullShortUrl, gid, statsRecord);}} catch (Throwable ex) {// 删除幂等标识messageQueueIdempotentHandler.delMessageProcessed(id.toString());log.error("记录短链接监控消费异常", ex);throw ex;}messageQueueIdempotentHandler.setAccomplish(keys);}public void actualSaveShortLinkStats(String fullShortUrl, String gid, ShortLinkStatsRecordDTO statsRecord) {fullShortUrl = Optional.ofNullable(fullShortUrl).orElse(statsRecord.getFullShortUrl());RReadWriteLock readWriteLock = redissonClient.getReadWriteLock(String.format(LOCK_GID_UPDATE_KEY, fullShortUrl));RLock rLock = readWriteLock.readLock();rLock.lock();try {if (StrUtil.isBlank(gid)) {LambdaQueryWrapper<ShortLinkGotoDO> queryWrapper = Wrappers.lambdaQuery(ShortLinkGotoDO.class).eq(ShortLinkGotoDO::getFullShortUrl, fullShortUrl);ShortLinkGotoDO shortLinkGotoDO = shortLinkGotoMapper.selectOne(queryWrapper);gid = shortLinkGotoDO.getGid();}int hour = DateUtil.hour(new Date(), true);Week week = DateUtil.dayOfWeekEnum(new Date());int weekValue = week.getIso8601Value();LinkAccessStatsDO linkAccessStatsDO = LinkAccessStatsDO.builder().pv(1).uv(statsRecord.getUvFirstFlag() ? 1 : 0).uip(statsRecord.getUipFirstFlag() ? 1 : 0).hour(hour).weekday(weekValue).fullShortUrl(fullShortUrl).gid(gid).date(new Date()).build();linkAccessStatsMapper.shortLinkStats(linkAccessStatsDO);Map<String, Object> localeParamMap = new HashMap<>();localeParamMap.put("key", statsLocaleAmapKey);localeParamMap.put("ip", statsRecord.getRemoteAddr());String localeResultStr = HttpUtil.get(AMAP_REMOTE_URL, localeParamMap);JSONObject localeResultObj = JSON.parseObject(localeResultStr);String infoCode = localeResultObj.getString("infocode");String actualProvince = "未知";String actualCity = "未知";if (StrUtil.isNotBlank(infoCode) && StrUtil.equals(infoCode, "10000")) {String province = localeResultObj.getString("province");boolean unknownFlag = StrUtil.equals(province, "[]");LinkLocaleStatsDO linkLocaleStatsDO = LinkLocaleStatsDO.builder().province(actualProvince = unknownFlag ? actualProvince : province).city(actualCity = unknownFlag ? actualCity : localeResultObj.getString("city")).adcode(unknownFlag ? "未知" : localeResultObj.getString("adcode")).cnt(1).fullShortUrl(fullShortUrl).country("中国").gid(gid).date(new Date()).build();linkLocaleStatsMapper.shortLinkLocaleState(linkLocaleStatsDO);}LinkOsStatsDO linkOsStatsDO = LinkOsStatsDO.builder().os(statsRecord.getOs()).cnt(1).gid(gid).fullShortUrl(fullShortUrl).date(new Date()).build();linkOsStatsMapper.shortLinkOsState(linkOsStatsDO);LinkBrowserStatsDO linkBrowserStatsDO = LinkBrowserStatsDO.builder().browser(statsRecord.getBrowser()).cnt(1).gid(gid).fullShortUrl(fullShortUrl).date(new Date()).build();linkBrowserStatsMapper.shortLinkBrowserState(linkBrowserStatsDO);LinkDeviceStatsDO linkDeviceStatsDO = LinkDeviceStatsDO.builder().device(statsRecord.getDevice()).cnt(1).gid(gid).fullShortUrl(fullShortUrl).date(new Date()).build();linkDeviceStatsMapper.shortLinkDeviceState(linkDeviceStatsDO);LinkNetworkStatsDO linkNetworkStatsDO = LinkNetworkStatsDO.builder().network(statsRecord.getNetwork()).cnt(1).gid(gid).fullShortUrl(fullShortUrl).date(new Date()).build();linkNetworkStatsMapper.shortLinkNetworkState(linkNetworkStatsDO);LinkAccessLogsDO linkAccessLogsDO = LinkAccessLogsDO.builder().user(statsRecord.getUv()).ip(statsRecord.getRemoteAddr()).browser(statsRecord.getBrowser()).os(statsRecord.getOs()).network(statsRecord.getNetwork()).device(statsRecord.getDevice()).locale(StrUtil.join("-", "中国", actualProvince, actualCity)).gid(gid).fullShortUrl(fullShortUrl).build();linkAccessLogsMapper.insert(linkAccessLogsDO);shortLinkMapper.incrementStats(gid, fullShortUrl, 1, statsRecord.getUvFirstFlag() ? 1 : 0, statsRecord.getUipFirstFlag() ? 1 : 0);LinkStatsTodayDO linkStatsTodayDO = LinkStatsTodayDO.builder().todayPv(1).todayUv(statsRecord.getUvFirstFlag() ? 1 : 0).todayUip(statsRecord.getUipFirstFlag() ? 1 : 0).gid(gid).fullShortUrl(fullShortUrl).date(new Date()).build();linkStatsTodayMapper.shortLinkTodayState(linkStatsTodayDO);} catch (Throwable ex) {log.error("短链接访问量统计异常", ex);} finally {rLock.unlock();}}
}
相关文章:
java八股-Redis Stream和RocketMQ实现的解决方案
文章目录 Redis Stream方案:ShortLinkStatsSaveProducer.javaShortLinkStatsSaveConsumer.java RocketMQ方案ShortLinkStatsSaveProducer.javaShortLinkStatsSaveConsumer.java Redis Stream方案: ShortLinkStatsSaveProducer.java package com.nageoff…...
第29天 MCU入门
目录 MCU介绍 MCU的组成与作用 电子产品项目开发流程 硬件开发流程 常用元器件初步了解 硬件原理图与PCB板 常见电源符号和名称 电阻 电阻的分类 贴片电阻的封装说明: 色环电阻的计算 贴片电阻阻值计算 上拉电阻与下拉电阻 电容 电容的读数 二极管 LED 灯电路 钳位作…...
【Python网络爬虫笔记】6- 网络爬虫中的Requests库
一、概述 Requests 是一个用 Python 语言编写的、简洁且功能强大的 HTTP 库。它允许开发者方便地发送各种 HTTP 请求,如 GET、POST、PUT、DELETE 等,并且可以轻松地处理请求的响应。这个库在 Python 生态系统中被广泛使用,无论是简单的网页数…...
Linux网络_网络协议_网络传输_网络字节序
一.协议 1.概念 协议(Protocol) 是一组规则和约定,用于定义计算机网络中不同设备之间如何进行通信和数据交换。协议规定了数据的格式、传输方式、传输顺序等详细规则,确保不同设备和系统能够有效地互联互通。 在网络通信中&#…...
浅谈网络 | 应用层之流媒体与P2P协议
目录 流媒体名词系列视频的本质视频压缩编码过程如何在直播中看到帅哥美女?RTMP 协议 P2PP2P 文件下载种子文件 (.torrent)去中心化网络(DHT)哈希值与 DHT 网络DHT 网络是如何查找 流媒体 直播系统组成与协议 近几年直播比较火,…...
css vue vxe-text-ellipsis table 实现多行文本超出隐藏省略
分享 vxe-text-ellipsis table grid 多行文本溢出省略的用法 正常情况下如果需要使用文本超出隐藏,通过 css 就可以完成 overflow: hidden; text-overflow: ellipsis; white-space: nowrap;但是如果需要实现多行文本溢出,就很难实现里,谷歌…...
基于hexo框架的博客搭建流程
这篇博文讲一讲hexo博客的搭建及文章管理,也算是我对于暑假的一个交代 !!!注意:下面的操作是基于你已经安装了node.js和git的前提下进行的,并且拥有github账号 创建一个blog目录 在磁盘任意位置创建一个…...
数据结构-简单排序
一.前提 二.冒泡排序 三.插入排序 #include<iostream> using namespace std; typedef int ElemengType; void Bubble_Sort(ElemengType A[], int N) {for (int p N - 1; p > 0; p--) {int flag 0;for (int i 0; i < p; i) {if (A[i] > A[i 1]) {swap(A[i], …...
三十一:HTTP多种重定向跳转方式的差异
在现代网站开发中,HTTP 重定向是一种常见的技术,用于将用户的请求从一个 URL 跳转到另一个 URL。重定向机制广泛应用于网站迁移、SEO 优化、以及内容管理系统中。不同的 HTTP 状态码代表不同的重定向方式,每种方式的行为和适用场景各有不同。…...
利用Python爬虫精准获取淘宝商品详情的深度解析
在数字化时代,数据的价值日益凸显,尤其是在电子商务领域。淘宝作为中国最大的电商平台之一,拥有海量的商品数据,对于研究市场趋势、分析消费者行为等具有重要意义。本文将详细介绍如何使用Python编写爬虫程序,精准获取…...
架构师的英文:Architect
中文版 软件架构师 的英文是 “Software Architect”。 Software: 软件Architect: 架构师,通常指的是设计和规划某种系统或结构的人。 Software Architect 通常负责软件系统的整体设计、技术选型、架构规划,确保系统的可扩展性、可维护性和高效性等。…...
数据结构 ——— 计数排序算法的实现
目录 计数排序算法的思想 计数排序算法的实现 计数排序算法的思想 遍历数组,找出数组中的最大值 max 和 最小值 min 最大值 max 减去最小值 min 再加 1 得出数组元素的范围 range 利用 range 的大小 malloc 一个 count 数组用来计数 再对 count 数组进行初始化…...
k8s搭建Istio环境,案例pod一直处在Init:CrashLoopBackOff
1 部署calico网络环境,网上去找k8s版本对应的calico的配置文件,k8s2.8.0我用的3.28 2 安装istio环境 curl -L https://istio.io/downloadIstio | sh - # 省略istioctl生效的步骤 source <(istioctl completion zsh) istioctl install --set profile…...
Jenkins升级到最新版本后无法启动
1. 场景还原 最近在web界面将jenkins升级到最新版本后,后台无法启动jenkins服务,服务状态如下: 运行jenkins命令提示invalid Java version jenkins --version jenkins: invalid Java version: java version "1.8.0_202" Java(TM)…...
用户界面创建一个新的运动类型
● 现在我们需要根据我们之前规划的架构步骤来实现在用户界面创建一个运动类型 ● 首先我们在要获取用户在表单中输入的数据 //从表单中获取数据const type inputType.value;const distance inputDistance.value;const duration inputDuration.value;● 然后针对与不同的运动…...
ubuntu防火墙入门(一)——设置服务、关闭端口
本机想通过git clone gitgithub.com:skumra/robotic-grasping.git下载代码,firewall-config中需要为当前区域的防火墙开启SSH服务吗 是的,如果你想通过 git clone gitgithub.com:skumra/robotic-grasping.git 使用 SSH 协议从 GitHub 下载代码࿰…...
分治算法——二分查找(c++)(详解)
大家好,今天进入一个实用算法:分治算法。 1.分治算法介绍 分治算法,大概就是将一个大问题拆解成若干个小问题,将小问题一一解决,大问题也就迎刃而解。它包含了多种算法,比如递归、递推等。这里就讲解一下其…...
Binder架构
一、架构 如上图,binder 分为用户层和驱动层两部分,用户层有客户端(Client)、服务端(Server)、服务管理(ServiceManager)。 从用户空间的角度,使用步骤如下(…...
大数据治理:解锁数据价值,引领未来创新
目录 引言 一、大数据治理的定义 二、大数据治理的重要性 三、大数据治理的核心组件 四、大数据治理的实践案例 1. 数据标准化 2. 数据质量管理 案例一:医疗行业的大数据治理——智能医疗助手守护健康 引言 在数字化时代,数据已成为企业最宝贵的…...
解决windows下php8.x及以上版本,在Apache2.4中无法加载CURL扩展的问题
本文已首发于:秋码记录 若你也想搭建一个个人博客,可参考:国内 gitee.com Pages 下线了,致使众多站长纷纷改用 github、gitlab Pages 托管平台 在日新月异的信息化下,软件也在跟随着互联网的脚步,逐步推进…...
【韩顺平老师Java反射笔记】
反射 文章目录 基本使用反射机制java程序在计算机有三个阶段反射相关的主要类 反射调用优化Class类的常用方法获取Class对象的6种方式哪些类型有Class对象类加载类加载时机类加载过程图 通过反射获取类的结构信息第一组:java.lang.Class类第二组:java.la…...
Arrays.asList()新增报错,该怎么解决
一、前言 在 Java 开发中,Arrays.asList() 是一个常用的工具方法,它允许开发者快速将数组转换为列表。尽管这个方法非常方便,但许多开发者在使用时可能会遭遇一个常见的错误:尝试向由 Arrays.asList() 返回的列表中添加元素时抛出…...
【热门主题】000072 分布式数据库:开启数据管理新纪元
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 【热…...
基于Springboot开发的云野旅游平台
一、功能介绍 云野旅游平台包含管理员、用户两个角色以及前后台系统。 前台系统功能 用户登录成功后,可以进行查看旅游路线、最新线路、旅游资讯、个人中心、后台管理、购物车、客服等功能模块。进行相对应操作。 后台系统功能 管理员或用户登录成功后…...
2024金盾信安杯线上赛 MISC ezpng[wp]
下载题目发现给了个password和png 图片发现损坏的 password丢随波逐流一键解 base64 给出解码的结果是 cimbar搜索发现在Github有工具 然后对附件中的图片进行小厨房xor 得到一张新图片 利用工具进行跑出答案...
搭建业务的性能优化指南
这是一篇搭建业务优化的心路历程,也是写给搭建业务的性能优化指南。 前言 直到今天,淘内的页面大多都迁移到了 SSR,从我们终端平台 - 搭建研发团队的视角看,业务大致可以分为两类 —— 搭建派 和 源码派。 这两者互不冲突…...
电脑提示报错“Directx error”怎么解决?是什么原因导致的?游戏软件提示“Directx error”错误的解决方案
DirectX Error(DX错误)通常指的是在使用基于DirectX技术的应用程序(尤其是游戏)时遇到的问题。这个问题可能由多种因素导致,以下是一些可能的原因及相应的解决方案: 可能的原因 DirectX版本不匹配&#x…...
Linux——自定义简单shell
shell 自定义shell目标普通命令和内建命令(补充) shell实现实现原理实现代码 自定义shell 目标 能处理普通命令能处理内建命令要能帮助我们理解内建命令/本地变量/环境变量这些概念理解shell的运行 普通命令和内建命令(补充) …...
基于matlab程序实现人脸识别
1.人脸识别流程 1.1.1基本原理 基于YCbCr颜色空间的肤色模型进行肤色分割。在YCbCr色彩空间内对肤色进行了建模发现,肤色聚类区域在Cb—Cr子平面上的投影将缩减,与中心区域显著不同。采用这种方法的图像分割已经能够较为精确的将人脸和非人脸分割开来。…...
Unity跨平台基本原理
Unity跨平台基本原理 Unity跨平台基本原理微软的.Net是什么微软做 .Net平台的目的如何实现的.Net跨语言?总结 .Net Framework.Net Framework的体系结构CLR总结 如何实现的跨平台?.Net Core.Net FrameWork 到 .Net CoreMonoMono如何实现跨平台总结如何实现…...
辽宁省建设培训中心网站/刷粉网站推广快点
- MySQL引擎 -一.MySQL存储MyISAM与InnoDB区别存储引擎Storage Engine:MySQL中的数据、索引以及其他对象是如何存储的,是一套文件系统的实现。二.常用的存储引擎有以下InnoDB引擎:InnoDB引擎提供了对数据库ACID事务的支持。并且还提供…...
wordpress 输入框/网络推广平台大全
变量 是可以改变的值,本质上是内存的空间,用来存储信息 数据类型 本质上是数据的一种存储方式,和它能参与的运算的一种抽象 数据类型的分类 值类型和引用类型的区别 值类型,从栈里互相引用; 引用类型,从堆里…...
吴忠市建设局官方网站/网站开发合同
队列(Queue):具有一定操作约束的线性表 插入和删除操作:只能在一端插入,而在另一端删除 先进先出 1、队列的顺序存储实现 队列的顺序存储结构通常由一个一维数组和一个记录队列头元素位置的变量front以及 一个记录队列…...
起名网站怎么做/运营推广计划怎么写
文章结束给大家来个程序员笑话:[M] 在C语言的应用范畴,如通讯范畴和嵌入式系统范畴,一个的软件项目平日包含很多庞杂的功能,实现这个项目不是一个程序员单枪匹马可以胜任的,往往需要一个团队的有效合作,另外…...
wordpress如何分栏/青岛做网站推广公司
我在同一个类中实现了一些逻辑进程。一个类实例为每个进程获取一个生成器,run()推进所述生成器。在我的情况下,发电机不会结束。在在下面的代码中,您将如何调用foo_函数和foo_对象class C(threading.Thread):def foo_function(self):"&q…...
网站域名费怎么查询/网络优化推广公司哪家好
1:sub dst,src cf1表示无符号数减法发生溢出 OF1表示有符号减法发生溢出 (一个正数减去一个负数却得到一个负数,一个负数减去一个正数却得到一个正数) 2:DEC DST 目的操作数减1,不置标志位,速度…...