资讯专栏INFORMATION COLUMN

服务治理深入浅出(2)- 远程方法调用的实现

hidogs / 3181人阅读

摘要:需求在了解了前面我们关于服务治理出现的必要性之后。我们知道服务治理是建立在众多服务基础之上的,那么,第一步,打通这些服务是基础,也就是我们常说的远程调用。上面执行远程调用也类似。

需求

在了解了前面我们关于服务治理出现的必要性之后。我们知道服务治理是建立在众多“服务”基础之上的,那么,第一步,打通这些服务是基础,也就是我们常说的 RPC 远程调用。要像调用本地方法一样调用远程服务器上的方法。

现在简单粗暴口语化的方式来介绍一个需求:

A 服务器上部署的项目中,有一个UserService里面有一个getUserInfo的方法。
B 服务器上想"直接"调用该方法,怎么办?

分析

我们以 PHP 为例来进行分析。
我们希望在 B 服务器上实现类似于 A 服务器上直接调用方式

$userService = new UserService();
$userService->getUserInfo($uid);

我们经常会使用 SDK 来调用第三方提供的 api 服务,我们的做法肯定类似于

$client  = new SDKClient();
$request = new SDKUserServiceRequestGetStudentInfoRequest();
$request->setUid($uid);
$request->setMethod("GET");
$response = $client->doAction($request);

sdk 里面的 GetStudentInfoRequest 通过http映射 A 服务器上的UserService::getUserInfo

sdk 的改造

我们只需要在原来的基础上稍作修改即可,下面的代码仅做简单的演示

服务端

该服务部署在localhost:8081

class UserService
{
    public static function getUserInfo($uid)
    {
        // 假设以下内容从数据库取出
        return [
            "id"       => $uid,
            "username" => "mengkang",
        ];
    }
}

$service = $_GET["service"];
$action = $_GET["action"];
$argv = file_get_contents("php://input");

if (!$service || !$action) {
    die();
}

if ($argv) {
    $argv = json_decode($argv, true);
}


$res = call_user_func_array([$service, $action], $argv);

echo json_encode($res);
客户端
class Client
{
    private $url;
    private $service;

    private $rpcConfig = [
        "UserService" => "http://127.0.0.1:8081",
    ];

    /**
     * Client constructor.
     * @param $service
     */
    public function __construct($service)
    {
        if (array_key_exists($service, $this->rpcConfig)) {
            $this->url = $this->rpcConfig[$service];
            $this->service = $service;
        }
    }

    public function __call($action, $arguments)
    {


        $content = json_encode($arguments);
        $options["http"] = [
            "timeout" => 5,
            "method"  => "POST",
            "header"  => "Content-type:application/x-www-form-urlencoded",
            "content" => $content,
        ];

        $context = stream_context_create($options);

        $get = [
            "service" => $this->service,
            "action"  => $action,
        ];

        $url = $this->url . "?" . http_build_query($get);

        $res = file_get_contents($url, false, $context);

        return json_decode($res, true);
    }

}

$userService = new Client("UserService");
var_export($userService->getUserInfo(103));

这样是不是就非常方便的在客户端实现了像在本地一样调用远程的方法呢?这也是鸟哥 @Laruence yar 的操作原理。下面对比下 Yar 的 demo:

Yar 演示

yar https://github.com/laruence/yar
yar 的 java 客户端 https://github.com/zhoumengka...

客户端代码,假设该服务设在局域网10.211.55.4上

class RpcClient {
    // RPC 服务地址映射表
    public static $rpcConfig = array(
        "RewardScoreService"    => "http://10.211.55.4/yar/server/RewardScoreService.class.php",
    );
 
    public static function init($server){
        if (array_key_exists($server, self::$rpcConfig)) {
            $uri = self::$rpcConfig[$server];
            return new Yar_Client($uri);
        }
    }
}
 
$RewardScoreService = RpcClient::init("RewardScoreService");
var_dump($RewardScoreService->support(1, 2));

服务器端代码

class RewardScoreService {
    /**
     * $uid 给 $feedId 点赞
     * @param $feedId  interge
     * @param $uid  interge
     * @return void
     */
    public function support($uid,$feedId){
        return "uid = ".$uid.", feedId = ".$feedId;
    }
}
 
$yar_server = new Yar_server(new RewardScoreService());
$yar_server->handle();

yar 背后的故事就是我前面那段 sdk 改造的代码演示。想必看到这里,rpc 框架不再那么神秘了吧。
当然这只是实现了 rpc 的一小部分,简单的远程调用。毕竟 php 是世界上最好的语言
java 上面执行远程调用也类似。

java 远程调用

