网站首页 > 文章中心 > 其它

基于go语言的中间件

作者:小编 更新时间:2023-12-18 12:35:35 浏览量:324人看过

go语言实现一个简单的简单网关

网关=反向代理+负载均衡+各种策略,技术实现也有多种多样,有基于 nginx 使用 lua 的实现,比如 openresty、kong;也有基于 zuul 的通用网关;还有就是 golang 的网关,比如 tyk.

这篇文章主要是讲如何基于 golang 实现一个简单的网关.

转自: troy.wang/docs/golang/posts/golang-gateway/

基于go语言的中间件-图1

整理:go语言钟文文档:

启动两个后端 web 服务(代码)

这里使用命令行工具进行测试

具体代码

直接使用基础库 httputil 提供的NewSingleHostReverseProxy即可,返回的reverseProxy对象实现了serveHttp方法,所以呢可以直接作为 handler.

director中定义回调函数,入参为*http.Request,决定如何构造向后端的请求,比如 host 是否向后传递,是否进行 url 重写,对于 header 的处理,后端 target 的选择等,都可以今天这一节完成.

director今天这一节具体做了:

基于go语言的中间件-图2

modifyResponse中定义回调函数,入参为*http.Response,用于修改响应的信息,比如响应的 Body,响应的 Header 等信息.

最终依旧是返回一个ReverseProxy,然后将这个对象作为 handler 传入即可.

随便 random 一个整数作为索引,然后取对应的地址即可,实现比较简单.

使用curIndex进行累加计数,一旦超过 rss 数组的长度,则重置.

后端真实节点包含三个权重:

操作步骤:

一致性 hash 算法,主要是用于分布式 cache 热点/命中问题;这里用于基于某 key 的 hash 值,路由到固定后端,但是只能是基本满足流量绑定,一旦后端目标节点故障,会自动平移到环上最近的那么个节点.

实现:

每一种不同的负载均衡算法,只需要实现添加以及获取的接口即可.

然后使用工厂方法,根据传入的参数,决定使用哪种负载均衡策略.

作为网关,中间件必不可少,这类包括请求响应的模式,一般称作洋葱模式,每一层都是中间件,一层层进去,然后一层层出来.

中间件的实现一般有两种,一种是使用数组,然后配合 index 计数;一种是链式调用.

如何实现Golang的http请求处理中间件

大多数现代Web组件栈允许通过栈式/组件式中间件"过滤"请求,这样就能干净地从web应用中分离出横切关注点(译注:面向方面程序设计中的概念?). 本周我尝试在Go语言的 http.FileServer 中植入钩子,发现实现起来十分简便,让我非常惊讶.

让我们从一个基本的文件服务器开始说起:

基于go语言的中间件-图3

func main() {

}

golang使用Nsq

① 介绍

最近在研究一些消息中间件,常用的MQ如RabbitMQ,ActiveMQ,Kafka等.NSQ是一个基于Go语言的分布式实时消息平台,它基于MIT开源协议发布,由bitly公司开源出来的一款简单易用的消息中间件.

①1 Features

①.). Distributed

NSQ提供了分布式的,去中心化,且没有单点故障的拓扑结构,稳定的消息传输发布保障,能够具有高容错和HA(高可用)特性.

NSQ支持水平扩展,没有中心化的brokers.内置的发现服务简化了在集群中增加节点.同时支持pub-sub和load-balanced 的消息分发.

NSQ非常容易配置和部署,生来就绑定了一个管理界面.二进制包没有运行时依赖.官方有Docker image.

官方的 Go 和 Python库都有提供.而且为大多数语言提供了库.

NSQ推荐通过他们相应的nsqd实例使用协同定位发布者,这意味着即使面对网络分区,消息也会被保存在本地,直到它们被一个消费者读取.更重要的是,发布者不必去发现其他的nsqd节点,他们总是可以向本地实例发布消息.

NSQ

首先,一个发布者向它的本地nsqd发送消息,要做到这点,首先要先打开一个连接,然后发送一个包含topic和消息主体的发布命令,在这种情况下,我们将消息发布到事件topic上以分散到我们不同的worker中.

