当前位置: 首页 > 编程日记 > 正文

go微服务框架go-micro深度学习(一) 整体架构介绍

产品嘴里的一个小项目,从立项到开发上线,随着时间和需求的不断激增,会越来越复杂,变成一个大项目,如果前期项目架构没设计的不好,代码会越来越臃肿,难以维护,后期的每次产品迭代上线都会牵一发而动全身。项目微服务化,松耦合模块间的关系,是一个很好的选择,随然增加了维护成本,但是还是很值得的。

微服务化项目除了稳定性我个人还比较关心的几个问题:

一: 服务间数据传输的效率和安全性。

二: 服务的动态扩充,也就是服务的注册和发现,服务集群化。

三: 微服务功能的可订制化,因为并不是所有的功能都会很符合你的需求,难免需要根据自己的需要二次开发一些功能。

go-micro是go语言下的一个很好的rpc微服务框架,功能很完善,而且我关心的几个问题也解决的很好:

一:服务间传输格式为protobuf,效率上没的说,非常的快,也很安全。

二:go-micro的服务注册和发现是多种多样的。我个人比较喜欢etcdv3的服务服务发现和注册。

三:主要的功能都有相应的接口,只要实现相应的接口,就可以根据自己的需要订制插件。

业余时间把go-micro的源码系统地读了一遍,越读越感觉这个框架写的好,从中也学到了很多东西。就想整理一系列的帖子,把学习go-micro的心得和大家分享。

通信流程

go-micro的通信流程大至如下

Server监听客户端的调用,和Brocker推送过来的信息进行处理。并且Server端需要向Register注册自己的存在或消亡,这样Client才能知道自己的状态。

Register服务的注册的发现。

Client端从Register中得到Server的信息,然后每次调用都根据算法选择一个的Server进行通信,当然通信是要经过编码/解码,选择传输协议等一系列过程的。

如果有需要通知所有的Server端可以使用Brocker进行信息的推送。

Brocker 信息队列进行信息的接收和发布。

go-micro之所以可以高度订制和他的框架结构是分不开的,go-micro由8个关键的interface组成,每一个interface都可以根据自己的需求重新实现,这8个主要的inteface也构成了go-micro的框架结构。

这些接口go-micir都有他自己默认的实现方式,还有一个go-plugins是对这些接口实现的可替换项。你也可以根据需求实现自己的插件

这篇帖子主要是给大家介绍go-micro的主体结构和这些接口的功能,具体细节以后的文章我们再慢慢说:

Transort

服务之间通信的接口。也就是服务发送和接收的最终实现方式,是由这些接口定制的。

源码:


type Socket interface {Recv(*Message) errorSend(*Message) errorClose() error
}type Client interface {Socket
}type Listener interface {Addr() stringClose() errorAccept(func(Socket)) error
}type Transport interface {Dial(addr string, opts ...DialOption) (Client, error)Listen(addr string, opts ...ListenOption) (Listener, error)String() string
}复制代码

Transport 的Listen方法是一般是Server端进行调用的,他监听一个端口,等待客户端调用。

Transport 的Dial就是客户端进行连接服务的方法。他返回一个Client接口,这个接口返回一个Client接口,这个Client嵌入了Socket接口,这个接口的方法就是具体发送和接收通信的信息。

http传输是go-micro默认的同步通信机制。当然还有很多其他的插件:grpc,nats,tcp,udp,rabbitmq,nats,都是目前已经实现了的方式。在go-plugins里你都可以找到。

Codec

有了传输方式,下面要解决的就是传输编码和解码问题,go-micro有很多种编码解码方式,默认的实现方式是protobuf,当然也有其他的实现方式,json、protobuf、jsonrpc、mercury等等。

源码


type Codec interface {ReadHeader(*Message, MessageType) errorReadBody(interface{}) errorWrite(*Message, interface{}) errorClose() errorString() string
}type Message struct {Id     uint64Type   MessageTypeTarget stringMethod stringError  stringHeader map[string]string
}复制代码

Codec接口的Write方法就是编码过程,两个Read是解码过程。

Registry

服务的注册和发现,目前实现的consul,mdns, etcd,etcdv3,zookeeper,kubernetes.等等,


type Registry interface {Register(*Service, ...RegisterOption) errorDeregister(*Service) errorGetService(string) ([]*Service, error)ListServices() ([]*Service, error)Watch(...WatchOption) (Watcher, error)String() stringOptions() Options
}复制代码

简单来说,就是Service 进行Register,来进行注册,Client 使用watch方法进行监控,当有服务加入或者删除时这个方法会被触发,以提醒客户端更新Service信息。

默认的是服务注册和发现是consul,但是个人不推荐使用,因为你不能直接使用consul集群

我个人比较喜欢etcdv3集群。大家可以根据自己的喜好选择。

