ernst-lee / laravel-tars
Laravel Tars
Requires
- guzzlehttp/guzzle: ^7.0.1
- illuminate/console: ~8
- illuminate/contracts: ~8
- illuminate/support: ~8
- laravelista/lumen-vendor-publish: ~8
- phptars/tars-deploy: ~0.1
- phptars/tars-log: ~0.1
- phptars/tars-server: ~0.6
- phptars/tars2php: ~0.3
- vlucas/phpdotenv: ^5.2
Requires (Dev)
README
中文版
描述
Tars 驱动器用于 Laravel。
Laravel 集成微服务治理框架 Tars
功能
- 支持服务打包
- 支持 Laravel/Lumen 原生开发
- 支持 TarsConfig
- 支持 TarsLog
- 支持网关注册下线
- 支持请求开始(laravel.tars.requesting)、请求结束(laravel.tars.requested)事件
- 支持 echo 输出内容
- 支持 http 和 tars 协议
- 支持 zipkin 分布式追踪(已移除,可以使用 laravel-zipkin 扩展包)
限制
- 由于框架本身的设计限制,不支持协程
环境依赖
- Laravel/Lumen5.x
- Tars-PHP
安装
-
创建项目
创建 Tars 项目目录结构(scripts、src、tars),Laravel/Lumen 项目放在 src 目录下
-
安装 Laravel Tars 包
更新 Composer 依赖
composer require "luoxiaojun1992/laravel-tars:*"
或在 composer.json 中添加 requirement
{ "require": { "luoxiaojun1992/laravel-tars": "*" } }
添加 ServiceProvider,编辑 src/bootstrap/app.php
$app->register(\Lxj\Laravel\Tars\ServiceProvider::class);
初始化 Laravel Tars
php artisan vendor:publish --tag=tars
-
修改配置文件 src/config/tars.php 文件 proto 字段,替换 appName、serverName、objName
-
如果使用 http 协议,且需要自动注册到网关(目前仅支持 Kong),修改配置文件 src/config/tars.php
'registries' => [ [ 'type' => 'kong', 'url' => 'http://kong:8001/upstreams/tars_mysql8/targets', //根据实际情况填写 ] ]
-
配置中心(TarsConfig)、日志服务(TarsLog)
服务启动时会自动拉取配置,如果需要记录日志,可以使用类似
Log::info('test log');
如果需要指定 TarsLog 记录的最低日志级别,修改配置文件 src/config/tars.php
'log_level' => \Monolog\Logger::INFO
-
如果使用 http 协议,按框架原生方式编写代码
$router->get('/test', function () { \Illuminate\Support\Facades\Log::info('laravel tars test log'); return 'Laravel Tars Test Success'; });
-
如果使用 tars 协议
在 tars 目录下编写 tars 接口描述文件,修改配置文件 src/config/tars 文件 proto 字段,新增 tarsFiles
在 scripts 目录执行编译脚本生成接口代码
/bin/bash tars2php.sh
在 src/app/Tars/impl 目录下创建接口实现类,编写业务逻辑代码
修改 src/config/tars.php 文件 services 字段,替换接口和接口实现命名空间
-
搭建 Tars-PHP 开发环境
如果使用 http 协议,请参考 TARS-PHP-HTTP服务端与客户端开发
如果使用 tars 协议,请参考 TARS-PHP-TCP服务端与客户端开发
-
在 Tars-PHP 开发环境下打包项目(在 src 目录下执行
php artisan tars:deploy
) -
在 Tars 管理后台发布项目,请参考 TARS-PHP-TCP服务端与客户端开发),测试
curl 'http://{ip}:{port}/{api_route}'
使用示例
Laravel 请参考 https://github.com/luoxiaojun1992/laravel-tars-demo
Lumen 请参考 https://github.com/luoxiaojun1992/lumen-tars-demo
集成部署
Jenkins Pipeline 配置示例(根据实际情况修改)
Laravel
pipeline {
agent {
node {
label 'phpenv'
}
}
parameters {
string(defaultValue: 'upload_from_jenkins', name: 'TAG_DESC', description: '发布版本描述' )
string(defaultValue: 'master', name: 'BRANCH_NAME', description: 'git分支,如:develop,master 默认: master')
}
environment {
def JENKINS_HOME = "/root/jenkins"
def PROJECT_ROOT = "$JENKINS_HOME/workspace/laravel-tars-demo"
def APP_NAME = "PHPTest"
def SERVER_NAME = "LaravelTars"
}
stages {
stage('代码拉取与编译'){
steps {
echo "checkout from git"
git credentialsId:'2', url: 'https://gitee.com/lb002/laravel-tars-demo', branch: "${env.BRANCH_NAME}"
script {
dir("$PROJECT_ROOT/src") {
echo "Composer Install"
sh "composer clear-cache"
sh "composer install -vvv"
sh "cp .env.example .env"
sh "php artisan config:clear"
sh "php artisan config:cache"
}
}
}
}
stage('单元测试') {
steps {
script {
dir("$PROJECT_ROOT/src") {
echo "phpunit 测试"
sh "vendor/bin/phpunit tests/"
echo "valgrind 测试"
}
}
}
}
stage('覆盖率测试') {
steps {
echo "LCOV 覆盖率测试"
}
}
stage('打包与发布') {
steps {
script {
dir("$PROJECT_ROOT/src") {
echo "打包"
sh "php artisan tars:deploy"
echo "发布"
sh "ls *.tar.gz > tmp.log"
echo "上传build包"
def packageDeploy = sh(script: "head -n 1 tmp.log", returnStdout: true).trim()
sh "curl -H 'Host:172.18.0.3:3000' -F 'suse=@./${packageDeploy}' -F 'application=${APP_NAME}' -F 'module_name=${SERVER_NAME}' -F 'comment=${env.TAG_DESC}' http://172.18.0.3:3000/pages/server/api/upload_patch_package > curl.log"
echo "发布build包"
def packageVer = sh(script: "jq '.data.id' curl.log", returnStdout: true).trim()
def postJson = '{"serial":true,"items":[{"server_id":"34","command":"patch_tars","parameters":{"patch_id":' + packageVer + ',"bak_flag":false,"update_text":"${env.TAG_DESC}"}}]}'
echo postJson
sh "curl -H 'Host:172.18.0.3:3000' -H 'Content-Type:application/json' -X POST --data '${postJson}' http://172.18.0.3:3000/pages/server/api/add_task"
}
}
}
}
}
post {
success {
emailext (
subject: "[jenkins]构建通知:${env.JOB_NAME} 分支: ${env.BRANCH_NAME} - Build# ${env.BUILD_NUMBER} 成功 !",
body: '${SCRIPT, template="groovy-html.template"}',
mimeType: 'text/html',
to: "luoxiaojun1992@sina.cn",
)
cleanWs()
}
failure {
emailext (
subject: "[jenkins]构建通知:${env.JOB_NAME} 分支: ${env.BRANCH_NAME} - Build# ${env.BUILD_NUMBER} 失败 !",
body: '${SCRIPT, template="groovy-html.template"}',
mimeType: 'text/html',
to: "luoxiaojun1992@sina.cn",
)
cleanWs()
}
}
}
Lumen
pipeline {
agent {
node {
label 'phpenv'
}
}
parameters {
string(defaultValue: 'upload_from_jenkins', name: 'TAG_DESC', description: '发布版本描述' )
string(defaultValue: 'master', name: 'BRANCH_NAME', description: 'git分支,如:develop,master 默认: master')
}
environment {
def JENKINS_HOME = "/root/jenkins"
def PROJECT_ROOT = "$JENKINS_HOME/workspace/lumen-tars-demo"
def APP_NAME = "PHPTest"
def SERVER_NAME = "LumenTars"
}
stages {
stage('代码拉取与编译'){
steps {
echo "checkout from git"
git credentialsId:'2', url: 'https://gitee.com/lb002/lumen-tars-demo', branch: "${env.BRANCH_NAME}"
script {
dir("$PROJECT_ROOT/src") {
echo "Composer Install"
sh "composer clear-cache"
sh "composer install -vvv"
sh "cp .env.example .env"
}
}
}
}
stage('单元测试') {
steps {
script {
dir("$PROJECT_ROOT/src") {
echo "phpunit 测试"
sh "vendor/bin/phpunit tests/"
echo "valgrind 测试"
}
}
}
}
stage('覆盖率测试') {
steps {
echo "LCOV 覆盖率测试"
}
}
stage('打包与发布') {
steps {
script {
dir("$PROJECT_ROOT/src") {
echo "打包"
sh "php artisan tars:deploy"
echo "发布"
sh "ls *.tar.gz > tmp.log"
echo "上传build包"
def packageDeploy = sh(script: "head -n 1 tmp.log", returnStdout: true).trim()
sh "curl -H 'Host:172.18.0.3:3000' -F 'suse=@./${packageDeploy}' -F 'application=${APP_NAME}' -F 'module_name=${SERVER_NAME}' -F 'comment=${env.TAG_DESC}' http://172.18.0.3:3000/pages/server/api/upload_patch_package > curl.log"
echo "发布build包"
def packageVer = sh(script: "jq '.data.id' curl.log", returnStdout: true).trim()
def postJson = '{"serial":true,"items":[{"server_id":"33","command":"patch_tars","parameters":{"patch_id":' + packageVer + ',"bak_flag":false,"update_text":"${env.TAG_DESC}"}}]}'
echo postJson
sh "curl -H 'Host:172.18.0.3:3000' -H 'Content-Type:application/json' -X POST --data '${postJson}' http://172.18.0.3:3000/pages/server/api/add_task"
}
}
}
}
}
post {
success {
emailext (
subject: "[jenkins]构建通知:${env.JOB_NAME} 分支: ${env.BRANCH_NAME} - Build# ${env.BUILD_NUMBER} 成功 !",
body: '${SCRIPT, template="groovy-html.template"}',
mimeType: 'text/html',
to: "luoxiaojun1992@sina.cn",
)
cleanWs()
}
failure {
emailext (
subject: "[jenkins]构建通知:${env.JOB_NAME} 分支: ${env.BRANCH_NAME} - Build# ${env.BUILD_NUMBER} 失败 !",
body: '${SCRIPT, template="groovy-html.template"}',
mimeType: 'text/html',
to: "luoxiaojun1992@sina.cn",
)
cleanWs()
}
}
}