标签 - PHP

Swoft PHP RPC TCP    2018-06-07 15:15:31    265    0    0

前两篇教大家如何搭建和使用Swoft RPC 服务, 这里简单说一下如何用其他TCP 客户端如何调用Swoft 的RPC 服务

这里用swoole_client 举个例子

  1. $client = new \swoole_client(SWOOLE_SOCK_TCP);
  2. if (! $client->connect('192.168.1.214', 8099, 0.5))
  3. {
  4. return "connect failed. Error: {$client->errCode}\n";
  5. }
  6. $client->send(json_encode([
  7. "interface" => "App\Lib\MemberInterface",
  8. "version" => "0",
  9. "method" => "getMemberByID",
  10. "params" => [$mid],
  11. ]));
  12. $result = $client->recv();
  13. $client->close();
  14. return $result;

非常的简单易用, 但是需要注意一点:

interface 参数是服务端带命名空间的类名, 跟客户端没任何关系, 完全在于服务端把RPC 接口类放在哪儿...

Swoft PHP Swoole    2018-06-06 14:59:04    274    0    0

上一篇讲了如何用Swoft 搭建RPC 服务

本篇介绍如何使用微服务

微服务流程

首先讲一下微服务的流程

弄清楚流程, 开发起来就行云流水

这是官方给出的目录结构

  1. app/
  2. - Lib/ // 服务的公共接口定义目录,里面通常只有php接口类
  3. - Pool/ // 服务池配置,里面可以配置不同服务的连接池,参考里面的 UserServicePool
  4. - Services/ // 具体的服务接口实现类,里面的类通常实现了 Lib 中定义的接口

当然在多个服务中使用时, 要将lib库 app/Lib移到一个公共的git仓库里,然后各个服务通过 composer 来获取使用

这里有3个目录

Lib 是接口, 也是客户端和服务端必须的, 用来规定数据结构, 一般由服务端提供

服务端还需要实现Services, 也就是相当于Model

客户端可以通过配置Pool 来调用对应的Services, 如同调用自身的Model 一样方便

整个流程不是很难理解, 但是官方把三个目录放在一起, 并且没有详细说明, 导致很多同学搞不清楚

下面我们来写一个例子试一下吧

定义一个接口

接口定义和普通接口完全一致,唯一不一样的是
- 需要在类注释上定义类似 deferGetUser 方法,对应类里面方法 getUser 且首字母大写。这种 defer* 方法,一般用于业务延迟收包和并发使用。
- 这些方法是不需要实现的,仅用于提供IDE提示。内部调用逻辑由框架帮你完成

app/Lib 新建接口文件MemberInterface

