基于OpenResty和Node.js的微服务架构实践
什么是微服务?
传统的单体服务架构是单独服务包,共享代码与数据,开发成本较高,可维护性、伸缩性较差,技术转型、跨语言配合相对困难。而微服务架构强调一个服务负责一项业务,服务可以单独部署,独立进行技术选型和开发,服务间松耦合,服务依赖的数据也独立维护管理。虽然微服务存在部署复杂、运维难度较大、分布式事务控制难、容错要求高等缺点,但总体而言,微服务的优点远大于其复杂性。

微服务架构需要注意哪些问题?
微服务架构,首先考虑客户端与服务端之间的通信问题。有两种解决办法,一是客户端与多个服务端直接进行通信,但存在对外暴露接口细节、众多接口协议无法统一、客户端的代码复
杂、服务端升级相对困难等问题。二是客户端访问统一的API网关,由API网关调用众多服务接口,易实现统一通信协议,降低客户端和服务端代码耦合,也可以达到统一的鉴权和流控,然而此方式存在延时增加的风险,可能使API网关成为系统发展的瓶颈。

微服务架构是分布式服务架构,如何进行服务的注册和发现也是需要解决的问题。一种是通过客户端发现,调用方需要知道所有依赖服务的地址,开发成本较高,协议升级比较困难。另一种是通过统一网关发现具体服务的地址,对客户端来说实现比较简单,能够在网关进行统一鉴权和流控,要求网关高度可用性。

调用微服务尽可能做到有序,避免相互调用,杜绝循环调用。服务间要有清晰的层次关系,上层服务可以依赖下层服务,如果遇到下层服务需要同步消息给上层调用方的情况,可以考虑通过消息队列异步解耦,比如订单/审核系统在创建订单或者改变订单状态时,可以考虑使用双写(即写入数据库后,同时在消息队列也写一份),异构系统(比如订单执行系统)可以通过订阅消息保存异构数据。
个推在微服务上有哪些实践?
个推的服务场景主要有三种。其一是个推推送场景,通过Java语言开发,SOA的架构方式来实现,保证信息推送的实时性与高并发性,这块微服务改造比较困难;其二是广告交易平台,比如投放平台、DMP数据管理,以Java为主进行开发,对并发数要求较高,我们在逐步进行基于Java的微服务框架的微服务化尝试;其三是web业务系统,它为前端提供无状态的业务API接口,是典型的request/response方式,同时,这是我们目前微服务实践最多的场景。

随着业务快速发展,公司web相关的业务系统开发需求不断增加,这些系统都涉及到用户管理,后台管理,权限管理等。为进一步提高团队开发效率,我们对服务进行平台化、模块化改造,选择了如上的技术选型。

个推的整体架构如上图所示。请求先经过LVS/HaProxy,到达基于OpenResty实现的API网关,API网关会根据请求将流量upstream到服务单元。服务单元作为一个整体,支持通过Lua、Node.js、Java等语言实现业务逻辑,启动时向Zookeeper注册,API网关会从Zookeeper获取服务单元部署信息。

服务单元如上图所示。它由Openresty统一对外暴露服务端,Openresty内置了lua语言,可以在weblua框架中通过编写lua程序来进行业务逻辑处理。Openresty通过proxy_pass,upstream将请求转给webnode处理,也可以在Openresty中通过配置处理Java业务逻辑。服务单元就像一个抽屉柜,具体的业务(app)就像一个抽屉,只要尺寸符合抽屉柜的要求,就能将抽屉推入到抽屉柜中,抽屉所用的语言不作要求。

Openresty集成了lua脚本作为编程语言,使用Zookeeper服务注册。为了解决lua与Zookeeper不适配问题,在Openresty启动时启动websocket服务,Node.js进程启动时同步启动websocket的client,这样每个Node.js进程会和Openresty保持长连接和心跳,Openresty会选择一个Node.js进程,启动Zookeeperclient完成服务注册。API网关也是基于服务单元通过类似的方式实现完成服务注册的。

