当前位置:网站首页>Implementation of distributed scenario business operation log (based on redis lightweight)
Implementation of distributed scenario business operation log (based on redis lightweight)
2022-04-23 02:36:00 【Fat brother 1930】
order
I don't have time to write in detail today , Let's talk about the current demand scenario , I just want to insert the business operation log ,springCloud Environmental Science . then , Based on the results of my implementation , Let's say , Design has no formula , It's the foundation 、 Series connection of characteristics .
One 、 Design thinking
Through the analysis of , And find other groups of colleagues to learn from , The general design idea is not divided 3 class , as follows :
1、 Based on the section AOP
2、 Based on events ,EventBus or SpringBus
3、 Based on message oriented middleware
Two 、 Trade-off process
1. Based on the section ( House )
the reason being that springCloud Distributed scenarios , If cut , Then there is 2 A plan :
A、 Each service handles all aspects by itself
I don't think everyone wants to , This means that every service has to have a set AOP Cut code , Too complicated , In addition, you may need to insert a composite business operation log in the later stage of the business . Then the transmission parameters and everything may need to be changed , To transfer parameters of the business interface , The change is too big , The risk is too high , And complicated , House .
B、 Cut in the gateway
What the gateway does is no longer pure , Loss of understanding , For the composite business operation log to be inserted , You may also face the need to modify the parameters of the business interface ... House
2. Based on events ,EventBus or SpringBus( House )
Let's start with the scene , this 2 For a single service springBoot, It must be very fragrant . But here we have to compare their differences , Lose the conclusion directly :