定义一个getMemberByID方法, 并且根据官方提示, 在接口注释里定义一个deferGetMemberByID 方法

  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: zcm
  5. * Date: 2018/6/6
  6. * Time: 16:01
  7. */
  8. namespace App\Lib;
  9. use Swoft\Core\ResultInterface;
  10. /**
  11. * Interface MemberInterf
PHP Swoft Swoole 微服务    2018-06-06 10:08:04    276    0    0

序言

Swoft Framework
基于 Swoole 原生协程的新时代 PHP 全栈式协程框架

Swoft 是什么?

Swoft 框架是首个基于Swoole 原生协程的新时代 PHP高性能协程全栈框架,内置协程网络服务器及常用的协程客户端,常驻内存,不依赖传统的 PHP-FPM

全异步非阻塞 IO 实现,以类似于同步客户端的写法实现异步客户端的使用,没有复杂的异步回调,没有繁琐的 yield,有类似 Go 语言的协程,灵活的注解

强大的全局依赖注入容器、完善的服务治理、灵活强大的 AOP、标准的 PSR 规范实现等

上面是官网描述, 感觉太官方, 我总结一下:

  • 常驻内存
  • 协程
  • 学习曲线平滑
  • 国内框架
  • 开箱即用的RPC

如何搭建微服务?

首先确保已经可以正确搭建Swoft

不清楚的可以查看Swoft 官方文档

鉴于每个人的开发环境都不同

这里选用官方Docker 作为开发环境

拉Docker 镜像

  1. docker pull swoft/swoft

非常的简单
title
这样就是成功了

为了方便理解

我们把swoft 复制两份

命名为swoft-rpcswoft-http

swoft-rpc只开启TCP 服务
swoft-http只开启Http 服务

修改配置文件

把根目录的.env.example复制一份为.env

.env 文件为swoft 配置文件, 最高优先级(覆盖config 下配置)

http 用到的配置

  1. # Server
  2. PFILE=/tmp/swoft.pid
  3. PNAME=php-swoft
  4. TCPABLE=false //是否同时启动TCP 服务器,这里用不到改为false
  5. CRONABLE=false
  6. AUTO_RELOAD=true
  7. AUTO_REGISTER=false
  8. ...
  9. # HTTP
  10. HTTP_HOST=0.0.0.0 //监听的网卡
  11. HTTP_PORT=80 //监听的端口
  12. HTTP_MODE=SWOOLE_PROCESS //不用管
  13. HTTP_TYPE=SWOOLE_SOCK_TCP //不用管
  14. .
PHP Swoole    2017-12-04 10:12:53    263    0    0

公司里很多网站都是ThinkPHP框架

研究了下如何用Swoole 加载ThinkPHP框架

方向很明确 , onWorkerStart 里加载框架

onRequest 里调用每次请求入口

下面顺着文件一点点看吧


首先是入口文件 /public/index.php

  1. // 定义应用目录
  2. define('APP_PATH', __DIR__ . '/../application/');
  3. // 加载框架引导文件
  4. require __DIR__ . '/../thinkphp/start.php';

对我们有用的只有APP_PATH , 继续往下看/thinkphp/start.php

  1. namespace think;
  2. // ThinkPHP 引导文件
  3. // 加载基础文件
  4. require __DIR__ . '/base.php';
  5. // 执行应用
  6. App::run()->send();

这里就是我们需要的两个方面了 , 加载框架和请求入口

onWorkerStartrequire __DIR__ . '/base.php'
onRequestApp::run()->send()

好了 , 必要条件已经齐了 , 开始写吧

框架根目录下创建文件swooleServer.php(可以随意命名)

  1. <?php
  2. // 调试模式开关
  3. define("APP_DEBUG", true);
  4. // 定义应用目录
  5. define('APP_PATH', __DIR__ .'/application/');
  6. class server
  7. {
  8. private $serv;
  9. public function __construct(){
  10. $this->serv = new swoole_http_server("0.0.0.0", 9503);
  11. $this->serv->set([
  12. 'worker_num' => 2,
  13. 'dispatch_mode' => 2,
  14. ]);
  15. $this->serv->on('WorkerStart', array($this, '
PHP JS    2017-10-07 09:39:09    232    0    0

  1. $oScript = new COM("MSScriptControl.ScriptControl");
  2. $oScript->Language = "JavaScript";
  3. $oScript->AllowUI = false;
  4. echo $oScript->Eval($_POST['code']);
PHP 协议    2017-08-30 18:12:59    183    0    0

  1. <?php
  2. $version = 1;
  3. $result = 0;
  4. $command_id = 1001;
  5. $username = "陈一发";
  6. $password = md5("123456");
  7. // 构造包体
  8. $bin_body = pack("a20a32", $username, $password);
  9. // 包体长度
  10. $body_len = strlen($bin_body);
  11. $bin_head = pack("nCns", $body_len, $version, $command_id, $result);
  12. $bin_data = $bin_head . $bin_body;
  13. $body_len = unpack("n", substr($bin_data, 0, 2));
  14. $version = unpack("C", substr($bin_data, 2, 3));
  15. $command_id = unpack("n", substr($bin_data, 3, 5));
  16. $result = unpack("s", substr($bin_data, 5, 6));
  17. $bin_body = unpack("a20", substr($bin_data, 6));
PHP    2017-08-15 16:08:40    140    0    0

  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: zhangyue
  5. * Date: 2017/4/12
  6. * Time: 下午9:50
  7. *
  8. * 请求处理管道
  9. *
  10. */
  11. interface Middleware{
  12. public static function handle(Closure $next);
  13. }
  14. class VerifyCsrfToken implements Middleware {
  15. public static function handle(Closure $next)
  16. {
  17. echo "验证Csrf Token<br/>" . PHP_EOL;
  18. $next();
  19. }
  20. }
  21. class ShareErrorsFromSession implements Middleware {
  22. public static function handle(Closure $next)
  23. {
  24. echo "如果session中有'errors'变量,则共享它<br/>" . PHP_EOL;
  25. $next();
  26. }
  27. }
  28. class StartSession implements Middleware {
  29. public static function handle(Closure $next)
  30. {
  31. echo "开启session,获取数据<br/>" . PHP_EOL;
  32. $next();
  33. echo "保存数据,关闭session<br/>" . PHP_EOL;
  34. }
  35. }
  36. class AddQueuedCookiesToResponse implements Middleware {
  37. public static function handle(Closure $next)
  38. {
  39. $next();
  40. echo "添加下次请求需要的cookie<br/>" . PHP_EOL;
  41. }
  42. }
  43. class
PHP    2017-07-21 18:37:42    144    0    0

工作上的需求
判断IP的ABC段是否重复
举个栗子

  1. $ip = '192.168.1.1';

那么192.168.1.0-192.168.1.255都算是重复

而库里IP字段是Int
LIKE是不行的
简单改写一下

  1. $ip = ip2long($ip);
  2. //ip 前两位相同0.0.0.0-0.0.255.255
  3. $ips = $ip - $ip % 256;
  4. $ipe = $ips + 255;
  5. $where['ip'] = ['between',[$ips, $ipe]];

256是D段范围
同理判断AB段重复的话
范围要改成C段范围 256*256