当前位置:   article > 正文

微服务入门学习笔记(黑马商城)

微服务入门学习笔记(黑马商城)

 课程转跳:SpringCloud微服务Day1-01.微服务课程介绍_哔哩哔哩_bilibili

一、服务拆分

新建一个maven项目将商品服务拆分出去

更改包扫描 

新建一个数据库用于商品服务,同样将表拆分出去

 更改配置文件的服务名和数据库名

 启动多个实例:

 

复制配置修改名称,修改运行端口 

 

启动成功。

 二、服务注册发现(nacos)

创建数据库导入需要的sql文件

centos使用docker安装nacos 

https://hub.docker.com/r/nacos/nacos-server

运行:(前提安装docker)

docker pull nacos/nacos-server

docker images

mkdir -p /mydata/nacos/logs/

mkdir -p /mydata/nacos/init.d/ 

vim /mydata/nacos/init.d/custom.properties

日志映射文件夹和配置
配置文件内容:(配置好自己的mysql信息)

server.contextPath=/nacos
server.servlet.contextPath=/nacos
server.port=8848

spring.datasource.platform=mysql
#配置持久化数据库相关信息 ####################################################
db.num=1
db.url.0=jdbc:mysql://xxx.xxx.xxx.x:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=root
##########################################################################

nacos.cmdb.dumpTaskInterval=3600
nacos.cmdb.eventTaskInterval=10
nacos.cmdb.labelTaskInterval=300
nacos.cmdb.loadDataAtStart=false
management.metrics.export.elastic.enabled=false
management.metrics.export.influx.enabled=false
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D %{User-Agent}i
nacos.security.ignore.urls=/,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/v1/auth/login,/v1/console/health/**,/v1/cs/**,/v1/ns/**,/v1/cmdb/**,/actuator/**,/v1/console/server/**
nacos.naming.distro.taskDispatchThreadCount=1
nacos.naming.distro.taskDispatchPeriod=200
nacos.naming.distro.batchSyncKeyCount=1000
nacos.naming.distro.initDataRatio=0.9
nacos.naming.distro.syncRetryDelay=5000
nacos.naming.data.warmup=true
nacos.naming.expireInstance=true

运行run 

docker run -d -p 8848:8848 -p 9848:9848 -p 9849:9849 --name nacos --privileged=true --restart=always -e JVM_XMS=256m -e JVM_XMX=256m -e MODE=standalone -e PREFER_HOST_MODE=hostname -v /mydata/nacos/logs:/home/nacos/logs -v /mydata/nacos/init.d/custom.properties:/home/nacos/init.d/custom.properties --restart=always nacos/nacos-server

 访问地址进入控制台xxx.xxx.xxx.x:8848/nacos

 服务注册:引入依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

配置文件: 

类似的方式启动了cart服务

nacos服务列表:

 openfeign便捷调用服务:

新建模块hm-api引入依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

 创建client:

  1. @FeignClient("item-service")
  2. public interface ItemClient {
  3. @GetMapping("/items")
  4. List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids);
  5. }

 返回类:

  1. package com.hmall.api.dto;
  2. import io.swagger.annotations.ApiModel;
  3. import io.swagger.annotations.ApiModelProperty;
  4. import lombok.Data;
  5. @Data
  6. @ApiModel(description = "商品实体")
  7. public class ItemDTO {
  8. @ApiModelProperty("商品id")
  9. private Long id;
  10. @ApiModelProperty("SKU名称")
  11. private String name;
  12. @ApiModelProperty("价格(分)")
  13. private Integer price;
  14. @ApiModelProperty("库存数量")
  15. private Integer stock;
  16. @ApiModelProperty("商品图片")
  17. private String image;
  18. @ApiModelProperty("类目名称")
  19. private String category;
  20. @ApiModelProperty("品牌名称")
  21. private String brand;
  22. @ApiModelProperty("规格")
  23. private String spec;
  24. @ApiModelProperty("销量")
  25. private Integer sold;
  26. @ApiModelProperty("评论数")
  27. private Integer commentCount;
  28. @ApiModelProperty("是否是推广广告,true/false")
  29. private Boolean isAD;
  30. @ApiModelProperty("商品状态 1-正常,2-下架,3-删除")
  31. private Integer status;
  32. }

 购物车服务引入依赖:

<dependency>
    <groupId>com.heima</groupId>
    <artifactId>hm-api</artifactId>
    <version>1.0.0</version>
</dependency>

启动类添加注解 

@EnableFeignClients(basePackages = "com.hmall.api.client")

 业务调用

  1. private final ItemClient itemClient;
  2. private void handleCartItems(List<CartVO> vos) {
  3. // 1.获取商品id
  4. Set<Long> itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toSet());
  5. List<ItemDTO> items = itemClient.queryItemByIds(itemIds);
  6. // 3.转为 id 到 item的map
  7. Map<Long, ItemDTO> itemMap = items.stream().collect(Collectors.toMap(ItemDTO::getId, Function.identity()));
  8. // 4.写入vo
  9. for (CartVO v : vos) {
  10. ItemDTO item = itemMap.get(v.getItemId());
  11. if (item == null) {
  12. continue;
  13. }
  14. v.setNewPrice(item.getPrice());
  15. v.setStatus(item.getStatus());
  16. v.setStock(item.getStock());
  17. }
  18. }

三、网关登录校验

创建网关模块,引入springcloud的网关依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

 配置网关转跳路由和过滤器,我的网关端口为8090
uri:lb://nacos中服务的名字
predicates: 服务接口路径
filters: 官方提供的过滤器或自定义过滤器

自定义过滤器有两种GatewayFilterFactory和GlobalFilter,前者可以设置单个服务过滤,也可以设置全局过滤,后者创建完后自动生效全局过滤实现更加简单。

启动,测试

登录校验过滤器实现:将过滤校验所需的配置类和工具类转移到网关

配置jwt和无需过滤的接口路径

  1. @Component
  2. @RequiredArgsConstructor
  3. public class AuthGlobalFilter implements GlobalFilter, Ordered {
  4. private final AuthProperties authProperties;
  5. private final JwtTool jwtTool;
  6. private final AntPathMatcher antPathMatcher = new AntPathMatcher();
  7. @Override
  8. public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  9. ServerHttpRequest request = exchange.getRequest();
  10. //检查接口是否无需过滤,是则放行
  11. if(isExclude(request.getPath().toString())){
  12. return chain.filter(exchange);
  13. }
  14. //登录校验
  15. String token = null;
  16. List<String> authorization = request.getHeaders().get("authorization");
  17. if(authorization != null && !authorization.isEmpty()){
  18. token = authorization.get(0);
  19. }
  20. Long userId ;
  21. try {
  22. userId = jwtTool.parseToken(token);
  23. } catch (Exception e) {
  24. //如果无法生成userId则说明没登录,返回401
  25. ServerHttpResponse response = exchange.getResponse();
  26. response.setStatusCode(HttpStatus.UNAUTHORIZED);
  27. return response.setComplete();
  28. }
  29. //如果登录了,则把userId放入请求头发送给接口服务,以便服务需要用户信息
  30. ServerWebExchange newExchange = exchange.mutate().request(builder -> builder.header("user-info", String.valueOf(userId))).build();
  31. return chain.filter(newExchange);
  32. }
  33. //判断路径是否无需过滤
  34. private boolean isExclude(String path) {
  35. List<String> excludePaths = authProperties.getExcludePaths();
  36. for (String excludePath : excludePaths) {
  37. if (antPathMatcher.match(excludePath, path)) {
  38. return true;
  39. }
  40. }
  41. return false;
  42. }
  43. //过滤器优先级,越小则越高
  44. @Override
  45. public int getOrder() {
  46. return 0;
  47. }
  48. }

 在common中编写拦截器获取userId

  1. public class UserInfoInterceptor implements HandlerInterceptor {
  2. //请求前将userId存入
  3. @Override
  4. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  5. String userId = request.getHeader("user-info");
  6. if(StrUtil.isNotBlank(userId)){
  7. UserContext.setUser(Long.parseLong(userId));
  8. }
  9. return true;
  10. }
  11. //出请求后删除userId
  12. @Override
  13. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  14. UserContext.removeUser();
  15. }
  16. }

 这样就实现了网关登录校验并且将用户信息传递给其他服务,但其他服务互相调用时还是不会传递用户信息。
 所以我们需要在服务之间发送http请求是带上用户信息的请求头。

借助feign提供的拦截器在发送请求前添加用户信息的请求头:

  1. public class DefaultFeignConfig {
  2. @Bean
  3. public RequestInterceptor userInfoRequestInterceptor(){
  4. return new RequestInterceptor() {
  5. @Override
  6. public void apply(RequestTemplate requestTemplate) {
  7. Long user = UserContext.getUser();
  8. if(user != null)
  9. requestTemplate.header("user-info", user.toString());
  10. }
  11. };
  12. }
  13. }

 四、nacos配置管理

引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

登录nacos后台添加配置

spring:

datasource:

url: jdbc:mysql://${hm.db.host}:${hm.db.port:3306}/${hm.db.database}}?characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai

driver-class-name: com.mysql.cj.jdbc.Driver

username: root

password: ${hm.db.pw}

mybatis-plus:

configuration:

default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler

global-config:

db-config:

update-strategy: not_null

id-type: auto

 编写bootstrap.yml
该文件读取在application.yml之前用于读取nacos中的配置文件

application.yml:

 

启动查看日志:

 成功拉取配置文件 。

配置热部署:

1.@ConfigurationProperties

  1. @Data
  2. @Component
  3. @ConfigurationProperties(prefix = "hm.cart")
  4. public class CartProperties {
  5. private Integer maxItems;
  6. }

2.@RefreshScope + @Value

  1. @Data
  2. @Component
  3. @RefreshScope
  4. public class CartProperties {
  5. @Value("${hm.cart.maxItems}")
  6. private Integer maxItems;
  7. }

nacos配置:

五、服务保护(sentinel) 

下载:Release v1.8.7 · alibaba/Sentinel · GitHub

下载完成后可以直接在本地java -jar 运行。 

官方中文文档:

introduction | Sentinel

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar

 访问ip:8088

 账号:sentinel 密码:sentinel

服务yaml配置

spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080
      eager: true
      #请求方法前缀
      http-method-specify: true
#feign整合sentinel,用于管理服务间请求
feign:
  sentinel:
    enabled: true

启动项目并访问任意一个端口。

 控制接口限流:

 线程隔离:

熔断:

超出限流Fallback处理:

  1. @Slf4j
  2. public class ItemClientFallbackFactory implements FallbackFactory<ItemClient> {
  3. @Override
  4. public ItemClient create(Throwable cause) {
  5. return new ItemClient() {
  6. @Override
  7. public List<ItemDTO> queryItemByIds(Collection<Long> ids) {
  8. log.error("查询异常", cause);
  9. return Collections.emptyList();
  10. }
  11. @Override
  12. public void deductStock(List<OrderDetailDTO> items) {
  13. throw new RuntimeException(cause);
  14. }
  15. };
  16. }
  17. }

  1. public class DefaultFeignConfig {
  2. @Bean
  3. public ItemClientFallbackFactory itemClientFallbackFactory(){
  4. return new ItemClientFallbackFactory();
  5. }
  6. }

设置qps为1,一秒只接收一次请求,方便测试。

进入swagger调试:

一秒内第一次:

一秒内第二次: 

后端:

 sentinel配置持久化 (使用nacos配置)

引入对呀sentinel版本的依赖

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
    <version>1.8.6</version>
</dependency>

nacos创建配置文件sentinel.json配置:

[

 {

  "resource": "GET:/carts",

  "count": 200.0,

  "grade": 0,

  "slowRatioThreshold": 0.5,

  "timeWindow": 10

 }

]

 添加springboot配置sentinel下:

datasource:
  ds2:
    nacos:
      server-addr: xxx.xxx.xxx.xxx:8848
      data-id: sentinel.json
      group-id: DEFAULT_GROUP
      data-type: json
      rule-type: degrade

重启服务 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/536581
推荐阅读
相关标签
  

闽ICP备14008679号