Selector

以Registry为基础,Selector 是客户端级别的负载均衡,当有客户端向服务发送请求时, selector根据不同的算法从Registery中的主机列表,得到可用的Service节点,进行通信。目前实现的有循环算法和随机算法,默认的是随机算法。

源码:

type Selector interface {Init(opts ...Option) errorOptions() Options// Select returns a function which should return the next nodeSelect(service string, opts ...SelectOption) (Next, error)// Mark sets the success/error against a nodeMark(service string, node *registry.Node, err error)// Reset returns state back to zero for a serviceReset(service string)// Close renders the selector unusableClose() error// Name of the selectorString() string
}复制代码

默认的是实现是本地缓存,当前实现的有blacklist,label,named等方式。

Broker

Broker是消息发布和订阅的接口。很简单的一个例子,因为服务的节点是不固定的,如果有需要修改所有服务行为的需求,可以使服务订阅某个主题,当有信息发布时,所有的监听服务都会收到信息,根据你的需要做相应的行为。

源码


type Broker interface {Options() OptionsAddress() stringConnect() errorDisconnect() errorInit(...Option) errorPublish(string, *Message, ...PublishOption) errorSubscribe(string, Handler, ...SubscribeOption) (Subscriber, error)String() string
}复制代码

Broker默认的实现方式是http方式,但是这种方式不要在生产环境用。go-plugins里有很多成熟的消息队列实现方式,有kafka、nsq、rabbitmq、redis,等等。

Client

Client是请求服务的接口,他封装Transport和Codec进行rpc调用,也封装了Brocker进行信息的发布。

源码


type Client interface {Init(...Option) errorOptions() OptionsNewMessage(topic string, msg interface{}, opts ...MessageOption) MessageNewRequest(service, method string, req interface{}, reqOpts ...RequestOption) RequestCall(ctx context.Context, req Request, rsp interface{}, opts ...CallOption) errorStream(ctx context.Context, req Request, opts ...CallOption) (Stream, error)Publish(ctx context.Context, msg Message, opts ...PublishOption) errorString() string
}复制代码

当然他也支持双工通信 Stream 这些具体的实现方式和使用方式,以后会详细解说。

默认的是rpc实现方式,他还有grpc和http方式,在go-plugins里可以找到

Server

Server看名字大家也知道是做什么的了。监听等待rpc请求。监听broker的订阅信息,等待信息队列的推送等。

源码


type Server interface {Options() OptionsInit(...Option) errorHandle(Handler) errorNewHandler(interface{}, ...HandlerOption) HandlerNewSubscriber(string, interface{}, ...SubscriberOption) SubscriberSubscribe(Subscriber) errorRegister() errorDeregister() errorStart() errorStop() errorString() string
}复制代码

默认的是rpc实现方式,他还有grpc和http方式,在go-plugins里可以找到

Service

Service是Client和Server的封装,他包含了一系列的方法使用初始值去初始化Service和Client,使我们可以很简单的创建一个rpc服务。

源码:


type Service interface {Init(...Option)Options() OptionsClient() client.ClientServer() server.ServerRun() errorString() string
}复制代码

具体的细节,我以后的帖子会给大家一一展开,希望这篇帖子,可以帮助你对go-micro的整体框架有个初步了解


转载于:https://juejin.im/post/5c74aa67e51d4518b656f912

相关文章:

多传感器融合之滤波(二)EKF

扩展卡尔曼滤波算法是解决非线性状态估计问题最为直接的一种处理方法,尽管EKF不是最精确的”最优“滤波器,但在过去的几十年成功地应用到许多非线性系统中。所以在学习非线性滤波问题时应该先从EKF开始。 EKF算法是将非线性函数进行泰勒展开,…

【Java】字符串(二)

