自我尝试微服务拆分的过程记录 - 详解
苍穹外卖拆分微服务(自我尝试第一期)
1.前期准备
因为没有前例供我参考,我只能自己摸着石头过河,所以备份重要,会使用git就会方便很多,以防你做错之后还要花大量时间去改回来。我都基本思路是把苍穹外卖,黑马点评,黑马商城融合到一块,整合出一个更强大的苍穹外卖。
2.技术选择
我这里选择spring cloud Alibaba,注册中心选用Nacos,服务调用选择Openfeign,服务保护选用sentienl,网关gateway,之后的中间件可能还要seata分布式事务管理,RabbitMQ消息中间件,可能会用到(elasticsearch),如果有时间有那个技术我再加个智能客服。
3.了解苍穹外卖的基本功能
公共模块(common)包含了项目的工具类
实体类模块(pojo)包含了项目所需的所有实体类
服务模块(server)重要的拆分对象,里面包含了系统运行的所有服务,主要有:
订单模块
分类套餐模块
商家模块
用户模块
控制台模块
购物车模块
4.怎么拆分
因为做过的时间太长了,具体的细节我不是记得很清楚了,所以我将控制台先放到了商家模块里,后面有需要我们在拆分
拆分后我大致分了这些模块:
原本的公共模块,实体模块我没有动
服务拆成了,商家模块,购物车模块,分类套餐模块,用户模块,订单模块
网关模块
把feign的客户端也单独抽出了一个模块(api模块)
5.拆分的过程
在主模块里创建新的模块,将服务对应的controller,service,mapper给分过去
将拦截器放到网关那部分,后期我们要用网关来统一拦截,拦截后会涉及用户信息传递的问题,后面到哪一步再说。
将像aop这种公共可用的放到common公共模块中,迁移过去记得修改扫描路径,使用通配符…类似
@Pointcut("execution(* com..mapper.*.*(..))(这一块我还没有实践不知道对不对,后面测试错了再讲)
各个模块的pom文件先将server的pom文件整块复制过去,后面做完我们再把没有用到的删除就好,记得把模块里的版本信息和名称改成对应模块的,方便我们后期在其他模块中引入,代码如下
<artifactId>sky-cart-service< /artifactId> <version>1.0-SNAPSHOT< /version>总的模块里加入新模块
代码如下:
<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.现状和后期打算
现在项目还启动不了,应该拆分时pagehelper出现了循环依赖的问题,我打算把mybatis换成mybatis-plus试一试
现在个服务间的调用还是模块的引用,要改成用fegin的方式
在网关的拦截器还没有做,后面把网关拦截器给做了
暂时现在就能想到这么多,后面我有进展了再更新

浙公网安备 33010602011771号