与Laravel结合使用

简介

Laravel集成微服务治理框架Tars

  • 支持服务打包
  • 支持Laravel/Lumen原生开发
  • 支持TarsConfig
  • 支持TarsLog
  • 支持网关注册下线
  • 支持请求开始(laravel.tars.requesting)、请求结束(laravel.tars.requested)事件
  • 支持echo输出内容
  • 支持http和tars协议
  • 支持zipkin分布式追踪(已移除,可以使用laravel-zipkin扩展包)
  • 受限于框架本身的设计,不支持协程

相关项目

使用

  1. 创建项目

    创建Tars项目目录结构(scripts、src、tars),Laravel/Lumen项目放在src目录下

  2. 安装Laravel Tars包

    更新Composer依赖

    1. composer require "luoxiaojun1992/laravel-tars:*"

    或添加 requirement 到 composer.json

    1. {
    2. "require": {
    3. "luoxiaojun1992/laravel-tars": "*"
    4. }
    5. }

    添加ServiceProvider,编辑src/bootstrap/app.php

    1. $app->register(\Lxj\Laravel\Tars\ServiceProvider::class);

    初始化Laravel Tars

    1. php artisan vendor:publish --tag=tars
  3. 修改配置文件src/config/tars.php文件proto字段,替换appName、serverName、objName

  4. 如果使用http协议,且需要自动注册到网关(目前仅支持Kong),修改配置文件src/config/tars.php

    1. 'registries' => [
    2. [
    3. 'type' => 'kong',
    4. 'url' => 'http://kong:8001/upstreams/tars_mysql8/targets', //根据实际情况填写
    5. ]
    6. ]
  5. 配置中心(TarsConfig)或者日志服务(TarsLog)

    服务启动时会自动拉取配置,如果需要记录日志,可以使用类似Log::info('test log');

    如果需要指定TarsLog记录的最低日志级别,修改配置文件src/config/tars.php

    1. 'log_level' => \Monolog\Logger::INFO
  6. 如果使用http协议,按框架原生方式编写代码,路由前缀必须为/Laravel/route

    1. $router->group(['prefix' => '/Laravel/route'], function () use ($router) {
    2. $router->get('/test', function () {
    3. \Illuminate\Support\Facades\Log::info('laravel tars test log');
    4. return 'Laravel Tars Test Success';
    5. });
    6. });
  7. 如果使用tars协议

    在tars目录下编写tars接口描述文件,修改配置文件src/config/tars文件proto字段,新增tarsFiles

    在scripts目录执行编译脚本生成接口代码

    1. /bin/bash tars2php.sh

    在src/app/Tars/impl目录下创建接口实现类,编写业务逻辑代码

    修改src/config/tars.php文件services字段,替换接口和接口实现命名空间

  8. 搭建Tars-PHP开发环境

    如果使用http协议,请参考TARS-PHP-HTTP服务端与客户端开发

    如果使用tars协议,请参考TARS-PHP-TCP服务端与客户端开发

  9. 在Tars-PHP开发环境下打包项目(在src目录下执行php artisan tars:deploy)

  10. 在Tars管理后台发布项目,请参考TARS-PHP-TCP服务端与客户端开发),测试curl 'http://{ip}:{port}/Laravel/route/{api_route}'

持续集成

Jenkins Pipeline 配置示例(根据实际情况修改)

Laravel:

  1. pipeline {
  2. agent {
  3. node {
  4. label 'phpenv'
  5. }
  6. }
  7. parameters {
  8. string(defaultValue: 'upload_from_jenkins', name: 'TAG_DESC', description: '发布版本描述' )
  9. string(defaultValue: 'master', name: 'BRANCH_NAME', description: 'git分支,如:develop,master 默认: master')
  10. }
  11. environment {
  12. def JENKINS_HOME = "/root/jenkins"
  13. def PROJECT_ROOT = "$JENKINS_HOME/workspace/laravel-tars-demo"
  14. def APP_NAME = "PHPTest"
  15. def SERVER_NAME = "LaravelTars"
  16. }
  17. stages {
  18. stage('代码拉取与编译'){
  19. steps {
  20. echo "checkout from git"
  21. git credentialsId:'2', url: 'https://gitee.com/lb002/laravel-tars-demo', branch: "${env.BRANCH_NAME}"
  22. script {
  23. dir("$PROJECT_ROOT/src") {
  24. echo "Composer Install"
  25. sh "composer clear-cache"
  26. sh "composer install -vvv"
  27. sh "cp .env.example .env"
  28. sh "php artisan config:clear"
  29. sh "php artisan config:cache"
  30. }
  31. }
  32. }
  33. }
  34. stage('单元测试') {
  35. steps {
  36. script {
  37. dir("$PROJECT_ROOT/src") {
  38. echo "phpunit 测试"
  39. sh "vendor/bin/phpunit tests/"
  40. echo "valgrind 测试"
  41. }
  42. }
  43. }
  44. }
  45. stage('覆盖率测试') {
  46. steps {
  47. echo "LCOV 覆盖率测试"
  48. }
  49. }
  50. stage('打包与发布') {
  51. steps {
  52. script {
  53. dir("$PROJECT_ROOT/src") {
  54. echo "打包"
  55. sh "php artisan tars:deploy"
  56. echo "发布"
  57. sh "ls *.tar.gz > tmp.log"
  58. echo "上传build包"
  59. def packageDeploy = sh(script: "head -n 1 tmp.log", returnStdout: true).trim()
  60. 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"
  61. echo "发布build包"
  62. def packageVer = sh(script: "jq '.data.id' curl.log", returnStdout: true).trim()
  63. def postJson = '{"serial":true,"items":[{"server_id":"34","command":"patch_tars","parameters":{"patch_id":' + packageVer + ',"bak_flag":false,"update_text":"${env.TAG_DESC}"}}]}'
  64. echo postJson
  65. 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"
  66. }
  67. }
  68. }
  69. }
  70. }
  71. post {
  72. success {
  73. emailext (
  74. subject: "[jenkins]构建通知:${env.JOB_NAME} 分支: ${env.BRANCH_NAME} - Build# ${env.BUILD_NUMBER} 成功 !",
  75. body: '${SCRIPT, template="groovy-html.template"}',
  76. mimeType: 'text/html',
  77. to: "luoxiaojun1992@sina.cn",
  78. )
  79. cleanWs()
  80. }
  81. failure {
  82. emailext (
  83. subject: "[jenkins]构建通知:${env.JOB_NAME} 分支: ${env.BRANCH_NAME} - Build# ${env.BUILD_NUMBER} 失败 !",
  84. body: '${SCRIPT, template="groovy-html.template"}',
  85. mimeType: 'text/html',
  86. to: "luoxiaojun1992@sina.cn",
  87. )
  88. cleanWs()
  89. }
  90. }
  91. }