如果换成 java 可稍微麻烦点,java 实现起来之后会让你觉得更加的本地化,所以 java 也是最强大的语言
由于 java 是静态编译的,不存在类似于 php 里的__call方法的方式来实现远程调用,一般通过动态代理来实现

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
 
/**
 * Created by zhoumengkang on 5/12/15.
 */
 
/**
 * 点赞的积分服务接口
 */
interface RewardScoreService{
    String support(int uid,int feedId);
}
 
public class SupportService {
 
    public static void main(String[] args) {
        add(1,2);
    }
 
    /**
     * uid 给 feedId 点赞
     * @param uid
     * @param feedId
     * @return
     */
    public static String add(int uid, int feedId){
        YarClient yarClient = new YarClient();
        RewardScoreService rewardScoreService = (RewardScoreService) yarClient.proxy(RewardScoreService.class);
        return rewardScoreService.support(uid, feedId);
    }
 
}
 
class YarClient {
 
    public final Object proxy(Class type) {
        YarClientInvocationHandler handler = new YarClientInvocationHandler();
        return Proxy.newProxyInstance(type.getClassLoader(), new Class[]{type}, handler);
    }
}
 
final class YarClientInvocationHandler implements InvocationHandler {
 
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("这里的动态调用实现了 php 的 __call 方法");
 
        System.out.println("method : " + method.getName());
        for (int i = 0; i < args.length; i++) {
            System.out.println("args["+ i +"] : " + args[i]);
        }
         
        return null;
    }
}
了解更多

看完本篇,是不是顿时觉得 rpc 框架不再那么神秘,有一点点感觉了呢?

老铁周末的直播:揭开她的神秘面纱 - 零基础构建自己的服务治理框架 赶快上车
https://segmentfault.com/l/15...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/31974.html

相关文章

  • 服务治理深入浅出(1)- 服务治理出现必要性探索

    摘要:服务化的出现假想一个京东的发展路程都是我虚构的。更多的服务的提取抽离,更多的团队出现业务继续发展,出现了京东大药房,专门卖药,需要调用京东目前的财务系统。 以下内容都是自己的理解,不保证正确,可能是对的,也可能把你带沟里,自己甄别。 更多详情请看直播 揭开她的神秘面纱 - 零基础构建自己的服务治理框架 https://segmentfault.com/l/15... 很久之前听别人分...

    Bryan 评论0 收藏0
  • Dubbo Spring Cloud 重塑微服务治理

    摘要:在服务治理方面,相较于而言,并不成熟。遗憾的是,往往被部分开发者片面地视作服务治理的框架,而非微服务基础设施。因此,建议开发人员将或者迁移为服务。因此,下一步需要将其配置服务远程。当服务提供方启动后,下一步实现一个服务消费方。 原文链接:Dubbo Spring Cloud 重塑微服务治理,来自于微信公众号:次灵均阁 摘要 在 Java 微服务生态中,Spring Cloud1 成为...

    wh469012917 评论0 收藏0
  • dubbo源码解析(四十三)2.7新特性

    摘要:大揭秘目标了解的新特性,以及版本升级的引导。四元数据改造我们知道以前的版本只有注册中心,注册中心的有数十个的键值对,包含了一个服务所有的元数据。 DUBBO——2.7大揭秘 目标:了解2.7的新特性,以及版本升级的引导。 前言 我们知道Dubbo在2011年开源,停止更新了一段时间。在2017 年 9 月 7 日,Dubbo 悄悄的在 GitHub 发布了 2.5.4 版本。随后,版本...

    qqlcbb 评论0 收藏0
  • PHP程序员如何简单开展服务治理架构(一)

    摘要:管理这些服务方案则叫服务治理。协议假定某些传输协议的存在,如或,为通信程序之间携带信息数据。请求程序就是一个客户机,而服务提供程序就是一个服务器。在服务器端,进程保持睡眠状态直到调用信息到达为止。 不涉及其他的语言及工具,我们从PHP本身来谈如何实现服务治理 本猿人已经写好的服务治理 https://github.com/CrazyCodes... 治理什么? 这个专业名词很容易发现...

    superPershing 评论0 收藏0
  • 外行人都能看懂SpringCloud,错过了血亏!

    摘要:集群系统中的单个计算机通常称为节点,通常通过局域网连接,但也有其它的可能连接方式。这样就高兴了,可以专心写自己的,前端就专门交由小周负责了。于是,小周和就变成了协作开发。都是为了项目正常运行以及迭代。 一、前言 只有光头才能变强 认识我的朋友可能都知道我这阵子去实习啦,去的公司说是用SpringCloud(但我觉得使用的力度并不大啊~~)... 所以,这篇主要来讲讲SpringClou...

    1treeS 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<