作者 彭建超

删除 README.md

正在显示 1 个修改的文件 包含 0 行增加346 行删除
1 -## 简介  
2 -AukeySwrpc是一个基于swoole开发的高性能rpc包,AukeySwrpc提供了注册发现,链路追踪,中间件等等功能,可以很容易集成到第三方框架,如laravel,yii等等。  
3 -  
4 -  
5 -  
6 -## 功能  
7 -  
8 -- 支持多进程模式或协程模式  
9 -- 支持同步,异步调用  
10 -- 支持自定义中间件  
11 -- 支持服务端按类提供对外服务  
12 -- 支持链路追踪  
13 -- 支持注册服务发现  
14 -- 支持客户端负载均衡,包含随机,权重两种模式  
15 -- 支持自定义日志,包协议,序列化方式等等  
16 -  
17 -  
18 -  
19 -## 安装  
20 -  
21 -```bash  
22 -php composer.phar require wuzhc/swprc ~1.0 -vvv  
23 -```  
24 -  
25 -  
26 -  
27 -## 快速体验  
28 -  
29 -假设我们User和School两个模块,为了获得用户学校名称,我们需要在User模块发起rpc请求调用School模块的服务。  
30 -  
31 -### School模块  
32 -  
33 -```php  
34 -<?php  
35 -use AukeySwrpc\LogicService;  
36 -class SchoolService extends LogicService  
37 -{  
38 - public function getUserSchool($userID) {  
39 - $name = $userID == 123 ? '火星' : '水星';  
40 - return $name.'学校';  
41 - }  
42 -}  
43 -```  
44 -  
45 -School模块将作为rpc服务端,对外提供服务,启动如下:  
46 -  
47 -```php  
48 -<?php  
49 -namespace AukeySwrpcTests;  
50 -use AukeySwrpc\Server;  
51 -  
52 -$basePath = dirname(dirname(__FILE__));  
53 -require_once $basePath . "/vendor/autoload.php";  
54 -  
55 -$options = [  
56 - 'enable_coroutine' => true,  
57 - 'pid_file' => __DIR__ . '/AukeySwrpc.pid',  
58 -];  
59 -$server = new Server('School_Module', '127.0.0.1', 9501, 1, $options);  
60 -$server->addService(\AukeySwrpcTests\services\SchoolService::class);  
61 -$server->start();  
62 -```  
63 -  
64 -将SchoolService添加到server,server会自动检索类中所有可用的public方法。  
65 -  
66 -![1615562843265](https://segmentfault.com/img/bVcPwbR)  
67 -  
68 -  
69 -  
70 -### User模块  
71 -  
72 -User模块作为客户端,调用School模块服务如下  
73 -  
74 -```php  
75 -<?php  
76 -namespace AukeySwrpcTests;  
77 -use AukeySwrpc\Request;  
78 -use AukeySwrpc\LogicService;  
79 -use AukeySwrpc\Client;  
80 -  
81 -class UserService extends LogicService  
82 -{  
83 - public function getUserSchoolName()  
84 - {  
85 - $userID = 123;  
86 - $module = 'School_Module'; //请求目标模块名称,需要和服务端定义的一致  
87 - $client = Client::create($module, '127.0.0.1', 9501);  
88 - return $client->send(Request::create('\AukeySwrpcTests\services\SchoolService_getUserSchool', [$userID]));  
89 - }  
90 -}  
91 -  
92 -//调用  
93 -echo UserService::factory()->getUserSchoolName();  
94 -```  
95 -注意:  
96 -- Request.method 为服务类命名 + 下划线 + 方法名,例如上面的`\AukeySwrpcTests\services\SchoolService_getUserSchool`,如果服务类有命名空间,记得一定要带上命名空间  
97 -  
98 -  
99 -  
100 -## 多进程和协程模式  
101 -  
102 -多进程或协程模式需要和swoole配置一致,具体参考swoole配置  
103 -  
104 -### 多进程模式  
105 -  
106 -创建10进程来处理请求  
107 -  
108 -```php  
109 -$options = [  
110 - 'worker_num' => 10  
111 - 'pid_file' => __DIR__ . '/AukeySwrpc.pid',  
112 -];  
113 -$server = new Server('School_Module', '127.0.0.1', 9501, 1, $options);  
114 -```  
115 -  
116 -### 协程模式  
117 -  
118 -目前AukeySwrpc协程模式是运行在单进程的  
119 -  
120 -```php  
121 -$options = [  
122 - 'enable_coroutine' => true,  
123 - 'pid_file' => __DIR__ . '/AukeySwrpc.pid',  
124 -];  
125 -$server = new Server('School_Module', '127.0.0.1', 9501, 1, $options);  
126 -```  
127 -  
128 -  
129 -  
130 -## 同步调用和异步调用  
131 -  
132 -在客户端发起同步调用,客户端会一直等待服务端返回结果  
133 -  
134 -```php  
135 -$client = \AukeySwrpc\Client::create($module, '127.0.0.1', 9501);  
136 -return $client->send(SyncRequest::create('SchoolService_getUserSchool', [$userID]));  
137 -```  
138 -  
139 -在客户端发起异步调用,客户端会立马得到响应结果,请求将被swoole的task进程处理  
140 -  
141 -```php  
142 -$client = \AukeySwrpc\Client::create($module, '127.0.0.1', 9501);  
143 -return $client->send(AsyncRequest::create('SchoolService_getUserSchool', [$userID]));  
144 -```  
145 -  
146 -  
147 -  
148 -## 自定义中间件  
149 -  
150 -中间件允许程序可以对请求进行前置操作和后置操作,底层使用了责任链设计模式,所以为了执行下一个中间件,必须返回`$next($request)`,如果想提前返回,则返回结果必须是`AukeySwrpc\Response`类型  
151 -  
152 -```php  
153 -//中间件除了用匿名函数定义,还可以用实现AukeySwrpc\Middlewares\MiddlewareInterface接口的类  
154 -$middleware = function (\AukeySwrpc\Request $request, Closure $next) {  
155 - $start = microtime(true); //前置操作,记录请求开始时间  
156 - $result = $next($request);  
157 - echo '耗时:'.(microtime(true) - $start).PHP_EOL; //后置操作,记录请求结束时间,从而计算请求耗时  
158 - return $result; //继续下个中间件的处理  
159 -};  
160 -$server = new Server('School_Module', '127.0.0.1', 9501, 1, $options);  
161 -$server->addService(SchoolService::class);  
162 -$server->addMiddleware($middleware); //添加中间件  
163 -$server->start();  
164 -```  
165 -如果要提前中止中间件,可以提前在匿名函数或类方法中返回\AukeySwrpc\Response对象,如下  
166 -```php  
167 -$middleware = function (\AukeySwrpc\Request $request, Closure $next) {  
168 - if (empty($request->getParams())) {  
169 - return \AukeySwrpc\Response::error('参数不能为空'); //提前返回,必须是Response类型  
170 - }  
171 - return $next($request);  
172 -};  
173 -```  
174 -  
175 -  
176 -  
177 -## 服务端按类提供对外服务  
178 -  
179 -从上面的例子中,我们把SchoolService整个类添加的server中,这样server就能对外提供SchoolService类所有public方法的功能。  
180 -  
181 -```php  
182 -$server = new Server('School_Module', '127.0.0.1', 9501, 1, $options);  
183 -$server->addService(SchoolService::class); //提供SchoolService所有public方法功能  
184 -$server->addService(AreaService::class); //提供AreaService所有public方法功能  
185 -$server->start();  
186 -```  
187 -客户端使用参考上面的快速体验  
188 -  
189 -  
190 -  
191 -## 注册服务发现  
192 -  
193 -如果服务端启动的时候有设置注册中心,则启动成功会自动向注册中心注册服务端地址。目前AukeySwrpc提供了`Consul`作为注册中心,使用如下  
194 -  
195 -```php  
196 -$server = new Server('School_Module', '127.0.0.1', 9501, 1, $options);  
197 -$server->addRegister(new Consul());  
198 -$server->addService(SchoolService::class);  
199 -$server->start();  
200 -```  
201 -  
202 -如上,使用Consul作为服务的注册中心,通过`http://127.0.0.1:8500`可以查看注册信息,如果想用etcd等其他注册中心,只要实现`AukeySwrpc\Middlewares\RegisterInterface`接口即可,然后在通过`$server->addRegister()`添加到server  
203 -  
204 -![1615562878292](https://segmentfault.com/img/bVcPwbR)  
205 -  
206 -![1615562927956](https://segmentfault.com/img/bVcPwb4)  
207 -  
208 -![1615562975815](https://segmentfault.com/img/bVcPwb5)  
209 -  
210 -  
211 -  
212 -## 客户端负载均衡  
213 -  
214 -如果服务端启动多个节点,例如School模块启动3个节点,并且注册到了注册中心,那么我们可以从注册中心获取所有服务端节点信息,然后做一些策略处理。  
215 -  
216 -```php  
217 -$register = new Consul();  
218 -$client = \AukeySwrpc\Client::createBalancer('School_Module', $register, \AukeySwrpc\Client::STRATEGY_WEIGHT);  
219 -$result = $client->send(Request::create('SchoolService_getUserSchool', [$userID]);  
220 -```  
221 -  
222 -目前AukeySwrpc提供两种简单策略模式,`\AukeySwrpc\Client::STRATEGY_WEIGHT权重模式`,`\AukeySwrpc\Client::STRATEGY_RANDOM`随机模式  
223 -  
224 -  
225 -  
226 -## 链路追踪  
227 -  
228 -当我们的服务非常多并且需要互相调用时候,如果其中某个调用失败,会导致我们得不到我们想要的结果,而要调试出是哪个环节出了问题也比较麻烦,可能你需要登录每台机器看下有没有错误日志,或者看返回的错误信息是哪个服务提供的。链路追踪记录了整个调用链过程,如果某个环节出错,我们可以快速从调用链得到调用中断地方。  
229 -  
230 -```php  
231 -class UserService extends LogicService  
232 -{  
233 - public function getUserSchoolName()  
234 - {  
235 - $userID = 123;  
236 - $module = 'School_Module'; //请求目标模块名称,需要和服务端定义的一致  
237 - $client = Client::create($module, '127.0.0.1', 9501);  
238 - return $client->send(Request::create('SchoolService_getUserSchool', [$userID], $this->getTracerContext(__FUNCTION__))); //getTracerContext()用于提供追踪上下文  
239 - }  
240 -}  
241 -  
242 -$users = UserService::factory()  
243 - ->setModule('User_Module') //当前模块,用于调用链的起点  
244 - ->setTracerUrl('http://127.0.0.1:9411/api/v2/spans') //zipkin链路追踪地址  
245 - ->getUserSchoolName();  
246 -```  
247 -  
248 -![1615563070157](https://segmentfault.com/img/bVcPwb6)  
249 -  
250 -如图,User_Module调用Class_Module,Class_Module又去调用School_Module  
251 -  
252 -![1615563170709](https://segmentfault.com/img/bVcPwb8)  
253 -  
254 -每个调用还记录响应结果  
255 -  
256 -  
257 -  
258 -  
259 -## 自定义日志处理器  
260 -默认使用`Monolog/Logger`作为日志处理器,日志信息会输出到控制台。可根据自己需求覆盖默认处理器,只要日志类  
261 -实现`Psr\Log\LoggerInterface`即可  
262 -```php  
263 -use AukeySwrpc\Server;  
264 -use Monolog\Handler\StreamHandler;  
265 -use Monolog\Logger;  
266 -  
267 -$logger = new Logger('AukeySwrpc');  
268 -$logger->pushHandler(new StreamHandler(fopen('xxxx.log','w+'), Logger::DEBUG));  
269 -  
270 -$server = new Server('127.0.0.1', 9501, ['enable_coroutine'=>true]);  
271 -$server->addService(UserService::class);  
272 -$server->addLogger($logger); //覆盖默认日志处理器  
273 -$server->start();  
274 -```  
275 -  
276 -  
277 -  
278 -## 序列化方式  
279 -  
280 -默认使用固定头+包体来解决**tcp粘包**问题,默认配置为`'package_length_type' => 'N'`,`'package_body_offset' => 4`  
281 -默认序列化数据会使用`serialize()`,如果swoole版本在4.5以上的自动使用swoole_substr_unserialize(),可以实现的类来覆盖默认配置,只要实现`src/Packer/PackerInterface`即可,注意服务端和客户端需要使用一样的协议,否则解析不了。  
282 -  
283 -```php  
284 -use AukeySwrpc\Server;  
285 -  
286 -$packer = new \AukeySwrpc\Packer\SerializeLengthPacker();  
287 -$server = new Server('127.0.0.1', 9501, ['enable_coroutine'=>true]);  
288 -$server->addService(UserService::class);  
289 -$server->addPacker($packer); //覆盖默认值  
290 -```  
291 -  
292 -  
293 -  
294 -## 安全证书配置  
295 -  
296 -参考:<https://wiki.swoole.com/#/server/setting?id=ssl_cert_file>  
297 -  
298 -### 服务端  
299 -  
300 -```php  
301 -$options = [  
302 - 'ssl_cert_file' => __DIR__.'/config/ssl.crt',  
303 - 'ssl_key_file' => __DIR__.'/config/ssl.key',  
304 - 'pid_file' => __DIR__ . '/AukeySwrpc.pid',  
305 -];  
306 -$server = new Server('School_Module', '127.0.0.1', 9501, $options, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL);  
307 -$server->addService(SchoolService::class);  
308 -$server->start();  
309 -```  
310 -  
311 -注意:  
312 -  
313 -- 文件必须为 `PEM` 格式,不支持 `DER` 格式,可使用 `openssl` 工具进行转换  
314 -  
315 -  
316 -  
317 -## 测试  
318 -  
319 -使用phpuint实现的简单测试案例,配置文件`phpunit.xml`,根据你的服务器配置ip地址  
320 -  
321 -```bash  
322 -php phpunit.phar tests --debug  
323 -```  
324 -  
325 -![1615602809212](https://segmentfault.com/img/bVcPwcb)  
326 -  
327 -### phpunit 测试报告  
328 -  
329 -```  
330 -Client (AukeySwrpcTests\Client)  
331 - [x] Client connect  
332 - [x] Client sync request  
333 - [x] Client async request  
334 -  
335 -Packer (AukeySwrpcTests\Packer)  
336 - [x] Serialize length pack  
337 - [x] Serialize lenght unpack  
338 - [x] Serialize eof pack  
339 - [x] Serialize eof unpack  
340 -  
341 -Server (AukeySwrpcTests\Server)  
342 - [x] Server register to consul  
343 - [x] Server unregister from consul  
344 - [x] Server add service  
345 - [x] Server add middleware  
346 -```