当前位置: 首页 > news >正文

网站建设目录网站推广的一般流程是

网站建设目录,网站推广的一般流程是,宿州公司做网站,免费虚拟主机免备案文章目录 前言什么时候需要异步调用常见同步耗时问题系统资源被白白浪费 异步调用实现方式Async注解消息队列 线程池配置要合理Async注解失效问题总结 前言 说起异步调用#xff0c;我想起刚学习微服务那会儿做的一个电商项目。用户下单后#xff0c;系统要扣库存、发短信、… 文章目录 前言什么时候需要异步调用常见同步耗时问题系统资源被白白浪费 异步调用实现方式Async注解消息队列 线程池配置要合理Async注解失效问题总结 前言 说起异步调用我想起刚学习微服务那会儿做的一个电商项目。用户下单后系统要扣库存、发短信、记日志…一大堆操作。当时图省事全部写在一个接口里同步执行。结果用户点完下单按钮页面要转10多秒才有反应用户还以为系统卡死了经常重复点击。后来排查发现发短信的第三方接口响应特别慢所有订单请求都堵在那里等着。那一刻才真正意识到异步调用的重要性。 现在回头看异步调用不仅仅是技术优化更是用户体验的保证。今天就来聊聊Spring Boot中异步调用的各种实现方式从最简单的Async到消息队列。 什么时候需要异步调用 常见同步耗时问题 想象一下这些场景用户上传头像页面转圈转了30秒用户注册成功等了半天才跳转还不知道是不是真的成功了导出个Excel报表浏览器直接超时…其实这些问题的根源都一样把不需要立即返回结果的操作和核心业务流程耦合在一起了。用户注册核心是把用户信息存到数据库至于发欢迎邮件、初始化用户数据这些完全可以后台慢慢处理。 系统资源被白白浪费 还有一个更隐蔽的问题资源浪费。Java的线程模型是一个请求对应一个线程如果线程都在等I/O操作数据库查询、文件读写CPU其实是闲着的但线程资源却被占用了。 异步调用实现方式 Async注解 对于刚接触异步编程的同学Async绝对是最友好的选择。只需要加个注解并自定义线程池Spring就帮你把方法丢到线程池里执行。 Configuration EnableAsync public class AsyncConfig {/**配置了一个名为taskExecutor的线程池核心线程数10始终保持活跃的线程数量最大线程数20当队列满时可以扩展到的最大线程数队列容量200任务队列能容纳的最大任务数线程名前缀Task-便于日志追踪*/Bean(taskExecutor)public TaskExecutor taskExecutor() {ThreadPoolTaskExecutor executor new ThreadPoolTaskExecutor();executor.setCorePoolSize(10); executor.setMaxPoolSize(20); executor.setQueueCapacity(200); executor.setThreadNamePrefix(Task-);executor.initialize();return executor;} }Service public class UserService {Async(taskExecutor)public void sendWelcomeEmail(String email) {try {// 模拟发邮件耗时Thread.sleep(2000);log.info(欢迎邮件发送成功: {}, email);} catch (Exception e) {log.error(邮件发送失败, e);}}Transactionalpublic User registerUser(UserRegisterDTO dto) {// 核心注册逻辑快速返回User user new User();user.setEmail(dto.getEmail());user.setUsername(dto.getUsername());User savedUser userRepository.save(user);// 异步发送欢迎邮件sendWelcomeEmail(user.getEmail());return savedUser;} }在代码中registerUser() 会在调用 sendWelcomeEmail() 后立刻继续执行并返回结果邮件发送由后台线程处理。这种方式的好处是简单直接。但有个坑要注意Async注解在同一个类的方法调用中是不生效的因为Spring AOP的限制。如果需要在同一个类里调用异步方法要么注入自己要么把异步方法提取到单独的Service里。 消息队列 当系统拆分成多个微服务后异步处理就不仅仅是单个应用内部的事了。这时候消息队列就派上用场了。我个人比较喜欢RabbitMQ配置简单功能够用。 Configuration EnableRabbit public class RabbitConfig {Beanpublic DirectExchange userExchange() {return new DirectExchange(user.exchange);}Beanpublic Queue userRegisteredQueue() {return QueueBuilder.durable(user.registered.queue).build();}Beanpublic Binding userRegisteredBinding() {return BindingBuilder.bind(userRegisteredQueue()).to(userExchange()).with(user.registered);} }// 用户服务 - 消息发送方 Service public class UserService {Autowiredprivate RabbitTemplate rabbitTemplate;Transactionalpublic User registerUser(UserRegisterDTO dto) {User user new User();user.setEmail(dto.getEmail());user.setUsername(dto.getUsername());User savedUser userRepository.save(user);// 发送用户注册消息UserRegisteredMessage message new UserRegisteredMessage(savedUser.getId(), savedUser.getEmail(), savedUser.getUsername());rabbitTemplate.convertAndSend(user.exchange, user.registered, message);log.info(用户注册消息已发送: {}, savedUser.getId());return savedUser;} }// 通知服务 - 消息接收方 Component public class NotificationService {RabbitListener(queues user.registered.queue)public void handleUserRegistered(UserRegisteredMessage message) {try {log.info(收到用户注册消息: {}, message.getUserId());// 发送欢迎邮件emailService.sendWelcomeEmail(message.getEmail(), message.getUsername());// 发送欢迎短信smsService.sendWelcomeSms(message.getPhone());log.info(用户注册后续处理完成: {}, message.getUserId());} catch (Exception e) {log.error(处理用户注册消息失败: {}, message.getUserId(), e);// 这里可以实现重试逻辑或者发送到死信队列throw e;}} }消息队列的好处是彻底解耦用户服务不需要知道有哪些下游服务只管发消息就行。而且天然支持重试、死信队列等容错机制。 不过消息队列也带来了复杂性消息顺序、重复消费、消息丢失等问题都需要考虑。我的建议是如果是单体应用优先考虑使用Async注解如果已经是微服务架构那消息队列是必选项。 线程池配置要合理 异步调用的核心是线程池配置不当会适得其反。我见过有的项目线程池设置得太小异步任务排队等待还不如同步执行快也见过设置得太大结果把系统内存撑爆了。 Configuration public class AsyncExecutorConfig {// CPU密集型任务Bean(cpuTaskExecutor)public TaskExecutor cpuTaskExecutor() {ThreadPoolTaskExecutor executor new ThreadPoolTaskExecutor();// CPU密集型核心线程数 CPU核数int processors Runtime.getRuntime().availableProcessors();executor.setCorePoolSize(processors);executor.setMaxPoolSize(processors * 2);executor.setQueueCapacity(50);executor.setThreadNamePrefix(cpu-task-);return executor;}// I/O密集型任务Bean(ioTaskExecutor)public TaskExecutor ioTaskExecutor() {ThreadPoolTaskExecutor executor new ThreadPoolTaskExecutor();// I/O密集型可以设置更多线程executor.setCorePoolSize(20);executor.setMaxPoolSize(50);executor.setQueueCapacity(200);executor.setThreadNamePrefix(io-task-);executor.setKeepAliveSeconds(60);return executor;} }一般来说CPU密集型任务的线程数设置为CPU核数比较合适I/O密集型任务可以设置更多线程具体数量需要根据实际情况调优。 Async注解失效问题 这个坑我估计每个Spring开发者都踩过。Async在同一个类的方法调用中是不生效的因为Spring AOP的代理机制限制。 错误写法 Service public class UserService {public void registerUser(User user) {userRepository.save(user);sendWelcomeEmail(user.getEmail()); // 这里调用不会异步执行}Asyncpublic void sendWelcomeEmail(String email) {// 发送邮件逻辑} }正确写法 // 正确写法1提取到单独的Service Service public class UserService {Autowiredprivate NotificationService notificationService;public void registerUser(User user) {userRepository.save(user);notificationService.sendWelcomeEmail(user.getEmail());} }Service public class NotificationService {Asyncpublic void sendWelcomeEmail(String email) {// 发送邮件逻辑} }总结 异步调用是现代Java应用开发的必备技能选择合适的实现方式很重要。简单的异步操作用Async就够了配置简单上手快。如果是微服务架构消息队列是必选项解耦彻底扩展性好。
http://www.w-s-a.com/news/308308/

