# xiao-store-cloud **Repository Path**: myxiao/xiao-store-cloud ## Basic Information - **Project Name**: xiao-store-cloud - **Description**: Spring Cloud 项目 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2018-12-25 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### 架构全靠一个人瞎折腾,如有不合理之处,还请告知 ##### QQ群:167409303 ### 相关技术 - Spring Boot - Spring Boot Admin - Spring cloud 全家桶 (OAuth2 + Config + Bus + Sleuth) - Spring Cloud Netflix 全家桶 (Eureka + Zuul + Feign + Ribbon + Hystrix + Turbine) - JSON Web Token(JWT) - ZipKin - RabbitMQ - MyBatis - Redis - Mysql - Thymeleaf ### 基础版本 - SpringBoot-2.0.4.RELEASE - SpringCloud-Finchley.SR1 ### 微服务模块和端口 微 服 务 | 作 用 | 端 口 -----|-----|----- xiao-store-eureka | 注册中心 | 8761 xiao-store-jwt-zuul | 使用jwt实现的zuul | 6650 xiao-store-web-portal | 首页 | 7200 xiao-store-web-cart | 购物车 | 7400 xiao-store-web-order | 订单 | 7600 xiao-store-service-googs | 商品微服务 | 7100 xiao-store-service-cart | 购物车微服务 | 7300 xiao-store-service-order | 订单微服务 | 7500 xiao-store-config-server | 配置中心 | 8400 xiao-store-monitor | 断路监控,trubine | 8500 zipkin-server | 数据链路(官方提供) | 9411 xiao-jwt-service | 用户服务 | 8700 ### 其他 项目名 | 作 用 | ------|----- xiao-store-common | 公共模块 | xiao-store-feign-client | feign接口 store-config | 所有配置文件 store-file | 所有静态文件 xiao-store-common-mapper | 公共mapper 静态文件使用nginx提供服务,端口号7000,根目录文件名store-file 正常来说,feignclient是由服务调用者自己实现,因为不同的微服务可能会调用同一个其他微服务,所以本实例打包到统一的jar包。 ### 未使用或未完成 微 服 务 | 作 用 | 端 口 | 备注 ------|-----|----|--- xiao-store-admin | 监控中心 | 8600 | 开发中 xiao-store-monitor | 断路器监控 | 8500 | 配合admin使用未实现,turbine端点可查看数据 xiao-store-zuul | 服务网关 | 6600 | 用xiao-store-jwt-zuul实现 xiao-store-zuul2 | 服务网关 | 6610 | 请求重试,幂等等测用 xiao-store-manage | 后台管理 | 8000 | 未实现 xiao-store-book | 服务 | 7900 | 请求重试,幂等等测用 使用xiao-jwt-service实现用户注册,代替xiao-auth-service和xiao-user-service 本项目的两个个核心服务order,cart服务和页面展示是完全分离的。对应的web服务,只是作为前端展示部分,完全可以使用纯html+js实现,实现前后端分离。 其他的项目也可以进行拆分实现前后端分离。 ### 开发中遇到的一些问题 - xiao-store-zuul的com.netflix.zuul.exception.ZuulException:Forwarding error 一开始通过网关请求微服务的时候,报异常,添加了 ``` ribbon: ReadTimeout: 60000 ConnectTimeout: 60000 hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000 ``` 任然报错最后在zuul中实现了ZuulFilter过滤器接口后,请求正常。 另外一种情况是eureka刚启动,就调用微服务出现该异常,可能的情况是微服务还没有来得及注册到eureka引起,可以稍等一会再试,一般问题可消失。 在使用oauth2后,zuul转发请求时,header中的Authorization信息会丢失,是因为zuul在转发时,会过滤掉zuul中的一些信息,比如Authorization和Cookie, 那么我们可以在zuul的过滤器中重新定义header头的内容,规避zuul的过滤,但是比较麻烦。此处采用简单的方式 ``` zuul.sensitive-headers= ``` 指定内容为空,就好。对所有的路由都有效。一个更好的方式是为每个路由单独指定 ``` zuul.routes..sensitive-headers= zuul.routes..custom-sensitive-headers=true ``` - 通过feign请求微服务时,参数值丢失的问题 定义以下接口 ``` @RequestMapping(value = "/query/{uid}",method = RequestMethod.GET) Cart query(@PathVariable("uid") Long uid); ``` 请求该接口时uid参数值会丢失,最终使用POST请求解决。正确的代码为: ``` @RequestMapping(value = "/query",method = RequestMethod.POST) Cart query(@RequestParam("uid") Long uid); ``` 在不同的版本中,上面的问题表现结果不尽相同,下面的写法肯定是万无一失的。 在Spring中,可以使用springmvc的注解定义feign,但最好的方式是使用标准的注解形式,不要省略任何注解字段,如@RequestParam,value等,使用POST请求。 - oauth2-service中,如果使用的是springboot+spring cloud E版本,在DefaultTokenServices对象创建是不能直接new,否则会报出现多个DefaultTokenServices对象 的错误,因为在oauth框架中已经定义了两个不同的实现Bean,我们只需要决定使用哪个即可 ``` @Primary @Bean public DefaultTokenServices tokenServices() { final DefaultTokenServices defaultTokenServices = new DefaultTokenServices(); defaultTokenServices.setTokenStore(tokenStore()); return defaultTokenServices; } ``` - user-service中 如果项目启动时,报错创建jwtAccessTokenConverter错误,http 401时,请检查yml中jwt.key-uri是否为oauth-service指定的地址(端口) - bootstrap.yml和application.yml bootstrap是引导的意思,顾名思义,bootstrap.yml是作为引导加载真正配置文件的文件,所以config-server的信息应该放在这里面。 一般系统级别固定不变的可写在botstrap.yml中。 如果每个服务有pro,dev和test各种环境,那么放在一个文件夹下管理不方便,所以按照服务分文件夹进行区分,那么在config-server的配置中需要体现出来 ``` git: uri: https://gitee.com/myxiao/xiao-store-cloud search-paths: store-config/{application} ``` - 配置中心 开发条件限制,没有使用bus的自动刷新功能,但是可以通过端点进行手动刷新。 如果spring-cloud-starter-bus-amqp依赖是注释掉的,那么只能通过对每个实例进行单独刷新,如果没有 就可以对相同类型的微服务其中一个进行刷新,其他实例也能刷新。 以xiao-store-service-goods为例,选取其中一个刷新 POST http://localhost:7100/actuator/bus-refresh 使用bus-ampq只需要刷新一次,不使用就需要对每个微服务进行单独刷新 - 服务链路追踪 zipkin zikpin的服务端直接使用官方提供的可执行jar,这也是官方推荐的方式 https://zipkin.io/pages/quickstart.html 本文使用jar包的方式,版本是2.11.12,启动方式和boot的jar包启动一样,java -jar xxx.jar 如果需要配置数据库和其他参数,那么可以创建一个启动脚本,run.bat,启动该脚本即可。 ``` @ECHO OFF ::set RABBIT_ADDRESSES=192.168.3.19:5672 ::set RABBIT_USER=rabbitadmin ::set RABBIT_PASSWORD=123456 set STORAGE_TYPE=mysql set MYSQL_HOST=localhost set MYSQL_TCP_PORT=3306 set MYSQL_USER=root set MYSQL_PASS=wksql6108 set MYSQL_DB=xiao-store set MYSQL_USE_SSL=false set JAVA_OPTS="-XX:ReservedCodeCacheSize=64m" java -jar zipkin-server-2.11.12-exec.jar ``` 数据库sql脚本见zipkin.sql文件(如果不做持久化可以不需要) 启动成功后可以看到默认端口是9411,进入localhost:9411即可,由于采样率的原因,不是每次请求都能被记录,可以多次重复请求查看效果。 #重试的问题 xiao-store-zuul,xiao-store-book,是重试的测试项目,如果post,put请求进行重试需要解决幂等的问题,可以在zuul的filter中对每个请求添加一个请求 id,这个id保存到redis,过期时间同zuul超时时间,实例读取id,如果存在,就是新的请求,如果不存在就是重试的请求。 每个接口解决幂等的问题? 商品秒杀可参考另外一个项目:https://gitee.com/myxiao/shopseckill