Home > Backend Development > PHP Tutorial > php+nodeJs+thrift protocol to realize automatic discovery of zookeeper node data

php+nodeJs+thrift protocol to realize automatic discovery of zookeeper node data

藏色散人
Release: 2023-04-07 12:38:01
forward
3111 people have browsed it

php是当下最流行的web服务器端语言,zookeeper是大型分布式协同工具,本文在这里介绍一种架构实现php服务器对于zookeeper数据变化的自动监听。

一.问题背景

php可以CLI模式模式连接zookeeper(下面简称zk),并实现zk节点数据的自动发现,这里不做过多叙述。但web服务器中,php只能主动连接zk以获得节点数据,做不到zk数据的自动发现。其次,php web服务,也难以和php CLI模式下的服务共享数据变量(cli模式下zk数据做成共享变量)。这就导致如果并发量大的话,每一个http请求php都会去连接zk,zk集群的压力会很大,其次,每一个请求都会连接zk,请求结束又释放zk连接,zk的连接与释放过于频繁。

二.解决思路

nodeJs多进程间可以通信,可以解决php服务难以实现共享变量的问题。nodeJs可以在主进程中抛出一个子进程,子进程中实现zk的自动发现,子进程侦察到zk节点数据变化时,主动通知主进程。node主进程写一个服务,像外界提供zk的数据。php web服务需要zk节点数据时,通过RPC协议(这里使用thrift协议),访问本地node主进程服务,来获取zk节点数据。

这样做有三点好处:

1.实现zk节点变化的自动发现;

2.php和node通信在同一台服务器上,不走网管,速度快,稳定性可靠

3.thrift协议直接操作套接字传输数据,比http服务要快,可以近似看作php调用自己的方法

三.具体实现

1.搭建zookeeper服务,这里我搭了一个5台zk服务的伪集群(zk服务的搭建这里不做过多介绍),测试zk服务是否能正常写入与读取节点数据

分别启动五台zk服务器

./server001/bin/zkServer.sh start
./server002/bin/zkServer.sh start
./server003/bin/zkServer.sh start
./server004/bin/zkServer.sh start
./server005/bin/zkServer.sh start
![zookeeper集群启动][1]
Copy after login

启动成功后,测试节点是否能够正常写入读取(这里提前创建了一个/zk_test节点)

启动zk客户端

./bin/zkCli.sh
/zk_test测试写入123:set /zk_test 123 发现可以正常写入与读取
![zk写入与读取][2]
Copy after login

2.创建node服务

定义thrift提供的服务,新建thrift文件,定义返回zk数据的服务:zkDataService,服务中有一个方法zkData返回节点数据

namespace php tutorial
service zkDataService {
     string zkData()
}
Copy after login

根据thrift协议生成服务端可客户端的中间代码(生成中间代码我放在windows上完成),

C:\Users\77388\AppData\thrift-0.10.0.exe -r --gen js:node zkData.thrift
Copy after login

此时会在文件夹中生成中间代码,在gen-nodejs文件夹中

![生成node端中间代码][3]
Copy after login

node安装zookeeper模块:cnpm install node-zookeeper-client,编写子进程support.js,自动发现zk节点数据变更

console.log('pid in worker:', process.pid);
process.on('message', function(msg) {
  console.log('3:', msg);
});
var i=0;
var zookeeper = require('node-zookeeper-client');
var client = zookeeper.createClient('localhost:2181');
var path = '/zk_test';//节点名称
 
function getData(client, path) {
    client.getData(
        path,
        function (event) {
            console.log('Got event: %s', event);
            getData(client, path);
        },
        function (error, data, stat) {
            if (error) {
                console.log('Error occurred when getting data: %s.', error);
                return;
            }
            process.send('zookeeper节点数据'+data.toString('utf8'));//通知主进程zk节点数据
        }
    );
}
 
client.once('connected', function () {
    console.log('Connected to ZooKeeper.');
    getData(client, path);
});
 
client.connect();
process.emit('message', '======');
Copy after login

编写主进程server.js,实现thrift定义的服务,并在主进程中启动子进程

var childprocess = require('child_process');
var worker = childprocess.fork('./support.js');
console.log('pid in master:', process.pid);
var childMessage="";
//监听子进程事件
worker.on('message', function(msg) {
  childMessage=msg;
  console.log('1:', msg);//监听子进程zk数据,并将zk节点数据打印
})
process.on('message', function(msg) {
  console.log('2:', msg);
})
Copy after login

worker.send('主进程给子进程传递的数据');

//触发事件 message
process.emit('message', '------');
var thrift = require("thrift");
var zkDataService = require("./gen-nodejs/zkDataService");
var ttypes = require("./gen-nodejs/tutorial_types");
var data = {};
var server = thrift.createServer(zkDataService, {
  zkData: function(result) {
    result(null, childMessage);//将zk节点数据返回
  }
});
server.listen(9090);
Copy after login

启动nodeJs主进程:node server.js

php+nodeJs+thrift protocol to realize automatic discovery of zookeeper node data

3.创建php服务,在php服务中也要生成thrift中间件程序,与node端类似,php端调用node主进程server.js的zkData方法,获取zk节点数据

<?php
namespace tutorial\php;
error_reporting(E_ALL);
require_once __DIR__.&#39;/lib/Thrift/ClassLoader/ThriftClassLoader.php&#39;;
require_once __DIR__.&#39;/gen-php/tutorial/zkDataService.php&#39;;
use Thrift\ClassLoader\ThriftClassLoader;
$GEN_DIR = realpath(dirname(__FILE__).&#39;/..&#39;).&#39;/gen-php&#39;;
$loader = new ThriftClassLoader();
$loader->registerNamespace(&#39;Thrift&#39;, __DIR__ . &#39;/lib&#39;);
$loader->registerDefinition(&#39;shared&#39;, $GEN_DIR);
$loader->registerDefinition(&#39;tutorial&#39;, $GEN_DIR);
$loader->register();
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
use Thrift\Protocol\TBinaryProtocol;
use Thrift\Transport\TSocket;
use Thrift\Transport\THttpClient;
use Thrift\Transport\TBufferedTransport;
use Thrift\Exception\TException;
try {
  if (array_search(&#39;--http&#39;, $argv)) {
    $socket = new THttpClient(&#39;localhost&#39;, 8080, &#39;/php/PhpServer.php&#39;);
  } else {
    $socket = new TSocket(&#39;192.168.0.105&#39;, 9090);
  }
  $transport = new TBufferedTransport($socket, 1024, 1024);
  $protocol = new TBinaryProtocol($transport);
  $client = new \tutorial\zkDataServiceClient($protocol);
  $transport->open();
  $result= $client->zkData();
  print "$result";//打印zk节点数据
  $transport->close();
} catch (TException $tx) {
  print &#39;TException: &#39;.$tx->getMessage()."\n";
}
?>
Copy after login

启动php服务,发现正常获取zk数据

php+nodeJs+thrift protocol to realize automatic discovery of zookeeper node data

修改zookeeper数据,在启动php服务,发现可以自动发现

php+nodeJs+thrift protocol to realize automatic discovery of zookeeper node data

总结:

自此,php和nodeJS相协作,完成php服务对zk数据的自动发现就完成了。架构的整体思路是node子进程实现zk的自动发现,node主进程维护一个zk节点数据的共享变量,其他服务要想使用zk节点数据时,从node主进程中获取。

The above is the detailed content of php+nodeJs+thrift protocol to realize automatic discovery of zookeeper node data. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
php
source:segmentfault.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template