rpc介绍python实现rpcrabbitmq实现rpc远程链接linux开发Elasticsearch介绍

Posted bnmm

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了rpc介绍python实现rpcrabbitmq实现rpc远程链接linux开发Elasticsearch介绍相关的知识,希望对你有一定的参考价值。

#to c   
#to b

# Linux 基础
# 1984年,微软发布了第一个操作系统-->MS-DOS
    -1980年,西雅图电脑产品公司(Seattle Computer Products)的一名24岁的程序员蒂姆·帕特森(Tim Paterson)花费了四个月时间编写出了86-DOS操作系统
    -在1981年7月27日,比尔盖茨完全获得了一个叫做Seattle Computer Systems(西雅图计算机系统公司)的“Quick and Dirty Operating System”,简称QDOS的授权,花费5w美元。后来该操作系统被称作MS-DOS


# 同时代,1969年(1970年,计算机元年)起,也有一款比较出名的操作系统交Unix
    -1968年 Multics项目
    -MIT、Bell实验室、美国通用电气有限公司走到了一起,致力于开发Multics项目。到后期由于开发进度不是很好,MIT和Bell实验室相继离开这个项目的开发,最终导致项目搁浅。
    -1970年(Unix元年,时间戳) Unix诞生
    -当时在开发Multics项目的时候,实验室中有一个开发成员开发了一款游戏(travel space:遨游太空),因为两个实验室相继离开项目开发,导致这名开发人员没法玩游戏,后来他提议组织人员重新在Multics项目之上重新的开发,也就出现了1970年的Unix。当时Unix操作系统是使用的汇编语言(机器语言)开发的。
    -1973年 用C语言重写Unix
    -因为汇编语言有一个最大的局限性:对于计算机硬件过于依赖。导致移植性不好,所以后期在1973年使用了C语言对其进行重新开发。
    -1975年 Bell实验室允许大学使用Unix。
    -1975年,bell实验室允许大学使用Unix操作系统用于教学作用,而不允许用于商业用途。

# 在1984年,微软发布DOS的同时,理查德·马修·斯托曼(Richard Matthew Stallman, RMS)创立了GUN项目 
   -GNU项目 (牛羚),GNU is not Unix的缩写,目的是创建一个类Unix的操作系统,因为unix不是免费的,商业收费,刚开始学校教学免费使用,后来不免费了,价格比较贵(MacOS是类Unix操作系统)
   -理查德·马修·斯托曼:1953年出生,自由软件运动的精神领袖、GNU计划以及自由软件基金会(Free Software Foundation)的创立者、著名黑客,代表作:Emacs编辑器,GCC编译器,GDB调试器

 # 自由的和免费的
    -自由的意味着源代码必须公开(windows和macos是私有的),
    -自由软件大部分是免费的,但是可以复制,修改,出售

# 1991年 Linux的开发作者,Linux之父,李纳斯·托瓦兹。Linux诞生时是荷兰在校大学生。
    -1991年 0.0.1版本
    -李纳斯当时学校使用的就是Unix操作系统,然后其对系统的底层代码进行了修改,放到了学校为学生开放的网站上,原先他把文件命名写成了Linus’s Unix,后期网络管理发现之后觉得这个名字不好,自己手动的将名字改成Linux。随后其他同学下载之后发现这个版本还是挺好用的,随后都把自己代码贡献给李纳斯。
    -1992年 0.0.2版本
    -1994年 1.0版本
    -2003年 2.6版本
# Linux吉祥物企鹅
    -李纳斯以前在澳大利亚被一只企鹅咬过

    
    
# 这两个项目是互补的,Linus其实就写了一个类Unix内核
# 1991年GNU项目已经创建了不少操作系统外网软件,比如cp命令,rm命令,GCC,GDB等--》好比Linux就是人的骨骼,GUN就是血肉
# 后来完善Linux的工作就由Linus和广大开源社区的黑客们
# GNU项目+Linux内核=完整的操作系统,我们现在叫的Linux一般都是指GUN项目+Linux内核