nsqd

每个channel的消息都会进行排队,直到一个worker把他们消费,如果此队列超出了内存限制,消息将会被写入到磁盘中.Nsqd节点首先会向nsqlookup广播他们的位置信息,一旦它们注册成功,worker将会从nsqlookup服务器节点上发现所有包含事件topic的nsqd节点.

nsqlookupd

①.)客户表示已经准备好接收消息

这确保了消息丢失唯一可能的情况是不正常结束 nsqd 进程.在这种情况下,这是在内存中的任何信息(或任何缓冲未刷新到磁盘)都将丢失.

如何防止消息丢失是最重要的,即使是这个意外情况可以得到缓解.一种解决方案是构成冗余 nsqd对(在不同的主机上)接收消息的相同部分的副本.因为你实现的消费者是幂等的,以两倍时间处理这些消息不会对下游造成影响,并使得系统能够承受任何单一节点故障而不会丢失信息.

单个 nsqd 实例被设计成可以同时处理多个数据流.流被称为"话题"和话题有 1 个或多个"通道".每个通道都接收到一个话题中所有消息的拷贝.在实践中,一个通道映射到下行服务消费一个话题.

efficiency

因为NSQ没有在守护程序之间共享信息,所以它从一开始就是为了分布式操作而生.个别的机器可以随便宕机随便启动而不会影响到系统的其余部分,消息发布者可以在本地发布,即使面对网络分区.

这种"分布式优先"的设计理念意味着NSQ基本上可以永远不断地扩展,需要更高的吞吐量?那就添加更多的nsqd吧.唯一的共享状态就是保存在lookup节点上,甚至它们不需要全局视图,配置某些nsqd注册到某些lookup节点上这是很简单的配置,唯一关键的地方就是消费者可以通过lookup节点获取所有完整的节点集.清晰的故障事件——NSQ在组件内建立了一套明确关于可能导致故障的的故障权衡机制,这对消息传递和恢复都有意义.虽然它们可能不像Kafka系统那样提供严格的保证级别,但NSQ简单的操作使故障情况非常明显.

不像其他的队列组件,NSQ并没有提供任何形式的复制和集群,也正是这点让它能够如此简单地运行,但它确实对于一些高保证性高可靠性的消息发布没有足够的保证.我们可以通过降低文件同步的时间来部分避免,只需通过一个标志配置,通过EBS支持我们的队列.但是这样仍然存在一个消息被发布后马上死亡,丢失了有效的写入的情况.

虽然Kafka由一个有序的日志构成,但NSQ不是.消息可以在任何时间以任何顺序进入队列.在我们使用的案例中,这通常没有关系,因为所有的数据都被加上了时间戳,但它并不适合需要严格顺序的情况.

NSQ对于超时系统,它使用了心跳检测机制去测试消费者是否存活还是死亡.很多原因会导致我们的consumer无法完成心跳检测,所以在consumer中必须有一个单独的步骤确保幂等性.

本文将nsq集群具体的安装过程略去,大家可以自行参考官网,比较简单.这部分介绍下笔者实验的拓扑,以及nsqadmin的基于go语言的中间件相关咨询.

topology

NSQ基本没有配置文件,配置通过命令行指定参数.

主要命令如下:

LOOKUPD命令

NSQD命令

工具类,消费后存储到本地文件.

发布一条消息

对Streams的详细信息进行查看,包括NSQD节点,具体的channel,队列中的消息数,连接数等信息.

nsqadmin

channel

列出所有的NSQD节点:

nodes

消息的统计:

msgs

lookup主机的列表:

hosts

NSQ基本核心就是简单性,是一个简单的队列,这意味着它很容易进行故障推理和很容易发现bug.消费者可以自行处理故障事件而不会影响系统剩下的其余部分.

事实上,简单性是我们决定使用NSQ的首要因素,这方便与我们的许多其他软件一起维护,通过引入队列使我们得到了堪称完美的表现,通过队列甚至让我们增加了几个数量级的吞吐量.越来越多的consumer需要一套严格可靠性和顺序性保障,这已经超过了NSQ提供的简单功能.

