基于nginx实现protobuf RPC
老婆一起来上海工作,每个月消费立马上来了,做了一个android记账应用,把每笔帐都实时记录进去。开始是单机版的,只能两个人分别记,月底再merge一下。刚好有一台阿里云的ECS,于是准备升级为带服务端版的,通信协议可以直接用android的http库,但考虑到越来越多的app应用都开始走私有协议(比如原来运维的手机淘宝),定制一套个性化的协议本身就比较麻烦,扩展性也不好,于是想到了protobuf-rpc。但还需要一个成熟的network frame(手写的话不知道要搞到什么时候),于是想到了nginx。
github地址:https://github.com/zmkeil/nrpc
为什么选nginx
Nginx是一款高性能的web服务器,清晰的代码结构及优良的模块化,非常易于扩展为各种各样的网络服务器。其构建的基础组件如内存池,链表等及event,network接口全部包含在core/event目录中,而且性能非常高,直接面向互联网服务,网络IO方面没有任何问题。
怎么使用nginx
为了保证对nginx的修改最少,我将RPC框架当成nginx的一个模块,启动时将它动态加入到nginx的模块列表(ngx_modules[])中去。
另外提供非常简易的编程接口(和大部分RPC实现类似),监听端口、protobuf service等信息都可以在应用程序初始化阶段通过编程接口来设置,所有初始化完成之后,应用程序可以直接调用server.start()来启动服务,这个方法实际上是调用nginx的main函数(改名为ngx_start),然后就进入了nginx的正常流程,初始化所有模块(包括我们的NRPC模块),然后打开所有监听端口,并启动work进程,开始接受request。主进程自动进入deamon模式,并且设置相应的信号处理程序。所以应用程序在调用完server.start()后,就可以直接return了(实际上是不会执行到的)。
此外,nginx的core、event模块的配置,可以直接用nginx.conf文件来配置,就像原汁原味的nginx一样。
启动过程如下图所示:

右侧是简易的应用程序流程:
1、首先创建一个server,包括一些初始化工作
2、然后通过server.push_service_set()接口,为该server添加一个service_set,并配置其监听地址,一般为“0.0.0.0:port”。同时,会将该service_set信息添加到全局变量nrpc_listens[]中去。
3、然后向该service_set中添加service。这里对service使用了两层逻辑的管理:一个监听端口对应一个service_set,一个service_set可以包含多个service。因为主要是考虑面向公网应用,服务器资源宝贵,可以同时提供多种服务。
4、最后通过server.start()启动服务,如前所述,这回调用nginx的启动流程,打开所有监听端口。这里设置了nrpc的ls->handler = ngx_nrpc_init_connection,后续所有nrpc的请求入口就从这里开始。
特性
该模块实现了RPC的基本功能,比如端口配置,service添加/删除,超时设置,local_session_context等。另外还有一些常用的功能。
服务端:
1.继承了nginx的core、event模块的所有特性
2.连接保持及复用
3.QPS并发限流
服务端流程如下图:

大致流程如上图:
1、第一行3个函数和第三行1个函数,都是通过nginx的event、network接口接收/发送请求,nginx是完全非阻塞的事件模型,写起来和一般的同步写法有些区别
2、中间一行的函数则是实现了protobuf的框架接口。这里提供的多种protocol,主要是针对输入的,目前实现的只接受protobuf格式的请求,考虑到http的通用性,以后会实现接口http格式的请求,内部转化成protobuf格式,返回response时再转化成http格式。
客户端:
利用pthread实现,和服务端是隔离的,代码单独组织在channel.cpp、connection_pool.cpp和controller.cpp(和服务端共用的)中,一些特性如下:
1.提供同步、异步两种模式,用户可以串行发请求,并同步处理返回结果;也可以并发发请求,异步处理结果,并提供join功能
2.自动重试机制,但RPC失败时,客户端会自动重试多次(可配置),不需要用户代码做任何处理
3.实现一个简单的连接池,可以复用连接
客户端流程如下图:

