谷粒商城收获记录1

谷粒商城收获记录1

尚硅谷鼎鼎大名的谷粒商城,B站开源,最近看了,准备记录下笔记。
多记录下,留下些痕迹。

关于mybatis查询,嵌套查询这种

看了雷神好多的查询方法,包括树形结构,非树形结构查询,采用的是简单查询,mybatis中不进行连接查询,减少连接查询,这种情况会降低mysql查询出现笛卡儿积形式的查询,拖慢效率。

引入jmeter工具进行压力测试

写完了接口之后,往往不知道效率如何并发量怎样,可以采用jmeter来进行测试,拖累吞吐量的地方往往是网络连接,IO操作,主要由以下几个方面造成:

  1. jvm内存分配不足
  2. 项目中使用了各种远程调用,包括业务和中间件的使用,链路长也会造成响应时间长,吞吐量低
  3. 业务代码编写问题,比如大量查询数据库,还有效率低下的sql,应该在业务中减少低效率的sql和引入缓存方式来减少数据库的操作

nginx反向代理,动静分离

  1. nginx反向代理保护了服务端的服务,还可以对网关层进行负载均衡;
  2. 采用动静分离方式,将业务中的图片,js,css等静态资源放入nginx的指定路径下,可以减少这些资源到tomcat中访问,缩短了这类的访问路径,提升了吞吐量。
  3. 真正的产品都是有域名的,咱们可以设置子域名和主域名,在nginx中配置将url转发到特定的服务上。
www.gulimail.com   主域名
search.gulimail.com 子域名

在这里插入图片描述

使用ES进行检索服务

es可以进行多条件的检索,使用倒排索引,根据词找到具体的内容,东西有点多,不写了。。

引入缓存

为了解决吞吐量问题,我们使用缓存,当属redis,我们可以显示的进行redisTemplate进行设置,也可以引入spring-cache来使用redis(redis相关配置和包自行引入),如下几步操作:

  1. 引入依赖
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>

2、配置文件中配置使用redis作为缓存

spring.cache.type=redis

3、配置注解

@EnableCaching   开启注解

@Cacheable 查询完数据库缓存
@CacheEvict 增删改方法,删除缓存(失效模式)
@CachePut 增删改方法,修改完数据库,写入缓存(双写模式)
@Caching 组合上面几种注解

分布式锁

有些业务避免不了使用到锁,但是涉及到分布式项目部署,所以采用了分布式锁来进行解决,使用redis作为分布式锁考虑。

redis满足分布式锁的条件:

  1. redis每步操作都是原子操作;
  2. 锁要满足自动解锁,因为可能宕机,redis可以设置到期时间
  3. 锁重入,可能会进行多次调用,redis设置key时把当前线程id放入,也可以加入定时
  4. 锁续期,可能预定期间无法完成处理请求,引入定时,或者时间稍微长点

redission分布式锁引入

//springboot整合包
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.16.4</version>
</dependency>

使用方式采用java JUC包中Lock使用方式即可

异步编排任务

有时候执行操作时,并发操作可以提高我们的效率,降低响应时间。比如一个场景,先查询数据表1,再查询数据表2,最终将1,2的结果整合再返回给界面,这期间操作,查询1,查询2的操作都是没有关联的,我们可以用异步来进行操作,拼装结果时需要等待1,2的结果。

CompletableFuture

CompletableFuture,结合了Future的优点,提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,提供了函数式编程的能力,可以通过回调的方式处理计算结果,并且提供了转换和组合CompletableFuture的方法,真香!

//无反回值任务,并使用提供的线程池执行
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor);
//有反回值任务,并使用提供的线程池执行
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor);
f1.thenRun(Runnable b)  //f1的结果无法传入到b中,并且整个方法没有返回值
f1.thenAccept(FunctionalInterface b) //f1的值b可以使用,但是整个方法没有返回值
f1.thenApply(FunctionalInterface b) //f1的值b可以使用,整个方法有返回值
f1.thenRun(Runnable b)  //f1的结果无法传入到b中,并且整个方法没有返回值
f1.thenAccept(FunctionalInterface b) //f1的值b可以使用,但是整个方法没有返回值
f1.thenApply(FunctionalInterface b) //f1的值b可以使用,整个方法有返回值

具体详查这个方法的使用吧!

Feign调用加入必要参数

Feign底层是封装了httpclient,通过代理模式来进行调用,注意在调用远程接口时,有些接口是需要带着特殊参数的请求或者特殊header的请求,这些要给自动设置上。

1、同一线程调用feign

设置RequestInterceptor,feign调用前会使用这个拦截器进行包装,在feign配置类中可以使用bean注解,注入一个拦截器,里面把原始上下文的请求信息设置上

@Bean
public RequestInterceptor requestInterceptor() {
	return new RequestInterceptor() {
		@Override
        public void apply(RequestTemplate template) {
           //spring提供从当前线程上下文拿到请求参数
	 ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
	 	//设置进template 
	 	template.header("token",token);	
        }
	} 	
}
2、非同一个线程调用feign

上述方式获取不到,因为是两个线程,获取不到第一个请求的头信息
所以在上面的基础上还得加上一步,就是把带请求参数的线程头信息同步到异步线程中

// 获取当前线程上下文环境器
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//异步线程
CompletableFuture<Void> addressFuture = CompletableFuture.runAsync(() -> {
     // 同步上下文环境器,解决异步无法从ThreadLocal获取RequestAttributes
     RequestContextHolder.setRequestAttributes(requestAttributes);
    //调用feign
 	memberFeignservice.getAddress();     
        }, executor);
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值