Lumen:

  1. pipeline {
  2. agent {
  3. node {
  4. label 'phpenv'
  5. }
  6. }
  7. parameters {
  8. string(defaultValue: 'upload_from_jenkins', name: 'TAG_DESC', description: '发布版本描述' )
  9. string(defaultValue: 'master', name: 'BRANCH_NAME', description: 'git分支,如:develop,master 默认: master')
  10. }
  11. environment {
  12. def JENKINS_HOME = "/root/jenkins"
  13. def PROJECT_ROOT = "$JENKINS_HOME/workspace/lumen-tars-demo"
  14. def APP_NAME = "PHPTest"
  15. def SERVER_NAME = "LumenTars"
  16. }
  17. stages {
  18. stage('代码拉取与编译'){
  19. steps {
  20. echo "checkout from git"
  21. git credentialsId:'2', url: 'https://gitee.com/lb002/lumen-tars-demo', branch: "${env.BRANCH_NAME}"
  22. script {
  23. dir("$PROJECT_ROOT/src") {
  24. echo "Composer Install"
  25. sh "composer clear-cache"
  26. sh "composer install -vvv"
  27. sh "cp .env.example .env"
  28. }
  29. }
  30. }
  31. }
  32. stage('单元测试') {
  33. steps {
  34. script {
  35. dir("$PROJECT_ROOT/src") {
  36. echo "phpunit 测试"
  37. sh "vendor/bin/phpunit tests/"
  38. echo "valgrind 测试"
  39. }
  40. }
  41. }
  42. }
  43. stage('覆盖率测试') {
  44. steps {
  45. echo "LCOV 覆盖率测试"
  46. }
  47. }
  48. stage('打包与发布') {
  49. steps {
  50. script {
  51. dir("$PROJECT_ROOT/src") {
  52. echo "打包"
  53. sh "php artisan tars:deploy"
  54. echo "发布"
  55. sh "ls *.tar.gz > tmp.log"
  56. echo "上传build包"
  57. def packageDeploy = sh(script: "head -n 1 tmp.log", returnStdout: true).trim()
  58. 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"
  59. echo "发布build包"
  60. def packageVer = sh(script: "jq '.data.id' curl.log", returnStdout: true).trim()
  61. def postJson = '{"serial":true,"items":[{"server_id":"33","command":"patch_tars","parameters":{"patch_id":' + packageVer + ',"bak_flag":false,"update_text":"${env.TAG_DESC}"}}]}'
  62. echo postJson
  63. 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"
  64. }
  65. }
  66. }
  67. }
  68. }
  69. post {
  70. success {
  71. emailext (
  72. subject: "[jenkins]构建通知:${env.JOB_NAME} 分支: ${env.BRANCH_NAME} - Build# ${env.BUILD_NUMBER} 成功 !",
  73. body: '${SCRIPT, template="groovy-html.template"}',
  74. mimeType: 'text/html',
  75. to: "luoxiaojun1992@sina.cn",
  76. )
  77. cleanWs()
  78. }
  79. failure {
  80. emailext (
  81. subject: "[jenkins]构建通知:${env.JOB_NAME} 分支: ${env.BRANCH_NAME} - Build# ${env.BUILD_NUMBER} 失败 !",
  82. body: '${SCRIPT, template="groovy-html.template"}',
  83. mimeType: 'text/html',
  84. to: "luoxiaojun1992@sina.cn",
  85. )
  86. cleanWs()
  87. }
  88. }
  89. }