结束语
github中的sample有示例代码,详细的使用方法README中有介绍,https://github.com/zmkeil/nrpc。
这算是我的第一个开源项目,代码有很多不严谨的地方,欢迎指正,欢迎使用。
另外特别以此纪念爷爷,爷爷去世有两周了,在这个临近新春的寒冷的四九天里,是遗憾吧,或是解脱吧。爷爷生于旧社会,经历过军阀、日本侵华、文革,一生勤勤恳恳,和气待人,村里造桥铺路,春耕秋收,都事事为先,受人尊敬。记得初中时,我有一次作文比赛得到一等奖,题目是第一次XX,我写的是第一次写毛笔字,爷爷为我调墨铺纸。
基于nginx实现protobuf RPC的更多相关文章
- 基于Nginx dyups模块的站点动态上下线并实现简单服务治理
简介 今天主要讨论一下,对于分布式服务,站点如何平滑的上下线问题. 分布式服务 在分布式服务下,我们会用nginx做负载均衡, 业务站点访问某服务站点的时候, 统一走nginx, 然后nginx根据一 ...
- 基于nginx+xxl-job+springboot高可用分布式任务调度系统
技术.原理讲解: <分布式任务调度平台XXL-JOB--源码解析一:项目介绍> <分布式任务调度平台XXL-JOB--源码解析二:基于docker搭建admin调度中心和execut ...
- Google 新实现的Protobuf RPC: grpc
转自: http://www.dongliu.net/post/622450 Google 刚刚开源了grpc, 一个基于HTTP2 和 Protobuf 的RPC 实现. Protobuf 本身虽 ...
- 基于nginx tomcat redis分布式web应用的session共享配置
一.前言 nginx 作为目前最流行的开源反向代理HTTP Server,用于实现资源缓存.web server负载均衡等功能,由于其轻量级.高性能.高可靠等特点在互联网项目中有着非常普遍的应用,相关 ...
- 基于nginx的tomcat负载均衡和集群
要集群tomcat主要是解决SESSION共享的问题,因此我利用memcached来保存session,多台TOMCAT服务器即可共享SESSION了. 你可以自己写tomcat的扩展来保存SESSI ...
- 转: 基于nginx的hls直播系统
转自:http://blog.csdn.net/cjsafty/article/details/9108587 看点: 1. 详细解解答了 nginx rtmp配置过程. 前写了一篇基于nginx的h ...
- Windows 环境下基于 nginx 的本地 PyPI 源
Windows 环境下基于 nginx 的本地 PyPI 源的搭建: 1.登录 nginx 官网,下载安装包
- 基于nginx+lua+redis高性能api应用实践
基于nginx+lua+redis高性能api应用实践 前言 比较传统的服务端程序(PHP.FAST CGI等),大多都是通过每产生一个请求,都会有一个进程与之相对应,请求处理完毕后相关进程自动释放. ...
- Ubuntu 14.10下基于Nginx搭建mp4/flv流媒体服务器(可随意拖动)并支持RTMP/HLS协议(含转码工具)
Ubuntu 14.10下基于Nginx搭建mp4/flv流媒体服务器(可随意拖动)并支持RTMP/HLS协议(含转码工具) 最近因为项目关系,收朋友之托,想制作秀场网站,但是因为之前一直没有涉及到这 ...
随机推荐
- Asp.net Vnext 自定义日志
概述 本文已经同步到<Asp.net Vnext 系列教程 >中] 可以通过自定义日志,把错误消息记录到数据库 实现 在启动文件Startup Configure方法中加入自定义的日志提供 ...
- Kafka(三)Kafka的高可用与生产消费过程解析
一 Kafka HA设计解析 1.1 为何需要Replication 在Kafka在0.8以前的版本中,是没有Replication的,一旦某一个Broker宕机,则其上所有的Partition数据 ...
- Hive(三)Hive元数据信息对应MySQL数据库表
概述 Hive 的元数据信息通常存储在关系型数据库中,常用MySQL数据库作为元数据库管理.上一篇hive的安装也是将元数据信息存放在MySQL数据库中. Hive的元数据信息在MySQL数据中有57 ...
- 基于 Laravel 开发博客应用系列 —— 设置 Linux/Mac 本地开发环境
1.不同 Linux 发行版本的区别 不同的 Linux 发行版本之间有一些细微区别,尤其是包管理器:CentOS 和 Fedora 使用 yum 作为包管理器,而Ubuntu 使用 apt,在 O ...
- ROT13 加密与解密
ROT13简介: ROT13(回转13位)是一种简易的替换式密码算法.它是一种在英文网络论坛用作隐藏八卦.妙句.谜题解答以及某些脏话的工具,目的是逃过版主或管理员的匆匆一瞥.ROT13 也是过去在古罗 ...
- Eclipse 更改默认的编码 和 换行符
- KVM libvirt的CPU热添加
一. NUMA1. NUMA 介绍 早期的时候,每台服务器都是单CPU,随着技术的发展,出现了多CPU共同工作的需求. NUMA(Non-Uniform Memory Access,非一致 ...
- python中 .write 无法向文件写入内容
问题代码如下 links = open("new") out = open("out.txt","w+") for link in link ...
- 学好js,这些js函数概念一定要知道
函数创建方式 1.声明方式 例如:function consoleTip (){ console.log("tip!"); } 2.表达式方式 例如:var consoleTip ...
- Spring Boot 基础配置
之前简单接触了一些Spring Boot ,并且写了一个简单的 Demo .本文就来简单学习一下 Spring Boot 的基础配置. 一.Spring Boot 项目入口 上文中有写到,Spring ...