# 因为Linux是开源自由软件,所以基于开源的代码可以定制属于自己的Linux系统,所以Linux的版本特别多

# Linux不同发行版的区别
  -安装方式不一样,有的简单,有的复杂
  -安装应用程序的方式也不一样 
  -预装的应用程序不一样

# 不同发行版使用的Linux内核一样
    -我们现在说的Linux其实都是指的是发行版(Distribution version),就是使用Linux内核加上各种GNU的库文件、应用程序,构造而成的操作系统
    -可以想象成同一个人(Linux内核),穿不通的衣服裙子羽绒服(软件)

# 不同发行版有的免费,有的收费


# 不同发行版
  -Red Hat:性能稳定,老牌的Linux发行版,RHEL收费,是red hat的企业版,源代码是开放的,收费是因为长期升级更新服务
  -现在Red Hat分两个系列:一个是red hat公司提供收费技术支持的RHEL,另一个是社区开放的免费版Fedora,每半年发行一次,由于发行频繁导致性能不太稳定,企业一般不选用Fedora
  -Centos:算是RHEL的克隆版,社区企业级操作系统, 改与Redhat, 完全开源,兼具社区和企业特性,融合了Fedora和redhat优点,长期支持,大规模使用稳定,企业普遍使用,特别适合做服务器
  -Deepin:深度,中国发行
  -Debian:迄今为止,最遵循GUN规范的Linux系统,ubuntu
  -Ubuntu :Debian一个后继或分支,社区维护, 现在主要做手机系统和电脑桌面系统。
graph TD;
    Linux--> Debian
    Linux--> RedHat
    Linux--> Deepin深度
    RedHat--> RHEL
    RedHat--> CentOS
    RedHat--> Fedora
    
    
# centos   yum install nginx
# ubuntu   apt-get install nginx
	yum update
    apt-get update
    apt-get install vim -y
    
    
    
# redis,mysql 都是官方镜像
#公司里:基于ubuntu---》安装redis---》基于ubuntu20.04的redis镜像
	-Dockerfile
    -拉个镜像---》运行成容器---》进到容器---》安装redis---》把命令记下来---》写Dockerfile
# 消息队列
	-kafka,rabbitmq
# 作用
	-解耦
    -流量肖锋
 	-分布式
    -异步调用  进程间通信
    
    
# 安装:docker安装

# python操作:pika

# 基本使用
	-生产者---消费者
# 多个消费者
	-按顺序依次给消费
    -闲置消费
    -ack消息确认
    -持久化(队列和消息)
    
# 发布订阅(观察者模式)
	发布者发了消息,所有观察者都能收到
    交换机----》不同的队列中  fanout
    direct   指定routing_key 
    topic    模糊匹配routing_key 

今日内容

1 rpc介绍

# RPC(Remote Procedure Call) 是指远程过程调用,也就是说两台服务器 A,B 一个应用部署在 A 服务器上,想要调用 B 服务器上应用提供的函数或方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据

# 为什么要用 RPC
就是无法在一个进程内,甚至一个计算机内通过本地调用的方式完成的需求,比如比如不同的系统间的通讯,甚至不同的组织间的通讯。由于计算能力需要横向扩展,需要在多台机器组成的集群上部署应用



# 常见RPC框架
	-dubbo java
    -gRpc  跨语言 