Look at the official documents and you can roughly know , this 2 Neither way is suitable for SpringCloud Distributed scenarios .
3. Based on message oriented middleware
This is because the business operation log is a lightweight business scenario , Adopted redis Publish and subscribe to information .redis It has also been implemented before publishing and subscribing to , Here I will directly share the core code , With some business design .
RedisSubListenerConfig
import cn.hutool.core.util.ArrayUtil;
import com.fillersmart.fsihouse.commonservice.component.RedisReceiver;
import com.fillersmart.fsihouse.data.constant.ConstantsEnum.MsgType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.stereotype.Component;
/** * redis Subscription listening configuration * * @author zhengwen **/
@Component
public class RedisSubListenerConfig {
@Value("${redis.msg.topics}")
private String topics;
/** * Initialize listener * * @param connectionFactory Connection factory * @param listenerAdapter Monitor adapter * @return redis Listening container */
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
List<PatternTopic> topicList = new ArrayList<>();
// new PatternTopic(" Here is the name of the monitoring channel ") The channel should be consistent with that of the publisher
if (StringUtils.isNotBlank(topics)) {
String[] topisArr = topics.split(",");
if (ArrayUtil.isNotEmpty(topisArr)) {
Arrays.stream(topisArr).forEach(c -> {
PatternTopic topic = new PatternTopic(c);
topicList.add(topic);
});
}
}
// Enumerate information channels
Arrays.stream(MsgType.values()).forEach(m -> {
PatternTopic topic = new PatternTopic(m.getType());
topicList.add(topic);
});
container.addMessageListener(listenerAdapter, topicList);
return container;
}
/** * Binding message listener and receiving listener * * @param redisReceiver redis recipient * @return Information monitoring adapter */
@Bean
MessageListenerAdapter listenerAdapter(RedisReceiver redisReceiver) {
// redisReceiver Message Receiver
// receiveMessage The method after receiving the message
return new MessageListenerAdapter(redisReceiver, "receiveMessage");
}
@Bean
StringRedisTemplate template(RedisConnectionFactory connectionFactory) {
return new StringRedisTemplate(connectionFactory);
}
/** * Registered subscribers * * @param latch CountDownLatch * @return RedisReceiver */
@Bean
RedisReceiver receiver(CountDownLatch latch) {
return new RedisReceiver(latch);
}
/** * Counter , Used to control threads * * @return CountDownLatch */
@Bean
CountDownLatch latch() {
// Number of times count specified 1
return new CountDownLatch(1);
}
}
RedisReceiver
import cn.hutool.json.JSONUtil;
import com.fillersmart.fsihouse.commonservice.service.CommonService;
import com.fillersmart.fsihouse.data.core.Result;
import com.fillersmart.fsihouse.data.vo.msgpush.RedisMsgVo;
import java.util.concurrent.CountDownLatch;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/*** * Message Receiver ( subscriber ) It needs to be injected into springboot in * @author zhengwen */
@Slf4j
@Component
public class RedisReceiver {
private CountDownLatch latch;
@Resource
private CommonService commonService;
@Autowired
public RedisReceiver(CountDownLatch latch) {
this.latch = latch;
}
/** * The method executed after receiving the message of the channel * * @param message */
public void receiveMessage(String message) {
// Here is the method to execute after receiving the channel's message
log.info("common General services received redis Information :" + message);
if (JSONUtil.isTypeJSON(message)) {
RedisMsgVo redisMsgVo = JSONUtil.toBean(message,RedisMsgVo.class);
Result<?> res = commonService.dealRedisMsg(redisMsgVo);
log.info("--redis Message processing results :{}",JSONUtil.toJsonStr(res));
}
latch.countDown();
}
}
The following is business related
dealRedisMsg Method
@Override
public Result<?> dealRedisMsg(RedisMsgVo redisMsgVo) {
log.info("-- General Services common Handle redis news --");
String queueName = redisMsgVo.getQueueName();
if (StringUtils.isBlank(queueName)) {
return ResultGenerator.genFailResult("redis The information queue name is empty ");
}
MsgType msgType = MsgType.getEnum(queueName);
if (msgType == null) {
return ResultGenerator.genFailResult(" Unknown redis Information queue name ");
}
String msgContent = redisMsgVo.getContent();
switch (msgType) {
case PAYED_MSG:
// Post payment information
break;
case BUSINESS_OPERATE_LOG_MSG:
// Business operation record
if (JSONUtil.isTypeJSON(msgContent)) {
BusinessOperateLogVo businessOperateLogVo = JSONUtil.toBean(msgContent,
BusinessOperateLogVo.class);
if (businessOperateLogVo == null) {
log.error(" Business operation record {} Convert to null ", msgContent);
} else {
businessOperateLogService.addBusLog(businessOperateLogVo);
}
}
break;
default:
break;
}
return ResultGenerator.genSuccessResult();
}
addBusLog Method
@Override
@Async
public Result<?> addBusLog(BusinessOperateLogVo businessOperateLogVo) {
// Parameter checking
Assert.notNull(businessOperateLogVo.getPlatform(), ResponseCodeI18n.PLATFORM_NULL.getMsg());
Assert.notNull(businessOperateLogVo.getOperateUserId(),
ResponseCodeI18n.OPERATE_USER_NULL.getMsg());
Assert.notNull(businessOperateLogVo.getBusinessId(),
ResponseCodeI18n.BUSINESS_ID_NULL.getMsg());
Assert.notNull(businessOperateLogVo.getCompanyId(), ResponseCodeI18n.PROJECT_ID_NULL.getMsg());
// Initial operator information
initOperateUserName(businessOperateLogVo);
// Initial business operation information
BusinessOperateLog operateLog = initBusinseeOperateLog(businessOperateLogVo);
businessOperateLogMapper.insert(operateLog);
return ResultGenerator.genSuccessResult();
}
Calling method
ThreadUtil.execAsync(() -> {
// Asynchronously convert and send redis Information
BusinessOperateVo businessOperateVo = new BusinessOperateVo(operateUserId.longValue(),DevicePlatformType.OPERATION_PC);
// Contract operation records
BusinessDataVo businessDataVo = new BusinessDataVo(JSONObject.parseObject(JSONObject.toJSONString(finalUserSubscribe)),
BusinessDataType.SUBSCRIBE_DATA,BusinessOperateType.BACK_APPLY,BusinessType.SUBSCRIBE);
businessOperateVo.getBusinessDataList().add(businessDataVo);
// The log of the rent return document
businessDataVo = new BusinessDataVo(JSONObject.parseObject(JSONObject.toJSONString(backApply)),
BusinessDataType.BACK_APPLY_DATA, BusinessOperateType.BACK_APPLY,BusinessType.BACK_APPLY);
businessOperateVo.getBusinessDataList().add(businessDataVo);
businessOperateLogRpcService.convertLogSendToRedis(businessOperateVo);
});
Supplementary table structure
CREATE TABLE `business_operate_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`company_id` int(11) DEFAULT NULL COMMENT ' project id',
`operate_type` int(2) DEFAULT NULL COMMENT ' Operation type ',
`operate_name` varchar(200) DEFAULT NULL COMMENT ' Operation name ',
`operate_time` datetime DEFAULT NULL COMMENT ' Operating time ',
`business_id` bigint(20) DEFAULT NULL COMMENT ' Business data primary key id',
`business_type` int(2) DEFAULT NULL COMMENT ' Business types ',
`operate_user_id` bigint(20) DEFAULT NULL COMMENT ' Operation user id',
`operate_user_name` varchar(200) DEFAULT NULL COMMENT ' Name of operator ( redundancy )',
`platform` int(1) DEFAULT NULL COMMENT ' Source of operating platform ',
`memo` varchar(500) DEFAULT NULL COMMENT ' remarks ',
`create_by` int(11) DEFAULT NULL COMMENT ' founder id',
`create_time` datetime DEFAULT NULL COMMENT ' Creation time ',
`is_deleted` int(1) DEFAULT NULL COMMENT ' Whether or not to delete ,0 no ,1 yes ',
PRIMARY KEY (`id`),
KEY `business_operate_log_company_id_IDX` (`company_id`) USING BTREE,
KEY `business_operate_log_business_type_IDX` (`business_type`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=246 DEFAULT CHARSET=utf8mb4 COMMENT=' Business logging ';
Screenshot of supplementary log storage

summary
1、ThreadUtil It's delicious (HuTool The toolkit ), Asynchronous does not affect interface performance
2、 The business trigger point only needs to pay attention to the key transmission parameters of the business operation log
3、 Scenarios run through distributed scenarios
Okay , Time is tight , So I'm going to go over here , I hope that helps , If you have any questions, please leave a message .
版权声明
本文为[Fat brother 1930]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204220822178570.html
边栏推荐
- 006_redis_SortedSet类型
- Consider defining a bean of type 'com netflix. discovery. AbstractDiscoveryClientOptionalArgs‘
- 【2019-CVPR-3D人体姿态估计】Fast and Robust Multi-Person 3D Pose Estimation from Multiple Views
- wordpress 调用指定页面内容详解2 get_children()
- [nk]牛客月赛48 D
- Synchronized lock and its expansion
- 011_ Redistemplate operation hash
- php 2022年4月20面试题整理
- VMware virtual machine installation openwrt as side route single arm route img image to vmdk
- 001_ Redis set survival time
猜你喜欢

Yes, from today on, our fans can participate in Netease data analysis training camp for free!

Using go language to build web server

SQL server2019 cannot download the required files, which may indicate that the version of the installer is no longer supported. What should I do

hack the box optimum靶机

Download the genuine origin Pro 2022 tutorial and how to activate it

SQL server2019无法下载所需文件,这可能表示安装程序的版本不再受支持,怎么办了

006_ redis_ Sortedset type

Talk about biology live broadcast: Dr. Wang Ziyuan, a lake view biology, exploring hepatitis B with gene therapy

VMware virtual machine installation openwrt as side route single arm route img image to vmdk

Arduino esp8266 network upgrade OTA
随机推荐
So library dependency
Tp6 Alibaba cloud SMS window reports curl error 60: SSL certificate problem: unable to get local issuer certificate
解决 注册谷歌邮箱 gmail 手机号无法用于验证
009_ Redis_ Getting started with redistemplate
[chrome extender] content_ Cross domain problem of script
Use of go language web Middleware
007_ Redis_ Jedis connection pool
The importance of ERP integration to the improvement of the company's system
006_ redis_ Jedis quick start
假如404页面是这样的 | 每日趣闻
013_ Analysis of SMS verification code login process based on session
【Chrome扩展程序】content_script的跨域问题
010_StringRedisTemplate
RT_ Thread ask and answer
Wechat public platform test number application, authorized login function and single sign on using hbuilder X and wechat developer tools
小程序 canvas 画布半圆环
If 404 page is like this | daily anecdotes
牛客手速月赛 48 C(差分都玩不明白了属于是)
Preliminary understanding of stack and queue
想用Mac学习sql,主要给自己个充足理由买Mac听听意见