目录 字符串格式化 日期和时间字符串格式化 日期格式化 时间格式化 格式化常见的日期时间组合 常见类型格式化 正则表达式(未完待续) 字符串生成器 字符串格式化 String类使用静态format()方法用于创建格式化的字符串。 format(String format&a…

为什么vue.js一眼看上去很美?

对其他框架我是佩服,对vue.js我则是爱。我就是一眼看上了vue.js,于是用它做各种东西,反反复复多次,然后觉得有些融会贯通,然后,我稍微细的思量了下,到底vue.js靓丽在哪? 还是上案例对比说明。这…

阿里云MWC 2019发布7款产品:Blink每秒可完成17亿次计算

在巴塞罗那举行的MWC 2019上,国内厂商不仅展示了目前的5G发展进程,也带来了一些云计算方面的进展。据报道,阿里云面向全球发布了7款产品,涵盖无服务器计算、高性能存储、全球网络、企业级数据库、大数据计算等主要云产品&#xff…

运用面向对象原则,设计一款音乐点唱机

2019独角兽企业重金招聘Python工程师标准>>> .设计内容及要求 能够实现简单的音乐播放器功能,如:打开本地文件,播放,暂停,停止,背景播放,单曲循环等等,界面充…

多传感器融合之滤波(三)--------

多传感器融合之滤波(三):IMU,GPS,Lidar,Ladar数据处理

【Codeforces】835B The number on the board (贪心)

把所有字符串上的数字加起来&#xff0c;看是否超过k&#xff0c;没有超过k的话&#xff0c;把字符串sort&#xff0c;从第一位开始&#xff0c;将字符变成9&#xff0c;直到sum大于等于k为止。 #include <iostream> #include <cstring> #include <string> …

拯救尴尬:鉴黄神器NSFW JS开源了!

近日&#xff0c;GitHub上开源了一款鉴定不雅内容的js库NSFW JS&#xff0c;你可以使用NSFW JS识别不雅内容&#xff0c;所有操作都只在客户端进行&#xff0c;甚至都不需要让文件离开用户的电脑。 演示地址&#xff1a;https://nsfwjs.com/ 项目地址&#xff1a;https://githu…

Linux下用于查看系统当前登录用户信息的4种方法

作为系统管理员&#xff0c;你可能经常会&#xff08;在某个时候&#xff09;需要查看系统中有哪些用户正在活动。有些时候&#xff0c;你甚至需要知道他&#xff08;她&#xff09;们正在做什么。本文为我们总结了4种查看系统用户信息&#xff08;通过编号&#xff08;ID&…

三维重建【一】——————(深度学习方式)

经典的计算机视觉问题是3-D重建。 基本上可以分成两种路径&#xff1a;一是多视角重建&#xff0c;二是运动重建。前者有一个经典的方法是多视角立体视觉&#xff08;MVS&#xff0c;multiple view stereo&#xff09;&#xff0c;就是多帧的立体匹配&#xff0c;这样采用CNN模…

【Codeforces】501B Misha and Changing Handles(map)

http://codeforces.com/problemset/problem/501/B map的应用&#xff0c;让新的名字作为key值&#xff0c;旧的名字作为value值&#xff0c;然后一一对应。如果这个旧名字不在map里&#xff0c;则添加进去&#xff1b;如果这个旧名字在map里&#xff0c;则需要进行替换&#x…

vue-cli3+typescript初体验

前言 气势汹涌&#xff0c;ts似乎已经在来的路上&#xff0c;随时可能敲门。2015年&#xff0c;三大前端框架开始火爆的时候&#xff0c;我还在抱着Backbone不放&#xff0c;一直觉得可以轻易转到其他框架去。后来换工作&#xff0c;现实把脸都打肿了&#xff0c;没做过vue、re…

三维重建【二】————3D reconstruction 较为实用的算法资料整理(传统方式)

本文结合一些pape并且将资源进行整合&#xff0c;以便于后期的学习。博客将这些资源一下&#xff0c;这里不得提到大名鼎鼎的KinectFusion以及他后面的一系列工作。KinectFusion单篇论文引用都已经超过3000次了&#xff0c;可以称得上是具有划时代意义的一篇巨著&#xff0c;如…

【Codeforces 738D】Sea Battle(贪心)

http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1  n grid. In this game a ships are placed on the grid. Each of the ships consists of bconsecutive cells. No cell can be part of two ships, however, the ships ca…

【POJ】3617 Best Cow Line (字典序 字符串)

http://poj.org/problem?id3617 给定长度为N(1≤N≤2000)的字符串S&#xff0c;要构造一个长度为N的字符串T。期初&#xff0c;T是一个空串&#xff0c;随后反复进行下列任意操作。 从S的头部删除一个字符&#xff0c;加到T的尾部 从S的尾部删除一个字符&#xff0c;加到T的…

python数据池连接PG

发现网上都是mysql&#xff0c;后面发现PG跟mysql差不多&#xff0c;记录下来&#xff0c;怕忘了 import psycopg2 from DBUtils.PooledDB import PooledDB import psycopg2.extraspool PooledDB(psycopg2, 10,database"boatdb", user"postgres",password…

ASP.NET WebAPi之断点续传下载(下)

前言 上一篇我们穿插了C#的内容&#xff0c;本篇我们继续来讲讲webapi中断点续传的其他情况以及利用webclient来实现断点续传&#xff0c;至此关于webapi断点续传下载以及上传内容都已经全部完结&#xff0c;一直嚷嚷着把SQL Server和Oracle数据库再重新过一遍&#xff0c;这篇…

Git学习记录(一)

git-book 全面资料 git 用树形查看 &#xff08;git 命令代替gitk查看节点树part two 日常使用只要记住下图6个命令即可&#xff0c;但是学海无涯啊 ​ 常用 Git 命令清单。几个专用名词的译名如下。 Workspace&#xff1a;工作区Index / Stage&#xff1a;暂存区Reposito…

【牛客】CSL 的字符串 (stack map)

https://ac.nowcoder.com/acm/contest/551/D 这个题怎么说&#xff0c;data用来存储这个字母在字符串中最后一次出现的位置&#xff0c;vis则用来记录该字母是否在栈中。 当栈为空的时候&#xff0c;直接将s[i]放入栈中 如果不为空则需要比较栈顶元素和当前s[i]的那个元素&a…

Python:UTF-8编码转换成GBK编码

2019独角兽企业重金招聘Python工程师标准>>> #!/usr/bin/env python # -*- coding:utf-8 -*- #UTF-8转换成GBK编码 #temp #decode #encode #原理就是把UTF-8转换成万国码&#xff0c;再给万国码进行编码转换成GBK&#xff0c;在python 2.x里面这么用 ""&q…

三维重建【三】-------------------(三维重建资料收集)

Major学者的个人主页汇总&#xff1a; 1.陈宝权&#xff1a;http://web.siat.ac.cn/~baoquan/ 2.南亮亮&#xff1a;http://web.siat.ac.cn/~liangliang/ 3.mueller&#xff1a;http://people.ee.ethz.ch/~pascmu/publications.html 4.Yasutaka Furukawa:http://homes.cs.washi…

在 Linux 中查看时区

1.date date "%Z %z"或者 date -R2.timedatectl timedatectl|grep "Timezone"可以使用 timedatectl 来设置 Linux 时区 3.显示文件 /etc/timezone 的内容 cat /etc/timezone

【HDU】1237 简单计算器 (stack)

http://acm.hdu.edu.cn/showproblem.php?pid1237 题目很好理解&#xff0c;一开始想用优先队列&#xff0c;但好像有点难实现&#xff0c;用stack比较好实现&#xff0c;遇到“ * ” 或者" / " 就进行操作&#xff0c;遇到“ - ” 就把它的相反数加进stack&#xf…

关于 synchronizeOnSession

本文为[原创]文章&#xff0c;转载请标明出处。原文链接&#xff1a;https://weyunx.com/2019/01/22...原文出自微云的技术博客 最近在维护一个老项目&#xff0c;发现了一个问题。我们新增了一个耗时较久的复杂查询的功能&#xff0c;页面采用了 ajax 异步请求数据&#xff0c…

用python操作mysql数据库(之“更新”操作)

#!/usr/bin/env python # -*- coding: utf-8 -*-import MySQLdb#建立连接 conn MySQLdb.connect(host127.0.0.1,userroot,passwd1qaz#EDC,dbtest_db) cur conn.cursor()#对数据进行操作 sql "update user set name%s where id7" #定义sql语句&#xff0c;用于修改…

OpenCV【零】—————cv::Mat——Mat对象创建方法

OpenCV (一)——Mat对象创建方法 目录 OpenCV (一)——Mat对象创建方法 1. cv::Mat优点及原理&#xff08;本质类&#xff09; 2. Mat类拷贝及对象的创建方法 3. Mat 对象元素的高效访问 4. 存储方法 5. 显式创建Mat对象 6. 与其他语言对比的方式 7. Mat操作实例 1. c…

在Vmware中安装Ubuntu

转载自&#xff1a;https://blog.csdn.net/stpeace/article/details/78598333 不是每一个程序员都必须玩过linux&#xff0c;只是博主觉得现在的很多服务器都是linux系统的&#xff0c;而自己属于那种前端也搞&#xff0c;后台也搞&#xff0c;对框架搭建也感兴趣&#xff0c;…

C++回声服务器_5-多进程版本

服务器和客户端都是用多进程来接收和发送数据。 服务器代码 #include <cstdio> #include <cstdlib> #include <cstring> #include <unistd.h> #include <csignal> #include <sys/wait.h> #include <arpa/inet.h> #include <sys/s…

OpenCV 【一】—— OpenCV中数组指针、图像分块计算、指针取像素值与MatToEigen方法,内存对齐

{ Topic1: 高效开辟内存&#xff0c;使适用于大型数组。//开辟新数组&#xff0c;或者开辟新的0或者某一数值的数组/Mat或者Map直接使用memset //大数组操作效率较高 举例1&#xff1a;cv::Mat cv_ncc_temp(cv_input_32f.rows, cv_input_32f.cols, CV_8UC1);memset(cv_ncc_temp…

【Java】类与对象 - 参数传值

目录 面向过程语言简介 面向对象语言简介 面向对象编程的三个特性 参数传值 传值机制 基本数据类型的参数的传值 引用类型参数的传值 可变参数 面向过程语言简介 核心是编写解决问题某个问题的代码块&#xff0c;代码块是程序执行时产生的一种行为。面向过程语言缺少一…