# Spring Cloud : Spring全家桶,用起来很舒服,只有你想不到,没有它做不到。可惜因为发布的比较晚,国内还没出现比较成功的案例,大部分都是试水,不过毕竟有Spring作背书,还是比较看好。
# Dubbox: 相对于Dubbo支持了REST,估计是很多公司选择Dubbox的一个重要原因之一,但如果使用Dubbo的RPC调用方式,服务间仍然会存在API强依赖,各有利弊,懂的取舍吧。
# Thrift: 如果你比较高冷,完全可以基于Thrift自己搞一套抽象的自定义框架吧。
# Montan: 可能因为出来的比较晚,目前除了新浪微博16年初发布的,
# Hessian: 如果是初创公司或系统数量还没有超过5个,推荐选择这个,毕竟在开发速度、运维成本、上手难度等都是比较轻量、简单的,即使在以后迁移至SOA,也是无缝迁移。
# rpcx/gRPC: 在服务没有出现严重性能的问题下,或技术栈没有变更的情况下,可能一直不会引入,即使引入也只是小部分模块优化使用。



# protohuf grpc自己定制的远程过程调用的通信格式


2 python实现rpc

# SimpleXMLRPCServer 自带的
# ZeroRPC

2.1 内置的

from xmlrpc.server import SimpleXMLRPCServer

