Code Monkey home page Code Monkey logo

php-dubbo-proxy's People

Contributors

comdeng avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar

php-dubbo-proxy's Issues

noResponse

老哥,这插件经常报错noresponse,我看了下,是因为返回结果如果带异常,就这样了。经常发生在数据结构比较复杂的场景,以及数据量传输比较大,或者是响应比较慢的场景。然后我用swoole重写了组件,貌似稳定很多。

懒得提交pull request了,直接把proxy.php文件贴这里了。如果有需要讨论的地方,联系我就行了。github的邮箱对应的qq号

`<?php
/**

namespace phpple\php_dubbo_proxy;

class Proxy {
const DUBBO_NO_SUCH_METHOD_FLAG = 'No such method ';
const DUBBO_NO_SUCH_SERVICE_FLAG = 'No such service ';
const DUBBO_NORMAL_END_FLAG = 'elapsed: ';
const DUBBO_NULL_RESULT_FLAG = "null\r\n";
const DUBBO_HINT_FLAG = 'dubbo>';

/**
 * Zookeeper's instance
 * @var \Zookeeper
 */
private $zoo;
/**
 * Registry's address
 * @var string
 */
private $registry = '127.0.0.1:2181';
/**
 * Provider's version
 * @var string
 */
private $version = "1.0.0";

/**
 * Service's name
 * @var string
 */
private $service;

private function __construct($service, $registry = null, $version = null) {
    $this->service = $service;
    if ($registry !== null) {
        $this->registry = $registry;
    }
    if ($version !== null) {
        $this->version = $version;
    }
}

/**
 * Get the proxy for custom service
 * @param $service service's name
 * @param array $conf configure,such as registry, version
 * @return Proxy
 */
public static function getService($service, $conf = array()) {
    $registry = null;
    if (isset($conf['registry'])) {
        $registry = $conf['registry'];
    }
    $version = null;
    if (isset($conf['version'])) {
        $version = $conf['version'];
    }
    return new self($service, $registry, $version);
}

/**
 * Invoke service's method
 * @param $name method's name
 * @param $arguments arguments
 * @return mixed
 */
public function __call($name, $arguments) {
    $provider = $this->getProvider($this->service, $name);
    if (empty($provider)) {
        throw new \Exception('dubbo.providerNotFound');
    }
    $ret = $this->invoke($provider, $name, $arguments);
    return json_decode($ret, true);
}

/**
 * Get the provider for the custom service and method
 * @param $service
 * @param $method
 * @return bool|array
 */
private function getProvider($service, $method) {
    if (!$this->zoo) {
        $this->zoo = new \Zookeeper($this->registry);
    }
    $path = sprintf('/dubbo/%s/providers', $service);
    $rows = $this->zoo->getChildren($path);
    $providers = [];
    foreach ($rows as $row) {
        $info = parse_url(rawurldecode($row));

        $options = [];
        if (isset($info['query'])) {
            parse_str($info['query'], $options);
        }
        unset($info['query']);
        $info['options'] = $options;

// if ($this->version && $info['options']['version'] != $this->version) {
// continue;
// }
$info['options']['methods'] = explode(',', $info['options']['methods']);
if (!in_array($method, $info['options']['methods'])) {
continue;
}

        $providers[] = $info;
    }
    $num = count($providers);
    if ($num == 0) {
        return false;
    }
    if ($num > 1) {
        $index = mt_rand(0, $num - 1);
        $provider = $providers[$index];
    } else {
        $provider = $providers[0];
    }
    return $provider;
}

/**
 * Call dubbo's remoting method
 * @param $provider
 * @param $method
 * @param $args
 * @return string
 * @throws \Exception
 */
private function invoke($provider, $method, $args){


    $timeout = isset($provider['options']['timeout']) ? $provider['options']['timeout'] / 1000 : 5;
    $args = json_encode($args);
    $args = substr($args, 1, -1);
    $cmd = sprintf("invoke %s.%s(%s)", $provider['options']['interface'], $method, $args);

    $client = new \swoole_client(SWOOLE_SOCK_TCP);
    if (!$client->connect($provider['host'], $provider['port'], -1))
    {
        throw new \RuntimeException("connect failed. Error: {$client->errCode}\n");
    }
    $client->send($cmd . "\n");
    $ret = $client->recv();
    $client->close();
    if(strstr($ret, self::DUBBO_NORMAL_END_FLAG)){
        $resArr= explode(self::DUBBO_NORMAL_END_FLAG, $ret);
        $res = trim($resArr[0]);
        return $res;
    }

    if ($ret === self::DUBBO_NULL_RESULT_FLAG) {
        throw new \RuntimeException("dubbo.nullResult : "+$ret);
    }

    if (strstr($ret, self::DUBBO_NO_SUCH_METHOD_FLAG)) {
        throw new \RuntimeException("dubbo.noMethod : "+$ret);
    }
    if (strstr($ret, self::DUBBO_NO_SUCH_SERVICE_FLAG)) {
        throw new \RuntimeException('dubbo.noService : '+$ret);
    }
    throw new \RuntimeException("dubbo.unknowError:" + $ret);
}
private function invoke2($provider, $method, $args) {
    $fh = fsockopen($provider['host'], $provider['port']);
    $timeout = isset($provider['options']['timeout']) ? $provider['options']['timeout'] / 1000 : 5;
    stream_set_blocking($fh, 0);
    stream_set_write_buffer($fh, 0);
    stream_set_timeout($fh, $timeout);
    $args = json_encode($args);
    $args = substr($args, 1, -1);
    $cmd = sprintf("invoke %s.%s(%s)", $provider['options']['interface'], $method, $args);
    fwrite($fh, $cmd . PHP_EOL);

    $output = [];
    $num = 0;

    while (!feof($fh)) {
        $buffer = fgets($fh);
        if ($buffer === self::DUBBO_NULL_RESULT_FLAG) {
            $output[] = 'null';
            break;
        }
        if (strncmp($buffer, self::DUBBO_NORMAL_END_FLAG, strlen(self::DUBBO_NORMAL_END_FLAG)) === 0) {
            break;
        }
        if (strncmp($buffer, self::DUBBO_NO_SUCH_METHOD_FLAG, strlen(self::DUBBO_NO_SUCH_METHOD_FLAG)) === 0) {
            fclose($fh);
            throw new \Exception("dubbo.noMethod : "+$buffer);
        }
        if (strncmp($buffer, self::DUBBO_NO_SUCH_SERVICE_FLAG, strlen(self::DUBBO_NO_SUCH_SERVICE_FLAG)) === 0) {
            fclose($fh);
            throw new \Exception('dubbo.noService : '+$buffer);
        }
        if ($buffer !== false) {
            $output[] = rtrim($buffer);
        } else {
            $num++;
            if ($num > 100000000) {
                trigger_error('dubbo.noResponse', E_USER_ERROR);
                break;
            }
        }
    }
    fclose($fh);
    $result = implode('', $output);
    if (strncmp($result, self::DUBBO_HINT_FLAG, strlen(self::DUBBO_HINT_FLAG)) === 0) {
        $line = substr($result, strlen(self::DUBBO_HINT_FLAG));
    }
    // if charset is defined in configure, convert is not required
    return $result;
    //这里是转化,但是没提供接口修改字符集,所以直接写死utf-8了
    //      if (isset($provider['options']['charset']) && strtolower($provider['options']['charset']) == 'utf-8') {
    //          return $result;
    //      }
    //      return iconv('gbk', 'utf-8', $result);
}

}`

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.