50万奖金+官方证书,深圳国际金融科技大赛正式启动,点击报名 了解详情
写点什么

Composer 结合 Git 创建 “服务类库”

  • 2019-09-15
  • 本文字数:2432 字

    阅读完需:约 8 分钟

Composer 结合 Git 创建 “服务类库”

我一直认为,现在的 PHP 已经进展到了工程化的领域。以前的 PHP 开发者,以快为美,速度和规模永远都是矛盾体。现在的 PHP 项目,特别是稍微大型一点的项目中,已经在逐渐演化成为需要兼顾工程化和规模化的层次了。一个代码工程化,就意味着演化为逐渐复杂的架构。复杂的架构,微服务往往就是一个很好的选择。

我在最近的一个项目中,就需要这个问题。我需要开发一个地图服务,这个服务当然不是简单的类库形式,而是有自己的数据库,自己的服务接口。这种情况其实最优的选择就是服务化。服务化的方式当然有很多了,Thrift,Http 等。但是我评估了下当前的部门环境,PHP 是主流的语言,加上自己这个项目的进度也比较紧,在我眼中,Thrift,Http 等方式都是使用网络协议实现服务的解耦合,这在我看来已经是重度解决方案了。我觉得在项目没有明确清晰病入膏肓的情况下是没有必要这种方式的。使用网络协议服务化的劣势在于引入了强大的复杂度。这个复杂度往往意味着人力,物力,时间上的投入。所以我希望,能够提供一个 PHP 语言的 “服务类库” 的形式进行开发。

我想到的就是 PHP 的 Composer。

Composer 的修改

创建服务类库

首先,我需要把我的 “服务类库” 从我的应用程序(起名为 xxx/main1)中独立出来,这个独立,我不是选择在应用程序中创建一个目录(事实我想过创建一个诸如 Services 的目录)。但是,如果和业务程序在代码上耦合起来,我觉得以人的惰性,很难从始至终都控制住自己能坚持不使用应用程序中方便的各种函数。所以我的选择是在 Git 库中新创建一个项目,起名为 xxx/mapService 。

composer.json

现在两个 Git 项目(xxx/main1 和 xxx/mapService),我在 main1 中的 composer.json 文件中增加下面的语句:


"require": {        "xxx/mapService" : "dev-master"},"repositories" : [       {                "type": "vcs",        "url" : "git@git.xxxx.com:cloud/mapService.git"    } ],
复制代码


而在 mapService 的 composer.json 如下:


{  "description": "xxxxxx",  "name": "xxx/mapService",  "type": "library",  "authors": [      {          "name": "Yejianfeng",          "email": "yejianfeng@xxxx.com"      }  ],  "require": {      "php": ">=5.2.4",      "illuminate/database" : "*"  },  "autoload": {      "psr-4": {          "xxxx\\xxxx\\MapService\\": "src"      }  } }
复制代码


这个配置告诉 main1 项目,mapService 的 Git 地址,需要使用的版本。


当然需要注意下面几点:


  • dev-master 意思是直接使用 mapService 的 master 分支。如果 mapService 有其他的 tag,这里完全可以使用 tag 信息

  • repositories 是说明项目的地址

  • 我这里的这个服务是放在我们公司自己搭建的 GitLab 上的

  • mapService 下面的 src 文件夹的命名空间为 xxxx\xxxx\MapService\ 并且支持 PSR-4

  • mapService 使用了 illuminate/database


最后使用 composer update -vvv 可以把我们需要的 mapService 下载下来放在 vendor 目录下。

更新修改

我们现在编辑器在 main1 项目中,如果我们有对 mapService 这个项目有进行编辑修改,并且希望合并到 mapService 的 master 分支的化,就直接进入 vender/xxx/mapService 目录,进行 Git 对应的操作。这样就可以进行直接的代码修改了。

独立配置

这种结构的组合方式只是完成了万里长征的第一步。后续更为重要的是在编写这个服务的时候,我需要时刻记住不使用 main1 的所有东西,这样才能保持 mapService 的独立性(独立性是服务化的必要条件之一)。比如我第一个遇到的问题就是配置文件需要独立。


我的实现方式是直接在 mapService 中创建一个 Config 类,这个类中直接写死配置。


这里一直觉得这个配置文件的实现方式有点挫,因为这样,这个配置文件就进入到了 Git 库。但是确实没有想到更好的方案了。Laravel 中有通过实现 ServiceProvider 将 Config 创建在 Laravel 的 config 文件夹下的方式,但是这种方式仅仅只适用于 Laravel。没有通用性。在另外一个方向,我想服务使用哪个数据库这个本身也是服务的一部分,放在服务的 Git 库中貌似也没有什么。

目录结构


目录结构如上


  • Configs 提供配置文件

  • Contracts 提供接口协议

  • Exceptions 提供异常

  • Supports 提供第三方方法或者类库

  • Models 提供对数据库的交互

  • Node.php 实现具体的接口


服务最重要的事情是接口协议。所以创建一个 Contracts 文件夹,将提供的服务接口化。