# 通信使用xml格式
class RPCServer(object):

    def __init__(self):
        super(RPCServer, self).__init__()
        print(self)
        self.send_data = \'lqz nb\'
        self.recv_data = None

    def getObj(self):
        print(\'get data\')
        return self.send_data

    def sendObj(self, data):
        print(\'send data\')
        self.recv_data = data
        print(self.recv_data)
        return \'收到了\'+data


# SimpleXMLRPCServer
server = SimpleXMLRPCServer((\'localhost\', 4242), allow_none=True)
server.register_introspection_functions()
server.register_instance(RPCServer())
server.serve_forever()

import time
from xmlrpc.client import ServerProxy

# SimpleXMLRPCServer
def xmlrpc_client():
    print(\'xmlrpc client\')
    c = ServerProxy(\'http://localhost:4242\')

    # res=c.getObj()
    # print(res)
    # res=c.sendObj(\'xxx\')
    # print(res)

    data = \'lqz nb\'
    start = time.time()
    for i in range(500):
        a=c.getObj()
        print(a)
    for i in range(500):
        c.sendObj(data)
    print(\'xmlrpc total time %s\' % (time.time() - start))

if __name__ == \'__main__\':
    xmlrpc_client()

2.2 zeroRpc

import zerorpc
import time
# zerorpc
def zerorpc_client():
    print(\'zerorpc client\')
    c = zerorpc.Client()
    c.connect(\'tcp://127.0.0.1:4243\')
    data = \'lqz nb\'

    start = time.time()
    for i in range(500):
        a=c.getObj()
        print(a)
    for i in range(500):
        c.sendObj(data)

    print(\'total time %s\' % (time.time() - start))


if __name__ == \'__main__\':
    zerorpc_client()
import zerorpc

class RPCServer(object):

    def __init__(self):
        super(RPCServer, self).__init__()
        print(self)
        self.send_data = \'lqz nb\'
        self.recv_data = None

    def getObj(self):
        print(\'get data\')
        return self.send_data

    def sendObj(self, data):
        print(\'send data\')
        self.recv_data = data
        print(self.recv_data)
# zerorpc
s = zerorpc.Server(RPCServer())
s.bind(\'tcp://0.0.0.0:4243\')
s.run()

3 rabbitmq实现rpc

# 跨语言
import pika
import uuid


class FibonacciRpcClient(object):
    def __init__(self):
        credentials = pika.PlainCredentials("admin", "admin")
        self.connection = pika.BlockingConnection(pika.ConnectionParameters(\'10.0.0.101\', credentials=credentials))
        self.channel = self.connection.channel()

        # 随机生成一个消息队列(用于接收结果)
        result = self.channel.queue_declare(queue=\'\', exclusive=True)
        self.callback_queue = result.method.queue

        # 监听消息队列中是否有值返回,如果有值则执行 on_response 函数(一旦有结果,则执行on_response)
        self.channel.basic_consume(queue=self.callback_queue, on_message_callback=self.on_response, auto_ack=True)

    def on_response(self, ch, method, props, body):
        if self.corr_id == props.correlation_id:
            self.response = body

    def call(self, n):
        self.response = None
        self.corr_id = str(uuid.uuid4())

        # 客户端 给 服务端 发送一个任务:  任务id = corr_id / 任务内容 = \'30\' / 用于接收结果的队列名称
        self.channel.basic_publish(exchange=\'\',
                                   routing_key=\'rpc_queue\',  # 服务端接收任务的队列名称
                                   properties=pika.BasicProperties(
                                       reply_to=self.callback_queue,  # 用于接收结果的队列
                                       correlation_id=self.corr_id,  # 任务ID
                                   ),
                                   body=str(n))
        while self.response is None:
            self.connection.process_data_events()

        return self.response


fibonacci_rpc = FibonacciRpcClient()

response = fibonacci_rpc.call(9)
print(\'返回结果:\', response)

import pika
credentials = pika.PlainCredentials("admin","admin")
connection = pika.BlockingConnection(pika.ConnectionParameters(\'10.0.0.101\',credentials=credentials))
channel = connection.channel()

# 声明一个队列rpc_queue
channel.queue_declare(queue=\'rpc_queue\')

def fib(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fib(n - 1) + fib(n - 2)

def on_request(ch, method, props, body):
    n = int(body)

    print(" [.] fib(%s)" % n)
    response = fib(n)

    ch.basic_publish(exchange=\'\',
                     routing_key=props.reply_to,
                     properties=pika.BasicProperties(correlation_id = \\
                                                         props.correlation_id),
                     body=str(response))
    ch.basic_ack(delivery_tag=method.delivery_tag)

channel.basic_qos(prefetch_count=1)
channel.basic_consume(queue=\'rpc_queue\', on_message_callback=on_request)

print(" [x] Awaiting RPC requests")
channel.start_consuming()

4 远程链接linux开发

#  python 有的模块只能用在linux上
# 公司内的开发环境
	-win开发,linux部署
    -mac开发,linux部署
    -linxu开发,linux部署
    	-台式机,装ubuntu,在ubuntu开发
        -台式机,装虚拟机,虚拟机装ubuntu,在ubuntu开发
       	-台式机装win---》centos虚拟机--->在台式机的win上远程链接虚拟机的centos开发
        -台式机装win---》公司专门的开发服务器---》账号链接进去开发

5 Elasticsearch介绍

# 存数据的地方,专注于大数据量的存储和检索
#Elasticsearch是什么   分布式全文检索引擎
Elasticsearch 是一个基于Lucene的分布式搜索和分析引擎。

ES是elaticsearch简写, Elasticsearch是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。
Elasticsearch使用Java开发,在Apache许可条款下开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便

使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,使得全文检索变得简单

设计用途:用于分布式全文检索,通过HTTP使用JSON进行数据索引,速度快

Frida + AndroidAsync 实现 RPC


一、目标

我们之前在 某段子App签名计算方法(一) 这篇教程里面使用 python的Flask库启动一个web Server 来实现App函数的RPC调用。

今天我们介绍一个新盆友,AndroidAsync, 用AndroidAsync来启动web Server,这样frida就直接搞定,不需要再请Python来帮忙了。

二、步骤

AndroidAsync

AndroidAsync的详细介绍大家可以自行谷歌,反正就是一个比较帅的网络库了。

它的老家在这里 https://github.com/koush/AndroidAsync

把它搞下来,然后编译成jar包再转成dex,frida可以调用了。准备工作就ok了

来个栗子

我们以昨天的 某资讯App signature签名分析 (一) 为例

先把web服务跑起来

  • 把androidAsync.dex拷贝到手机里面

adb push androidAsync.dex /data/local/tmp/
  • 在 android.app.Application.attach 的时候启动WebServer

//Java.openClassFile("/data/local/tmp/androidAsync.dex").load();

var ApplicationCls = Java.use("android.app.Application");
ApplicationCls.attach.implementation = function () {
try {
var AsyncHttpServer = Java.use("com.koushikdutta.async.http.server.AsyncHttpServer");
var androidAsync = AsyncHttpServer.$new();
androidAsync.get("/", RequestTestCallback.$new());
androidAsync.listen(8181);
console.log("reg webServer Ok");
} catch (e) {
console.error("reg webServer Error!!!, e:" + e);
}

this.attach.apply(this, arguments);
};

代码就不用解释了,牛X的代码自己会说话。

在8181端口启动了WebServer,然后注册了一个测试用的 RequestTestCallback

  • 挂上心爱的Frida,试一把

打开浏览器 http://127.0.0.1:8181 木反应?

哦,晕了,这是在手机里监听8181,不是在电脑上,所以应该是访问手机的ip, http://192.168.2.113:8181/

还是木反应?看看日志,并没有 reg webServer Ok 或者 reg webServer Error!!!

原来我们用的Frida attach 模式,可能并没有跑到 android.app.Application.attach 这个函数。

这就好办了,设置一个开关变量,直接在签名函数 signInternal 里面启动服务

var bRunServer = 0;

var SignUtilCls = Java.use("com.yxdxxx.news.util.sign.SignUtil");
SignUtilCls.signInternal.implementation = function(a,b){
if( bRunServer == 0){
bRunServer = 1;
runWebServer();
}

var rc = this.signInternal(a,b);
console.log("inStr = " + b);
console.log(">>> rc = " + rc);
return rc;
}

好了这次可以看到启动成功的提示了

[MI NOTE Pro::com.hxxx.yxdxxx]-> reg webServer Ok

主动调用 签名函数

RunServer的时候增加一个 /onenewssign 接口

// androidAsync.get("/onenewssign", OneNewsSignRequestCallback.$new());

OneNewsSignRequestCallback = Java.registerClass({
name: "OneNewsSignRequestCallback",
implements: [HttpServerRequestCallback],
methods: {
onRequest: function (request, response) {
// 主动调用代码直接写这里
var InStr = request.getQuery().getString("instr");
console.log("RPC Str = " + InStr);
var context1 = Java.use('android.app.ActivityThread').currentApplication().getApplicationContext();
console.log(context1);

var SignUtilCls = Java.use("com.yxdxxx.news.util.sign.SignUtil");
var ret = SignUtilCls.signInternal(context1,InStr);
response.send("{\"code\":0,\"message\":\"" + ret + "\"}");
}
}
});

好了直接调用, http://192.168.2.113:8181/onenewssign?instr=yxdxxx5.7.7.21k6lwwmig_1620967068422_166028401 算下和之前结果对不对。

结果并不一样,但是每次传相同的参数,结果都不一样,估计so的算法里面还是加入了随机数。不过应该这个结果是可用的。

三、总结

不知道是 AndroidAsync 不太稳定还是 Frida+AndroidAsync不太稳定,反正我崩了好几回。

凑活用吧,说不定是我手机的问题。多个方法总是好的。

android.content.Context 参数获取有两种方法,一种是用Api获取全局的 Context,还有一种就是 保存 signInternal 函数的参数。

注意:response.send 的返回值必须是 Json

1:ffshow

绝大多数时候,凑合着做完,比完美地半途而废要好。绝大多数时候,决定要做就直接开始,比自认为准备充分了再开始要好。

 手机查看不方便,可以网页看

    http://91fans.com.cn


以上是关于rpc介绍python实现rpcrabbitmq实现rpc远程链接linux开发Elasticsearch介绍的主要内容,如果未能解决你的问题,请参考以下文章

python通过protobuf实现rpc

Thrift介绍以及Java中使用Thrift实现RPC示例

Frida + AndroidAsync 实现 RPC

基于grpc的流式方式实现双向通讯(python)

RPC介绍与代码实现

Trident中的DRPC实现