Thursday, April 28, 2022

gRPC running examples

 

Overview




In gRPC, a client application can directly call a method on a server application on a different machine as if it were a local object, making it easier for you to create distributed applications and services.

As in many RPC systems, gRPC is based around the idea of defining a service, specifying the methods that can be called remotely with their parameters and return types. On the server side, the server implements this interface and runs a gRPC server to handle client calls. On the client side, the client has a stub (referred to as just a client in some languages) that provides the same methods as the server.

Concept Diagram

Install gRPC

For python: https://grpc.io/docs/languages/python/quickstart/#grpc

python -m pip install grpcio
python -m python -m pip install grpcio-tools

For c++, it suggests to build from source. For simplicity and spike purpose, we can use vcpkg package to install the library and all its dependencies, though they do not officially support any packaging system for C++.

Links:

for the trial, install gRPC on windows using vcpkg:

# install vcpkg package manager on your system using the official instructions
> cd z:
> git clone https://github.com/Microsoft/vcpkg.git
> cd vcpkg
​
# Bootstrap on Windows instead:
> ./bootstrap-vcpkg.bat
> ./vcpkg integrate install
​
# install gRPC using vcpkg package manager
> vcpkg install grpc:x64-windows

General steps to work with gRPC

  • Define a service in a .proto file.

  • Generate server and client code using the protocol buffer compiler

  • Use the gRPC API to write a simple client and server for your service.

pull the repo to play with grpc examples:

git clone https://github.xxx.com/xx/grpc.git
cd grpc
git checkout python_executor_example

1. define service in proto file

create a proto file named python_executor.proto in folder of grpc\examples\python

syntax = "proto3";
​
option java_multiple_files = true;
option java_package = "io.grpc.p";
option java_outer_classname = "PythonExecutorProto";
option objc_class_prefix = "PEP";
​
package pythonexecutor;
​
service PythonExecutor {
 // Run a python script and get the result as DataFrame
 //
 // the results are streamed if there are repeated DataFrame to return
 // in case the result are fetched and handled page by page
 rpc RunScripts(Script) returns (stream DataFrame) {}
}
​
message Script {
//the python script to evaluate
string script = 1;
}
​
message DataFrame {
   enum Type
  {
       SIMPLEData = 0;
       PandaDF = 1;
       ERRORMESSAGE = 2;
}
 // The name of the feature.
 Type type = 1;
 
 // the real data
 string payload = 2;
}
​

2. generate server/client code using proto compiler on different platforms

for python:

cd grpc\examples\python\python_executor
python -m grpc_tools.protoc -I../../protos --python_out=. --grpc_python_out=. ../../protos/python_executor.proto

for c++:

using cmake to call the proto compiler to generate the code.

> cd grpc\examples\cpp\python_executor
> mkdir cmake\build
> cd cmake\build
> Z:\vcpkg\downloads\tools\cmake-3.21.1-windows\cmake-3.21.1-windows-i386\bin\cmake -DCMAKE_PREFIX_PATH=z:\vcpkg\installed\x64-windows ../..
​
​

python -m install pandas
python -m install simplejson

3. write server/client code for the services

for python, act as the server side

  • to listen the request, expose the service

  • implement the services defined in proto file

# Copyright 2015 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
from concurrent import futures
import logging
​
import grpc
​
import python_executor_pb2
import python_executor_pb2_grpc
import pandas as pd
import simplejson
​
class Greeter(python_executor_pb2_grpc.PythonExecutorServicer):
​
   def RunScripts(self, request, context):
       user_code = request.script
       function_to_evaluate = f'def _user_script():\n'
       for u in user_code.splitlines():
           function_to_evaluate += " " + u + "\n"
       print('function_to_evaluate:')
       print(function_to_evaluate)
       
       exec(function_to_evaluate, globals())
       
       with futures.ThreadPoolExecutor(max_workers=1) as executor:
           future = executor.submit(_user_script)
           result = future.result()
           
           print(type(result))
           
           import types
           if isinstance(result, types.GeneratorType):
               for page in result:
                 if isinstance(page, pd.DataFrame):
                   pddf = page.to_json(orient="table").encode("utf-8")
                   df = python_executor_pb2.DataFrame(type=python_executor_pb2.DataFrame.Type.PandaDF, payload=pddf)
                   print(page.info())
                   yield df
                 else:
                   #todo: error/error, not expected to return other than
                   #pd.DataFrame
                   pass
​
           elif result is not None:
               if isinstance(result, pd.DataFrame):
                   pddf = result.to_json(orient="table").encode("utf-8")
                   df = python_executor_pb2.DataFrame(type=python_executor_pb2.DataFrame.Type.PandaDF, payload=pddf)
                   print(result.info())
                   yield df
               else:
                   # dump as json objects
                   dp = simplejson.dumps(result, ignore_nan=True)
                   df = python_executor_pb2.DataFrame(type=python_executor_pb2.DataFrame.Type.SIMPLEData, payload=dp)
                   print(df)
                   yield df
           else:
               # null result: {}
               df = python_executor_pb2.DataFrame(type=python_executor_pb2.DataFrame.Type.SIMPLEData, payload='{}')
               print(df)
               yield df
​
def serve():
   server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
   python_executor_pb2_grpc.add_PythonExecutorServicer_to_server(Greeter(), server)
   server.add_insecure_port('[::]:50052')
   server.start()
   server.wait_for_termination()
​
​
if __name__ == '__main__':
   logging.basicConfig()
   serve()