服务单元在Openresty层完成了统一鉴权,不会产生额外的性能开销。
我们可以用“通道化”来阐述服务间的调用问题。我们将微服务之间的调用比喻成水管,从水管的一端流进去的是请求信息,那么从另一端流出来的也应该是请求信息,我们只要求流入流出的信息保持一致,而不关心这些信息在传输过程中经过了转换或其他过程。如上图,A、B之间的调用通过进程内require就能实现,而A、C间的调用是通过服务单元内的http完成的。
Q&A
Q:微服务架构在运维部署是否会很麻烦?
A:随着微服务的不断推进,服务数量势必会越来越多,这就需要考虑DEVOPS。比如代码提交之后通过Jenkins自动触发打包编译,自动生成版本号,进而触发自动测试部署和自动化测试,测试通过后进行一键部署升级、支持升级失败自动回滚等。我们目前已经实现了自动打包和测试部署,后续环节正在推进。
Q:Openresty里对Session管理进行了处理,开发人员会不会觉得不方便?
A:在引入微服务框架之前,公司有很多独立业务服务,每个服务都有自己的账号系统实现登录验证逻辑。虽然有现成的代码模块可以用,但每次都需要重新测试验证。如今,具体的业务服务都可以通过Openresty完成鉴权并统一对外,对开发和测试人员来说,反而减少了一定的工作量。
基于OpenResty和Node.js的微服务架构实践的更多相关文章
- 使用 Node.js 搭建微服务网关
目录 Node.js 是什么 安装 node.js Node.js 入门 Node.js 应用场景 npm 镜像 使用 Node.js 搭建微服务网关 什么是微服务架构 使用 Node.js 实现反向 ...
- 基于 Docker 的微服务架构实践
本文来自作者 未闻 在 GitChat 分享的{基于 Docker 的微服务架构实践} 前言 基于 Docker 的容器技术是在2015年的时候开始接触的,两年多的时间,作为一名 Docker 的 D ...
- Cola Cloud 基于 Spring Boot, Spring Cloud 构建微服务架构企业级开发平台
Cola Cloud 基于 Spring Boot, Spring Cloud 构建微服务架构企业级开发平台: https://gitee.com/leecho/cola-cloud
- 基于 Spring Cloud 的微服务架构实践指南(下)
show me the code and talk to me,做的出来更要说的明白 本文源码,请点击learnSpringCloud 我是布尔bl,你的支持是我分享的动力! 一.引入 上回 基于 S ...
- 微服务架构实践 - 你只懂docker与spring boot就够了吗?
微服务架构实践 - 你只懂docker与spring boot就够了吗? 作者 浮云发发 已关注 2017.02.27 02:50* 字数 2613 阅读 2583评论 6喜欢 35赞赏 2 微服务并 ...
- 基于 Spring Cloud 的微服务架构实践指南(上)
show me the code and talk to me,做的出来更要说的明白 GitHub 项目learnSpringCloud同步收录 我是布尔bl,你的支持是我分享的动力! 一. 引入 上 ...
- 从 Spring Cloud 开始,聊聊微服务架构实践之路
[编者的话]随着公司业务量的飞速发展,平台面临的挑战已经远远大于业务,需求量不断增加,技术人员数量增加,面临的复杂度也大大增加.在这个背景下,平台的技术架构也完成了从传统的单体应用到微服务化的演进. ...
- 放弃Dubbo,选择最流行的Spring Cloud微服务架构实践与经验总结
http://developer.51cto.com/art/201710/554633.htm Spring Cloud 在国内中小型公司能用起来吗?从 2016 年初一直到现在,我们在这条路上已经 ...
- 基于node.js构建微服务中的mock服务
缘起 由于现在微服务越来越火了,越来越多的微服务融入到了日常开发当中.在开发微服务的时候,经常会遇到一个问题由于依赖于其他服务,导致你的进度受到阻碍.使你不得不先mock出你期望调用依赖服务的输出,来 ...
随机推荐
- .NET 4.0 Tuple 元组
Tuple是.NET 4.0的新特性,主要功能是动态返回数据结构,也可以用做临时数据结构. 原来做一些功能时需要一个方法返回几个值,有两种方法: 1. 非常难看.难用的OUT参数: 2. 新写一个实体 ...
- 5 种使用 Python 代码轻松实现数据可视化的方法
数据可视化是数据科学家工作中的重要组成部分.在项目的早期阶段,你通常会进行探索性数据分析(Exploratory Data Analysis,EDA)以获取对数据的一些理解.创建可视化方法确实有助于使 ...
- loadrunner socket协议问题归纳(4)---buffer接收变长和定长的数据
测试场景:聊天系统 用户登录后,要先向服务器发送用户名,然后可以发送聊天信息,同时也可以接受聊天信息. 如果接受的字符为定长时,可以设定接受长度.recv buf2 66 #include " ...
- 严重: Failed to destroy end point associated with ProtocolHandler ["http-nio-8080"] java.lang.NullPointer
刚接触servlet类,按照课本的方法使用eclipse新建了一个servlet类. 新建完成后,在web.xml里面进行注册 这时候就会报错了. 五月 07, 2016 11:23:28 上午 or ...
- Eclipse项目导入到Android Studio中
背景 最近需要将Eclipse中的android项目导入到Android Studio中!倒腾一番,记录如下! 步骤1 打开Android Studio(下文称AS),选择Import project ...
- Haproxy + Rabbit 集群 简要介绍
# 两台主机都安装上rabbitMQ yum install -y rabbitmq-server # 两台主机都配置/etc/hosts文件 192.168.23.10 rabbitmq1 19 ...
- Java实现的词频统计——单元测试
前言:本次测试过程中发现了几个未知字符,这里将其转化为十六进制码对其加以区分. 1)保存统计结果的Result文件中显示如图: 2)将其复制到eclipse环境下的切分方法StringTokenize ...
- 设计模式php篇(一)————单例模式
话不多说,直接上代码: <?php namespace DesignPattern; /** * php设计模式之单例模式 */ class SingleInstance { private s ...
- python/django将mysql查询结果转换为字典组
使用python查询mysql数据库的时候,默认查询结果没有返回表字段名称,不方便使用.为了方便使用一般会选择将查询结果加上字段名称以字典组的方式返回查询结果. 实现如下: def dict_fetc ...
- linux设置时区和自动同步时间
1.设置时区 编辑 /etc/sysconfig/clock 修改 ZONE="Asia/Shanghai" 然后 cp /usr/share/zoneinfo/Asia/Sh ...