interface NodeInterface
{
/*
* 获取某个城市某个坐标点某个范围内的nodes
* @params int $cityId 城市id
* @params int $lat 纬度
* @params int $lng 经度
* @params int $distance 坐标点范围,单位:米
*
* @return array(Models/Node)
*
* @throws
*/
public function gets($cityId, $lat, $lng, $distance);
}
复制代码


接口的异常处理尽量使用异常,而不是错误码的方式进行交互。而且这些异常尽量要自定义。这样,在上层就有了统一处理的可能性。

思考

这个架构模式我定位为 PHP 代码层面服务化的模式。适用的场景应该是:


  • 后期计划服务化

  • 前期人力和思维都希望维持快速开发

  • 的场景

和 Git 的 SubTree 、SubModule 的区别

其实这三种方式说到底都是将一个项目作为另外一个项目的类库来使用的。SubTree 和 SubModule 是 Git 的解决方案。而 Composer 是 PHP 语言的解决方案,它除了将某个项目加入到另外一个项目的功能之外,还提供了加入版本,依赖解决等方案。如果你的项目是 PHP 的,那么无疑,使用 Composer 是更优的选择。

后期协议服务化

如果后期我的这个 mapService 想要协议服务化,那么这个 mapService 项目就可以简化成为一个 SDK,对于上层业务逻辑,只需要使用 composer update 进行更新就行。

服务注册和发现

我这里所谓的 “服务类库” 确实没有解决服务注册的问题,我无法知道到底有几个项目使用了我的服务。这个可能需要额外的流程的工作了。


本文转载自公众号滴滴技术(ID:didi_tech)。


原文链接:


https://mp.weixin.qq.com/s/6rKaqRgttESAB57tUiCpvg


2019-09-15 23:17716

评论

发布
暂无评论
发现更多内容

Grafana 最新开源项目 Phlare 速体验

Grafana 爱好者

云原生 可观测性 Grafana 11月月更

易观千帆 | 2022年9月银行APP月活跃用户规模盘点

易观分析

金融 手机银行

Java中的static关键字详解

共饮一杯无

Java 关键字 11月月更

云原生系列四:Yelp 如何在 Kubernetes 上运行 Kafka

叶秋学长

kafka Kubernetes 云原生 11月月更

SQL 碎碎念,你可能用不到但不能不知道的数据库技巧(2)

百里丶落云

数据库 后端 11月月更

QUIC不是TCP的替代品

俞凡

TCP 网络 QUIC

Vue组合式函数(二)封装一个请求

Augus

Vue3 11月月更

JavaScript基本数据类型和引用数据类型详解

肥晨

js 11月月更 数据结构js

pyside6 qml 支持更新液位的伪3D圆柱

Mr_No爱学习

超全!前端面试题大汇总

肥晨

前端面试题 11月月更 超全前端面试题

Redis 的 Sentinel 系统

月明风清

redis Sentinel 系统 哨兵机制

微服务架构组件总结篇

邱学喆

负载均衡 Spring Cloud 注册中心 配置中心 熔断服务

Java中的内部类与匿名内部类详解

共饮一杯无

Java 内部类 11月月更 匿名内部类

随机森林-概述

烧灯续昼2002

Python 机器学习 算法 sklearn 11月月更

下一代TCP: 网络演进的平台

俞凡

TCP 网络

SQL Sever提供的字符串类型

乔乔

11月月更

去哪儿的常态化容量保障是怎么做的?

TakinTalks稳定性社区

架构实战营模块 4 作业

陌生流云

#架构实战营

不借助 Fiori client,直接在手机浏览器里调用 SAP UI5 BarcodeScanner 实现条形码扫描的可能性?

汪子熙

sdk SAP Fiori SAP UI5 11月月更

学生管理系统考试试卷存储方案设计

乖乖IvyShine

从3开始,在业务系统中增加分页功能

闫同学

go语言 11月月更 后端系统

【LeetCode】爱生气的书店老板Java题解

Albert

算法 LeetCode 11月月更

从零到一带你构建可靠的大型分布式系统,不愧是IT领域又一神作!

Java永远的神

Java 分布式 程序人生 后端 架构师

还担心接口乱糟糟?快来试试“斯瓦格”在线文档管理平台!

wljslmz

华为云 接口管理 swagger 11月月更

Go语言入门13—并发

良猿

Go golang 后端 开发 11月月更

图片懒加载

源字节1号

软件开发

简单剖析开发:区块链杠杆合约交易所的核心优势

W13902449729

区块链交易所 合约交易所开发

美图是如何搭建压测监控一体化平台的?

TakinTalks稳定性社区

压测平台

HTML学习笔记(二)

lxmoe

html 前端 学习笔记 11月月更

【愚公系列】2022年11月 微信小程序-Request网络请求的封装

愚公搬代码

11月月更

【kafka运维】TopicCommand运维脚本

石臻臻的杂货铺

kafka Kafka实战 kafka运维 11月月更

Composer 结合 Git 创建 “服务类库”_文化 & 方法_轩脉刃_InfoQ精选文章