这几天忙着在做另一个客户的定制项目,所以SAAS没有进展,也因为没有进展,所以多了一些时间进行思考,发现以前的想法有一些问题。也有了新的解决方案。
使用Dcat Admin多后台
之前计划是将每一个租户应用后台都新建一个Dcat的多后台进行部署。并且用户后台也使用多后台的其中之一个后台。
但这种做法有很多弊端。如下:
租户应用之间的耦合太严重。
每个租户应用都是一个dcat的多后台之一,就会造成,所有的租户应用后台全部在一个laravel之内,甚至全部在一个Dcat Admin应用内。掺杂在一起,非常不方便后期升级和部署租户应用以及中央应用。
部分租户应用未必会使用Dcat Admin。
Dcat Admin是一个优秀的快速后台扩展,但这也不意味着任何场景下都会使用它,也就是说,如果一个新的租户应用并没有使用Dcat Admin作为后台,那么之前用dcat多后台来部署每一个租户应用的这种想法就无法实施下去。
不利于后期平台的扩展。
我并不能保证我的saas一定会顺利运营下去并且成功盈利,甚至,我目前都抱着大概率会失败的心理预期来做这个项目。假如我的第一个,甚至前几个租户应用,都不如人意。那么我可能还将会继续开发第三个,第四个,第五个新的租户应用继续集成在这个saas框架内。届时,如果使用dcat多后台,我在部署后面新的租户应用的时候,还不得不去照顾前面已经失败的几个项目。这肯定有问题。
另外,我的这个SAAS平台,如果所有的租户应用都由我以及我的团队自己来开发,那么一年也开发不了几个租户应用。如果平台本身架构合适,我会希望召集很多已经拥有自己laravel作品的开发者,将自己的作品放置在我们的saas平台下进行运营。所以之前我使用Dcat Admin多后台的架构,也不适合我当前的这个想法。
—
架构改进
针对上面的问题,也和 @苏有才 沟通了下,这是我们目前远程合作团队的伙伴,我对架构重新做了梳理。解决了上面的所有问题。具体架构如下:
租户应用单独部署
我们使用的SAAS扩展是 stancl/tenancy
,(中文文档:http://doc.wyz.xyz/tenancy/1/0-introduction),这个扩展的机制是用户在注册并且产生租户应用的时候,会自动给用户分配一个子域名。但是当用户在完成这一步的时候,事实上和租户应用还没什么交互,仅仅是对租户应用执行了数据库迁移,除此之外,此时此刻和租户应用是0交互。也就是说,用户注册的时候,系统根本不会理会你的租户应用这时候在哪里。
所以我们完全可以将租户应用单独部署在一个新的站点内,和你平时部署一个新的laravel站点一摸一样。然后只需要解决一下几个问题即可。
让用户注册后生成的子域名,直接访问租户应用
这个其实很好做到。我们只需要将符合用户域名的泛域名解析到独立的租户应用站点即可。
有的人可能会稍微疑惑,如果租户应用有很多个,那么怎么判断用户的域名访问哪个租户应用呢?比如访问的是CRM还是ERP呢?
这个也不难,在用户初次注册SAAS站点,应且选择应用的时候,我们就会在SAAS的租户表内记录这个租户绑定的应用标识。
用户注册SAAS并且创建租户应用,如何进行数据库迁移?
这是个问题。因为目前咱们的saas站点,和租户站点,其实是完全不同的两个独立站点。用户在saas站点创建应用,怎么去寻找另外一个站点内的数据库迁移文件并且执行?
我的想法是,因为SAAS站点,和租户站点,虽然是两个不同的站点,但是都在同一台服务器,那么SAAS在用户开通租户的时候,选择数据库迁移文件夹的时候,是否可以通过相对路径来将执行数据库迁移的路径指向到租户站点呢?
这个我没试过。不知道能不能做到?另外,也不知道以后站点升级的时候,我们在使用stancl/tenancy
扩展内置的升级租户应用的方法,是否还适用于我们这种架构?
访问租户域名,怎么寻找当前租户的数据库连接?
假设上一个数据库迁移的问题我们已经解决,那么这时候按道理是可以通过租户域名访问到租户站点。但是因为每个租户生成一个单独数据库,那么系统怎么去寻找当前租户的数据库是哪个呢?
因为我们的租户应用是独立部署的站点,saas站点寻找相应数据库的这套逻辑,在我们的租户站点内并不适用。因为是完全不同的两个站点,彼此没一点关系。SAAS扩展的一些方法,在我们租户站点内根本无效。而且这时候,我们的租户站点的数据库连接方式是在 .env
或者config
里面定义的,我们的数据库用户名和密码都可以直接写死为mysql管理员的账号密码,比如root。但是怎么通过用户访问的域名,去寻找对应的数据库名称呢?这个也和 @苏有才 沟通过,它的办法是通过域名识别可以做到。
目前我还没有深入思考这一点,但有几点疑惑,假如通过访问域名来寻找当前租户的数据库,那么每次访问都需要先处理一下寻找数据库的逻辑,这是不是会造成一些性能问题?
另外是,通过域名直接找到数据库名,说明域名和数据库名称之间有个固定的匹配规则,那么这种规则如果被人知道了,别人也很容易知道这个站点的数据库名称叫什么,是否安全?
最后一个需要处理的问题:SAAS站点的一些信息,如何带进租户站点?
比如用户在SAAS平台的后台内,将这个租户应用的套餐,从普通套餐升级到豪华套餐,那么租户站点如何知道当前租户是豪华套餐?也就是说,需要在租户应用内,拿到SAAS站点内的一些数据。
@苏有才 给的解决方式,是通过api接口传递。所以如此看来,这个问题也就解决了。
结语
如果上面这几个问题都能解决掉,那么这个SAAS的架构就非常自由,并且部署和升级几乎毫无耦合。租户站点随时可以独立升级。不用考虑SAAS站点的事情。
而且只要是任何使用laravel开发的站点(因为需要用到数据库迁移这个功能),几乎都可以直接扔到我们的平台内作为租户应用提供给用户使用。
目前看来我认为这种做法非常完美。当然局限于我的技术水平,可能有很多我没发现的隐患或者问题,欢迎各位技术大牛在下面回复指出来。一起探讨。