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

简介:

需求

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

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

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

分析

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

$userService = new UserService();
$userService->getUserInfo($uid);
AI 代码解读

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

$client  = new \SDK\Client();
$request = new \SDK\UserService\Request\GetStudentInfoRequest();
$request->setUid($uid);
$request->setMethod("GET");
$response = $client->doAction($request);
AI 代码解读

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);
AI 代码解读

客户端

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));
AI 代码解读

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

Yar 演示

yar https://github.com/laruence/yar
yar 的 java 客户端 https://github.com/zhoumengkang/yar-java-client

客户端代码,假设该服务设在局域网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));
AI 代码解读

服务器端代码

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();
AI 代码解读

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;
    }
}
AI 代码解读

了解更多

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

相关文章
Dubbo服务暴露机制解密:深入探讨服务提供者的奥秘【九】
Dubbo服务暴露机制解密:深入探讨服务提供者的奥秘【九】
125 0
【Dubbo3技术专题】「服务架构体系」第一章之Dubbo3新特性要点之RPC协议分析介绍
【Dubbo3技术专题】「服务架构体系」第一章之Dubbo3新特性要点之RPC协议分析介绍
158 1
框架巨擘:Dubbo如何一统异构微服务江湖,成为开发者的超级武器!
【8月更文挑战第8天】在软件开发中,微服务架构因灵活性和可扩展性备受欢迎。面对异构微服务的挑战,Apache Dubbo作为高性能Java RPC框架脱颖而出。它具备服务注册与发现、负载均衡及容错机制等核心特性,支持多种通信协议和序列化方式,能有效连接不同技术栈的微服务。Dubbo的插件化设计保证了面向未来的扩展性,使其成为构建稳定高效分布式系统的理想选择。
98 5
【Dubbo3技术专题】「云原生微服务开发实战」 一同探索和分析研究RPC服务的底层原理和实现
【Dubbo3技术专题】「云原生微服务开发实战」 一同探索和分析研究RPC服务的底层原理和实现
197 0
作者推荐|剖析云原生服务框架中服务发现机制的核心原理与实现机制
作者推荐|剖析云原生服务框架中服务发现机制的核心原理与实现机制
350 0
|
11月前
|
作者推荐 | 一文深度解读 — 彻底认识与理解微服务技术之Rest与Restful架构精髓
作者推荐 | 一文深度解读 — 彻底认识与理解微服务技术之Rest与Restful架构精髓
583 0
微服务框架(十七)Dubbo协议及编码过程源码解析
  此系列文章将会描述Java框架Spring Boot、服务治理框架Dubbo、应用容器引擎Docker,及使用Spring Boot集成Dubbo、Mybatis等开源框架,其中穿插着Spring Boot中日志切面等技术的实现,然后通过gitlab-CI以持续集成为Docker镜像。   本文为Dubbo协议、线程模型、和其基于Netty的NIO异步通讯机制及源码
微服务技术系列教程(44)- SpringCloud2.x新知识介绍
微服务技术系列教程(44)- SpringCloud2.x新知识介绍
58 0
【完整解析】Dubbo分布式服务框架:优点、架构和未来趋势(一)
【完整解析】Dubbo分布式服务框架:优点、架构和未来趋势
1185 2

热门文章

最新文章