相关文章:

  • 网站开发工作需要什么专业学做网站游戏教程
  • 电子商务网站规划 分析 设计杭州网站优化平台
  • 汕头企业自助建站系统网站后台登陆验证码无法显示
  • 宁波网站制作服务做外贸推广自己网站
  • php 微信 网站开发青岛网站互联网公司
  • 网站软件免费下载大全网站建设开发价格高吗
  • asp网站制作软件上海做网站制作
  • 福田区住房和建设局网站好搜搜索引擎
  • 平面设计师看的网站济南机场建设
  • 俄文网站开发翻译平台页面设计模板
  • 建设在线购物网站淮南电商网站建设价格
  • 龙泉市旅游门户网站建设wordpress faq插件
  • 网站的流程图贵阳做网站方舟网络
  • c 做网站开发实例wordpress 加上index
  • 济南seo网站推广搜索广告推广
  • 有关于网站建设的参考文献宁波seo网络推广公司
  • 网站设配色个人主页介绍文案
  • 网站seo相关设置优化网站建设的好处
  • 上海市建设工程安全生产协会网站郴州网站设计公司
  • 网站大型网页游戏自己搭建服务器做视频网站
  • 建立网站企业wordpress用户名密码破解
  • 网站管理助手建站教程国外网站做acm题目比较好
  • 网站开发框架排行专业网页制作服务商
  • 企业网站建设入账政务网站建设信息
  • 网络平台建设是什么江门排名优化怎么做
  • 响应式旅游网站模板下载网址做
  • 个人做网站名称可以随意更改吗惠州网站推广排名
  • 自己建设一个网站步骤网站认证怎么认证
  • 深圳建站公司开发费用沧州手机建站哪家好
  • 兰州网站设计公司排名百度怎么发布短视频