苍穹外卖微服务版(第一期)

苍穹外卖拆分微服务(自我尝试第一期)

1.前期准备

因为没有前例供我参考,我只能自己摸着石头过河,所以备份重要,会使用git就会方便很多,以防你做错之后还要花大量时间去改回来。我都基本思路是把苍穹外卖,黑马点评,黑马商城融合到一块,整合出一个更强大的苍穹外卖。

2.技术选择

我这里选择spring cloud Alibaba,注册中心选用Nacos,服务调用选择Openfeign,服务保护选用sentienl,网关gateway,之后的中间件可能还要seata分布式事务管理,RabbitMQ消息中间件,可能会用到(elasticsearch),如果有时间有那个技术我再加个智能客服。

3.了解苍穹外卖的基本功能
  1. 公共模块(common)包含了项目的工具类

  2. 实体类模块(pojo)包含了项目所需的所有实体类

  3. 服务模块(server)重要的拆分对象,里面包含了系统运行的所有服务,主要有:

    1. 订单模块

    2. 分类套餐模块

    3. 商家模块

    4. 用户模块

    5. 控制台模块

    6. 购物车模块

4.怎么拆分

因为做过的时间太长了,具体的细节我不是记得很清楚了,所以我将控制台先放到了商家模块里,后面有需要我们在拆分

拆分后我大致分了这些模块:

  1. 原本的公共模块,实体模块我没有动

  2. 服务拆成了,商家模块,购物车模块,分类套餐模块,用户模块,订单模块

  3. 网关模块

  4. 把feign的客户端也单独抽出了一个模块(api模块)

5.拆分的过程
  1. 在主模块里创建新的模块,将服务对应的controller,service,mapper给分过去

  2. 将拦截器放到网关那部分,后期我们要用网关来统一拦截,拦截后会涉及用户信息传递的问题,后面到哪一步再说。

  3. 将像aop这种公共可用的放到common公共模块中,迁移过去记得修改扫描路径,使用通配符…类似

    @Pointcut("execution(* com..mapper.*.*(..))
    

    (这一块我还没有实践不知道对不对,后面测试错了再讲)

  4. 各个模块的pom文件先将server的pom文件整块复制过去,后面做完我们再把没有用到的删除就好,记得把模块里的版本信息和名称改成对应模块的,方便我们后期在其他模块中引入,代码如下

    <artifactId>sky-cart-service</artifactId>
        <version>1.0-SNAPSHOT</version>
    
  5. 总的模块里加入新模块

    代码如下:

     <modules>
            <module>sky-gateway</module>
            <module>sky-user-service</module>
            <module>sky-product-service</module>
            <module>sky-order-service</module>
            <module>sky-cart-service</module>
            <module>sky-admin-service</module>
            <module>sky-common</module>
            <module>sky-pojo</module>
            <module>sky-api</module>
        </modules>
    
6.拆分结束后

再次强调一定备份

拆分结束后就可以将server模块给删除了,此时其他服务调用时还用的是模块的引用,我们后面可用改用fegin来调用

7.编写api模块

这里面放了所有的fegin的客户端,主要我们做两件事情,客户端,和服务降级

示例代码:

/**
 * 用户服务API接口
 */
@FeignClient(name = "sky-user-service", fallbackFactory = UserServiceFallbackFactory.class)
public interface UserServiceApi {

    /**
     * 根据id查询地址
     * @param id
     * @return
     */
    @GetMapping("/user/addressBook/{id}")
    Result<AddressBook> getById(@PathVariable Long id);

    /**
     * 查询默认地址
     * @return
     */
    @GetMapping("/user/addressBook/default")
    Result<AddressBook> getDefault();
}

/**
 * 用户服务降级实现类
 * 当用户服务不可用时,会调用此类中的方法返回友好提示
 */
@Component
public class UserServiceFallback implements UserServiceApi {

    /**
     * 根据id查询地址的降级处理
     * @param id
     * @return
     */
    @Override
    public Result<AddressBook> getById(Long id) {
        return Result.error("服务暂时不可用,请稍后再试");
    }

    /**
     * 查询默认地址的降级处理
     * @return
     */
    @Override
    public Result<AddressBook> getDefault() {
        return Result.error("服务暂时不可用,请稍后再试");
    }
}
/**
 * 用户服务降级工厂类
 * 可以在降级时获取到异常信息
 */
@Component
public class UserServiceFallbackFactory implements FallbackFactory<UserServiceApi> {

    /**
     * 创建降级实现类实例
     * @param throwable 异常信息
     * @return 降级实现类实例
     */
    @Override
    public UserServiceApi create(Throwable throwable) {
        // 可以记录异常信息,例如日志记录
        System.err.println("用户服务调用失败,异常信息:" + throwable.getMessage());
        // 返回降级实现类实例
        return new UserServiceFallback();
    }
}
/**
 * 全局Feign异常处理器
 * 用于统一处理Feign调用异常
 */
@Slf4j
@RestControllerAdvice
public class GlobalFeignExceptionHandler {

    /**
     * 处理Feign调用异常
     * @param e Feign异常
     * @return 异常信息
     */
    @ExceptionHandler(FeignException.class)
    public String handleFeignException(FeignException e) {
        log.error("Feign调用异常:{}", e.getMessage(), e);
        return "服务暂时不可用,请稍后再试";
    }
}

这里我采用了工厂模式来实现服务降级,整体的代码我都没有测试,还在摸索阶段

8.现状和后期打算
  1. 现在项目还启动不了,应该拆分时pagehelper出现了循环依赖的问题,我打算把mybatis换成mybatis-plus试一试

  2. 现在个服务间的调用还是模块的引用,要改成用fegin的方式

  3. 在网关的拦截器还没有做,后面把网关拦截器给做了

暂时现在就能想到这么多,后面我有进展了再更新

你可能感兴趣的:(学习记录,微服务,架构)