结合我们的业务系统来看,对于我们所需要传输的发票消息,相对比较敏感,无法容忍某个nsqd宕机,或者磁盘无法使用的情况,该节点堆积的消息无法找回.这是我们没有选择该消息中间件的主要原因.简单性和可靠性似乎并不能完全满足.相比Kafka,ops肩负起更多负责的运营.另一方面,它拥有一个可复制的、有序的日志可以提供给我们更好的服务.但对于其他适合NSQ的consumer,它为我们服务的相当好,我们期待着继续巩固它的坚实的基础.

golang适合做web开发吗

小型项目你甚至不用框架,用net/http http - The Go Programming Language

常用库也成熟了 Top - Go Search

golang的web后端即使不concurrent也比php,ruby,python快很多很多

golang里用concurrent真的非常方便,非常非常快,超大web项目golang scale成本低

如果你想,golang的部署可以比php更方便,使用go get和http.ServeAndListen()可以不用nginx和apache

对于文件改动重新编译其实并不是大问题,看pilu/fresh - GitHub,其实你自己写shell脚本(也可以直接用go写,因为它本身就是系统语言)监控文件系统改动然后自动重新build,即使是C/C++的项目这也不是大问题,人们不用C/C++写web是因为它们不是写web app的最佳选择

golang写的代码编译通过后,要比scripting language鲁棒,因为go compiler强制一些最佳实践

docker有个啥用啊

举个栗子,小明写了一个CMS系统,该系统的技术栈非常广,需要依赖于各种开源库和中间件.如果按照纯手动的部署方式,小明需要安装各种开源软件,还需要写好每个开源软件的配置文件.如果只是部署一次,这点时间开销还是可以接受的,但如果小明每隔几天就需要换个服务器去部署他的程序,那么这些繁琐的重复工作无疑是会令人发狂的.这时候,Docker的用处就派上场了,小明只需要根据应用程序的部署步骤编写一份dockerfile文件(将安装、配置等操作交由Docker自动化处理),然后构建并发布他的镜像,这样,不管在什么机器上,小明都只需要拉取他需要的镜像,然后就可以直接部署运行了,这正是Docker的魅力所在.

那么镜像又是什么呢?镜像是Docker中的一个重要概念:

Image(镜像):它类似于虚拟机中使用到的镜像,由于任何应用程序都需要有它自己的运行环境,Image就是用来提供所需运行环境的一个模板.

Container(容器):Container是Docker提供的一个抽象层,它就像一个轻量级的沙盒,其中包含了一个极简的Linux系统环境与运行在其中的应用程序.Container是Image的运行实例(Image本身是只读的,Container启动时,Docker会在Image的上层创建一个可写层,任何在Container中的修改都不会影响到Image,如果想要在Image保存Container中的修改,Docker采用了基于Container生成新的Image层的策略),Docker引擎利用Container来操作并隔离每个应用(也就是说,每个容器中的应用都是互相独立的).

其实从Docker与Container的英文单词原意中就可以体会出Docker的思想.Container可以释义为集装箱,集装箱是一个可以便于机械设备装卸的封装货物的通用标准规格,它的发明简化了物流运输的机械化过程,使其建立起了一套标准化的物流运输体系.而Docker的意思为码头工人,可以认为,Docker就像是在码头上辛勤工作的工人,把应用打包成一个个具有某种标准化规格的"集装箱"(其实这里指出的集装箱对应的是Image,在Docker中Container更像是一个运行中的沙盒),当货物运输到目的地后,码头工人们(Docker)就可以把集装箱拆开取出其中的货物(基于Image来创建Container并运行).这种标准化与隔离性可以很方便地组合使用多个Image来构建你的应用环境(Docker也提倡每个Image都遵循单一职责原则,也就是只做好一件事),或者与其他人共享你的Image

以上就是土嘎嘎小编为大家整理的基于go语言的中间件相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!

版权声明:倡导尊重与保护知识产权。未经许可,任何人不得复制、转载、或以其他方式使用本站《原创》内容,违者将追究其法律责任。本站文章内容,部分图片来源于网络,如有侵权,请联系我们修改或者删除处理。

编辑推荐

热门文章