Z:\grpc\examples\python\python_executor> python python_executor_server.py

for c++, as a client, to call the services via the stub:

    // Context for the client. It could be used to convey extra information to
   // the server and/or tweak certain RPC behaviors.
   ClientContext context;
   DataFrame resultDf;
​
   std::unique_ptr<ClientReader<DataFrame> > reader(
       stub_->RunScripts(&context, sc));
​
   while (reader->Read(&resultDf)) {
     std::cout << "\n\nGot one data dataframe ---> \n"
               << "type:" << resultDf->type() << std::endl
               << "size: " << resultDf->ByteSizeLong() << " in bytes"
               << std::endl
               << std::endl;
  }
​
​
   Status status = reader->Finish();
   if (status.ok()) {
     std::cout << "python execution succeeded." << std::endl;
  } else {
     std::cout << "python execution failed." << std::endl
               << status.error_message().c_str()
               << status.error_details().c_str();
  }
​

After we use cmake to generate the project/solution, open with visual studio, to build the project, generate the target file.

> cd grpc\examples\cpp\python_executor\cmake\build\Debug
> set path=Z:\vcpkg\installed\x64-windows\debug\bin;%path%
> python_executor_client.exe
​

Reference

Saturday, August 1, 2020

Embedding Analytics with MicroStrategy REST API

Purpose

Learn to leverage MicroStrategy REST APIs to create your own applications. Embed dossiers in web pages with the Embedding API library, manipulate data objects from a custom application, and push your data into a data cube using custom code.

MicroStrategy products covered

  • MicroStrategy REST API Explorer
  • MicroStrategy Web
  • MicroStrategy Library
  • Push API
  • Embedding API

Topics

  • Fundamentals in REST API
  • Certify a Dossier
  • Embedding a Dossier in an HTML Page
  • Creating Data using Push API

>> 

Thursday, September 20, 2018

Remote Desktop for Mac


First thing first, to download the app, please follow this link:
https://rink.hockeyapp.net/apps/5e0c144289a51fca2d3bfa39ce7f2b06/





This article is to take a note where to find the RDP app for Mac, it is always not easy to search this app out from the wild world on Internet.
  • for Mac OS 10.11 or later
  • by Microsoft Remote Desktop
  • Microsoft Remote Desktop is designed to help you get your work done wherever you are. You can connect to remote PCs or applications and be productive as if these resources were running locally. 
Version 10.2.2 (1255)RDP on macRemote Desktop Connection Manager on Machttps://rink.hockeyapp.net/apps/5e0c144289a51fca2d3bfa39ce7f2b06/ Microsoft Remote Desktop for Mac


Monday, June 15, 2015

cloudera installation error : Installation failed. Failed to receive heartbeat from agent

Installation failed. Failed to receive heartbeat from agent



I am receiving an error on two of the three machines:
Ensure that the host's hostname is configured properly.
Ensure that port 7182 is accessible on the Cloudera Manager server (check firewall rules).
Ensure that ports 9000 and 9001 are free on the host being added.
Check agent logs in /var/log/cloudera-scm-agent/ on the host being added (some of the logs can be found in the installation details).


Solution:

1. first to check /etc/hosts file


Your hostname needs to be tied to an actual IP address on your local network which can send/receive traffic between all the hosts. (an error is the address you have associated your hostname with is the loopback address, which cannot route actual network traffic off the host.)


Use "ifconfig -a" to see a listing of your network interfaces and choose one that has an actual IP address.


2. check if another process already uses the port 9000 and 9001:

(for my instance, it (scm agent) actually uses 19001 port, some configuration file specified that, cant remember where it resides now)


to find the process that uses the port, kill the process and retry on the failed machine.


[root@hd-1] netstat -apn | grep 9001
tcp 0 0 127.0.0.1:35582 127.0.0.1:19001 ESTABLISHED 6330/python

[root@hd-1] kill -9 6330





Tuesday, August 21, 2012

近期看的电影

1. 盗梦空间(Inception)IMDB评分值很高的一部电影,大概可以排到前3位,或许是因为电影本身的逻辑非常严谨完备,很多电影爱好者不断的去研究和推敲。影片讲的是leo一帮人潜入别人的梦境,想要改变梦中人的潜意识。潜入梦境过程中又有连环的梦中梦,影片情节较复杂。

2.赤裸特工,洪金宝带着一帮小生门拍的小电影,剧本漏洞很多,抄袭学习了其他不少影片,商业影片,看看不需要说太多。

Saturday, April 28, 2012

install chukwa for hbase metrics log

Chukwa is claimed to provide log collection, analysis and results displaying solution based on HDFS and map/reduce framework, and now it is under Apache incubator project list.

Chukwa web interface




1.if you want to store into HBase and also HDFS, set it in chukwa-collector-conf.xml 
<name>chukwaCollector.pipeline</name> 
<value>org.apache.hadoop.chukwa.datacollection.writer.hbase.HBaseWriter,org.apache.

hadoop.chukwa.datacollection.writer.SeqFileWriter</value> 


notes: hbase.HBaseWriter  must be written before SeqFileWriter, because SeqFileWriter does not pass data to next writer, this is the reason that it has to be the last writer in the pipeline as a workaround.  


2. if you have questions, please make a comment, or mail to me



scala project to support JDK 17

Compiling my Scala project with JDK 17. status: the project once used sbt version 1.2.8 and scala 2.12.8, and targets JDK 11. it works fin...