MeEdu 是基于 Laravel 开发的在线教育点播收费系统。您可以通过 MeEdu 开启您的在线教育事业。
本篇文章主要给小伙伴们介绍下MeEdu的微服务架构设计。首先,来看下MeEdu服务层的目录结构:
# ./app/Services
.
├── Base
│ ├── Interfaces
│ │ ├── CacheServiceInterface.php
│ │ ├── ConfigServiceInterface.php
│ │ └── RenderServiceInterface.php
│ ├── Providers
│ │ └── BaseServiceRegisterProvider.php
│ └── Services
│ ├── CacheService.php
│ ├── ConfigService.php
│ └── RenderService.php
├── Course
│ ├── Interfaces
│ │ ├── CourseCommentServiceInterface.php
│ │ ├── CourseServiceInterface.php
│ │ ├── VideoCommentServiceInterface.php
│ │ └── VideoServiceInterface.php
│ ├── Models
│ │ ├── Base.php
│ │ ├── Course.php
│ │ ├── CourseChapter.php
│ │ ├── CourseComment.php
│ │ ├── Video.php
│ │ └── VideoComment.php
│ ├── Providers
│ │ └── CourseServiceRegisterProvider.php
│ ├── Proxies
│ │ ├── CourseServiceProxy.php
│ │ └── VideoServiceProxy.php
│ └── Services
│ ├── CourseCommentService.php
│ ├── CourseService.php
│ ├── VideoCommentService.php
│ └── VideoService.php
├── Member
└── README.md
由于篇幅,上面省略掉了部分服务,不过重点的已经在里面了。微服务的架构设计从目录上面就能看出很多东西。
微服务
首先,我们先来了解下微服务到底是什么?下面是百度百科给出的解释:
微服务可以在“自己的程序”中运行,并通过“轻量级设备与HTTP型API进行沟通”。关键在于该服务可以在自己的程序中运行。通过这一点我们就可以将服务公开与微服务架构(在现有系统中分布一个API)区分开来。在服务公开中,许多服务都可以被内部独立进程所限制。如果其中任何一个服务需要增加某种功能,那么就必须缩小进程范围。在微服务架构中,只需要在特定的某种服务中增加所需功能,而不影响整体进程的架构。
总结来说,微服务就是讲复杂的应用进行拆分独立部署,高内聚,低耦合,配合DevOps实现快速敏捷迭代开发。
高内聚,低耦合
我想大家应该都有遇到过某些项目,这些项目的代码紧密的结合在一起,当看到代码之后,你脑子里面想的第一个词:“重构”。如果在项目开始之初,没有严格的规范和约束,随着业务范围的扩张和开发人员的变动,项目会越来越复杂,越来越臃肿,经过一段时间的积累之后,后来接手项目的人就苦逼了。
为了避免出现这样的问题,我们在设计项目的时候,就要考虑一个问题:“如何做到高内聚,低耦合?”
为了解决这个为,在传统的MVC架构下,引入了很多的解决方案,对代码进行分割,对系统代码和业务代码进行分离,但是啊,我们可以看到的是,这些其实作用并不是很大,随着产品需求的变更,原来一开始或许不错的代码会变得越来越糟糕,为什么会这样呢?是因为设计的不合理吗?其实也不是,我觉得最主要的原因就是代码写在一起了!没有做彻底的分离!
微服务的出现就不一样了,对系统进行服务服务划分之后,相应的开发人员负责自己的服务,它的代码范围就局限在自己的服务里面,这样就做到了高内聚,低耦合。更严格的情况下,不同的服务的数据库也是不一样的,这样就更加独立和自主了。
服务划分
微服务最重要的一点就是对系统进行服务划分,那怎么样的划分最为合理呢?服务的界限以什么为标准呢?
这其实没有具体的标准,服务划分的界限要考虑到很多东西,项目的架构,产品的业务范围,技术人员,维护等。所以,这个界限标准,只要你的团队都觉得合理,就可以了。但是有一点需要注意的是,服务并不是越细越好!
在MeEdu中,基于现有的功能,主要划分了下面几个服务:
| 服务 | 说明 |
| --- | --- |
| Base | 系统底层服务,主要有:缓存,配置服务等 |
| Member | 会员服务,负责 MeEdu 系统的会员注册/登录/找回密码/会员等级等 |
| Course | 课程服务,主要提供课程/视频在线观看 |
| Order | 订单服务,主要提供课程/视频/会员的在线购买服务 |
| Other | 其它服务,主要是系统的一些小功能,包括像:上传,短信发送等 |
服务注册/发布
微服务的架构当中,每个服务需要将自己注册到注册中心,这样消费者才可以消费服务。
MeEdu虽然是微服务的架构,但是毕竟没有做到彻底的服务分离,所以,所有的服务还是写在一个系统里面的。那么MeEdu的服务是怎么注册的呢?请看下下面的代码:
class CourseServiceRegisterProvider extends ServiceProvider
{
public function register()
{
$this->app->instance(CourseServiceInterface::class, $this->app->make(CourseServiceProxy::class));
$this->app->instance(VideoServiceInterface::class, $this->app->make(VideoServiceProxy::class));
$this->app->instance(CourseCommentServiceInterface::class, $this->app->make(CourseCommentService::class));
$this->app->instance(VideoCommentServiceInterface::class, $this->app->make(VideoCommentService::class));
}
}
MeEdu是基于Laravel开发的,在这里,我们将容器当做了服务的注册中心,在需要用到的服务的时候,我们在容器里面拿到我们想要的服务!
服务的治理
服务治理也是微服务架构设计中的一个必不可少的环节。在MeEdu的微服务设计中,也存在着服务治理的影子。我们将视线再次移到上面的服务注册代码中,我们可以看到 Course 和 Video 的注册服务后面都带有 Proxy 这个关键字!这里的 Proxy 就是实现服务治理的目的!来看下 CourseServiceProxy 的代码:
class CourseServiceProxy extends ServiceProxy implements CourseServiceInterface
{
public function __construct(CourseService $service)
{
parent::__construct($service);
$this->cache['getLatestCourses'] = function ($limit) {
return new CacheInfo('c:cs:lc:'.$limit, $this->configService->getCacheExpire());
};
$this->cache['chapters'] = function ($courseId) {
return new CacheInfo('c:cs:cc:'.$courseId, $this->configService->getCacheExpire());
};
}
}
CourseServiceProxy 实现了 CourseServiceInterface 接口,所以,它可以被注册到注册中心。这里我们需要关注下 ServiceProxy :
由于篇幅的原因,这里仅贴出核心的代码,全部代码可以到meedu的仓库查看。
public function __call($name, $arguments)
{
// 锁控制
if (isset($this->lock[$name])) {
return $this->lockHandlerBefore($name, $arguments);
}
// 限流
$this->limitHandler($name, $arguments);
// 缓存
$response = $this->cacheHandler($name, $arguments);
return $response;
}
上面的核心代码就是采用AOP设计思想实现了锁控制,限流,缓存等治理功能。
服务调用
这是最重要的一个环节,如果这个环节做不好,那么微服务的架构设计就没有意义了。许多项目就是因为代码之间的互相调用导致了代码越来越复杂,越来越看不懂。所以,限制服务之间的调用是必须要考虑的一点。
在MeEdu的微服务架构设计中,我们规定,Base 服务可以被其它任何服务调用,除了 Base 服务之外,禁止调用其它任何服务。只有这样严格的规定,才能做到真正的高内聚,低耦合。
服务之外的任何地方都可以任意的调用各种服务的方法,没有限制。
所有的服务禁止手动初始化,必须通过容器的方式拿到服务的实例对象。
总结
微服务架构远不止这么简单,真正做到微服务架构设计需要更多的专业知识和人力成本。MeEdu的微服务架构设计,目前仅仅是代码层面实现的架构设计,不过,在这个基础上,后期如果切换真正的微服务架构也是非常简单的。因为,路已经铺好了!
本作品采用《CC 协议》,转载必须注明作者和本文链接
开源教育系统https://meedu.vip