0.micro框架

在了解go-micro之前,我们先来了解一下什么是micro。

Micro是一个专注于简化分布式系统开发的微服务生态系统。由开源库和工具组成。主要包含以下几种库:

  • go-micro用于编写微服务的可插入Go-RPC框架; 服务发现,客户端/服务器rpc,pub/sub等,是整个Micro的核心。

    默认使用mdns做服务发现,可以在插件中替换成consul,etcd,k8s等

  • go-pluginsgo-micro的插件,包括etcd,kubernetes(k8s),nats,rabbitmq,grpc等

  • micro一个包含传统入口点的微服务工具包; API网关,CLI,Slack Bot,Sidecar和Web UI。

其他各种库和服务可以在github.com/micro找到。

我们先来了解一下服务发现是个什么东西?有什么作用?

1.服务发现

我们在做微服务开发的时候,客户端的一个接口可能需要调用N个服务,客户端必须知道所有服务的网络位置(ip+port),如下图所示

以往的做法是把服务的地址放在配置文件活数据库中,这样就有以下几个问题:

  • 需要配置N个服务的网络位置,加大配置的复杂性
  • 服务的网络位置变化,需要改变每个调用者的配置
  • 集群的情况下,难以做负载(反向代理的方式除外)

总结起来一句话:服务多了,配置很麻烦,问题一大堆

所以现在就选择服务发现来解决这些问题。我们来看一下,服务发现如何解决这个问题,具体设计如下:
与之前解决方法不同的是,加了个服务发现模块。服务端把当前自己的网络位置注册到服务发现模块(这里注册的意思就是告诉),服务发现就以K-V的方式记录下,K一般是服务名,V就是IP:PORT。服务发现模块定时的轮询查看这些服务能不能访问的了(这就是健康检查)。客户端在调用服务A-N的时候,就跑去服务发现模块问下它们的网络位置,然后再调用它们的服务。这样的方式是不是就可以解决上面的问题了呢?客户端完全不需要记录这些服务的网络位置,客户端和服务端完全解耦!

常见的服务发现框架有:Etcd、Eureka、Consul、Zookeeper

这里我们选择go-micro默认的服务发现框架consul来做一个详细介绍。

2.了解consul并使用

Consul是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置。包含多个组件,但是作为一个整体,为你的基础设施提供服务发现和服务配置的工具.他提供以下关键特性:

服务发现:consul通过DNS或者HTTP接口使服务注册和服务发现变的很容易,一些外部服务,例如saas提供的也可以一样注册。

健康检查:健康检测使consul可以快速的告警在集群中的操作。和服务发现的集成,可以防止服务转发到故障的服务上面。(心跳机制)

键/值存储:一个用来存储动态配置的系统。提供简单的HTTP接口,可以在任何地方操作。

多数据中心:无需复杂的配置,即可支持任意数量的区域。

官方建议:最好是三台或者三台以上的consul在运行,同名服务最好是三台或三台以上,默认可以搭建集群

2.1consul安装

​Consul用Golang实现,因此具有天然可移植性 (支持 Linux、windows和macOS)。安装包仅包含一个可执行文件。 Consul安装非常简单,只需要下载对应系统的软件包并解压后就可使用。

安装步骤如下:

# 这里以 ubuntu系统为例:
$ wget https://releases.hashicorp.com/consul/1.5.2/consul_1.5.2_linux_amd64.zip
$ unzip consul_1.5.2_linux_amd64.zip
$ sudo mv consul /usr/local/bin/

也可用离线包进行解压安装
链接:https://pan.baidu.com/s/1OQoAdn2_IrWbYbQUCg3_zQ
提取码:a4rd
安装验证:

安装 Consul后,通过执行 consul命令,你可以看到命令列表的输出

~ consul

无报错即为成功

2.2 consul的命令行

consul安装好之后,我们来使用一下吧。首先我们来看一下consul都有哪些命令。使用命令consul -h可以查看consul支持的所有参数,而且每个参数里面还支持其他参数,下面我们来具体看看。

agent指令是consul的核心,它运行agent来维护成员的重要信息、运行检查、服务宣布、查询处理等等。

-bind=0.0.0.0       指定 consul所在机器的 IP地址。 默认值:0.0.0.0
-http-port=8500    consul 自带一个web访问的默认端口:8500
-client=127.0.0.1   表明哪些机器可以访问consul 。 默认本机。0.0.0.0 所有机器均可访问。
-config-dir=foo      所有主动注册服务的 描述信息
-data-dir=path       储存所有注册过来的srv机器的详细信息。
-dev                         开发者模式,直接以默认配置启动 consul
-node=hostname  服务发现的名字。
-rejoin                     consul 启动的时候,加入到的 consul集群
-server                    以服务方式开启consul, 允许其他的consul 连接到开启的 consul上 (形成集群)。如果不加 -server, 表示以 “客户端” 的方式开启。不能被连接。
-ui                           可以使用 web 页面 来查看服务发现的详情

测试上述命令:

# 在终端中,键入:
consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -node=n1 -bind=192.168.6.108 -ui -rejoin -config-dir=/etc/consul.d/ -client 0.0.0.0#看到提示:
==> Consul agent running!

需要先在/etc/下面创建consul.d目录

  • -server : 定义agent运行在server模式
  • -bootstrap-expect :在一个datacenter中期望提供的server节点数目,当该值提供的时候,consul一直等到达到指定sever数目的时候才会引导整个集群,该标记不能和bootstrap共用
  • -bind:该地址用来在集群内部的通讯,集群内的所有节点到地址都必须是可达的,默认是0.0.0.0
  • -node:节点在集群中的名称,在一个集群中必须是唯一的,默认是该节点的主机名
  • -ui: 启动web界面 :8500
  • -rejoin:使consul忽略先前的离开,在再次启动后仍旧尝试加入集群中。
  • -config-dir:配置文件目录,里面所有以.json结尾的文件都会被加载
  • -client:consul服务侦听地址,这个地址提供HTTP、DNS、RPC等服务,默认是127.0.0.1所以不对外提供服务,如果你要对外提供服务改成0.0.0.0
  • data-dir:提供一个目录用来存放agent的状态,所有的agent允许都需要该目录,该目录必须是稳定的,系统重启后都继续存在

启动 Google 浏览器, 测试:

2.2.1停止consul

你可以使用Ctrl-C 不优雅的关闭Agent. 中断Agent之后你可以看到他离开了集群并关闭.

​在退出中,Consul提醒其他集群成员,这个节点离开了.如果你强行杀掉进程.集群的其他成员应该能检测到这个节点失效了.当一个成员离开,他的服务和检测也会从目录中移除.当一个成员失效了,他的健康状况被简单的标记为危险,但是不会从目录中移除.Consul会自动尝试对失效的节点进行重连.允许他从某些网络条件下恢复过来.离开的节点则不会再继续联系.

​此外,如果一个agent作为一个服务器,一个优雅的离开是很重要的,可以避免引起潜在的可用性故障影响达成一致性协议.
consul优雅的退出:

$ consul leave

2.2.2注册服务

搭建好conusl集群后,用户或者程序就能到consul中去查询或者注册服务。可以通过提供服务定义文件或者调用HTTP API来注册一个服务.

这里我们使用定义服务文件来注册一个服务:

{"service": {"name": "Faceid","tags": ["rails"],"port": 9000}
}

服务定义文件在我们的配置目录下面,/etc/consul.d/,文件都是以.json结尾。

注册完服务之后,我们重启consul。

2.2.3查询服务

一旦agent启动并且服务同步了.我们可以通过DNS或者HTTP的API来查询服务.这里我们通过HTTP来查询服务:

$ curl -s 127.0.0.1:8500/v1/catalog/service/faceid

可以得到一串json数据,可拿去进行json格式解析,还可以打开web页面,查看注册的服务。默认consul对应的端口是8500,在浏览器输入地址`localhost:8500,也可以看到注册的服务

2.2.4健康检查

健康检查是服务发现的关键组件.预防使用到不健康的服务.和服务注册类似,一个检查可以通过检查定义或HTTP API请求来注册.我们将使用和检查定义来注册检查.和服务类似,因为这是建立检查最常用的方式.

在/etc/consul.d/目录下面创建文件web2.json,内容如下:

{"service": {"name": "web","tags": ["extract", "verify", "compare", "idcard"],"address": "192.168.137.130","port": 9000,"check": {"id": "api","name": "HTTP API on port 9000","http": "http://localhost:9000","interval": "10s","timeout": "1s"}}
}

如果我们没有开启服务,那么健康检查一定会报错

consul做健康检查的必须是Script、HTTP、TCP、TTL中的一种。
Script类型需要提供Script脚本和interval变量。**具体配置如下:

{  "check": {  "id": "mem-util",  "name": "Memory utilization",  "script": "/usr/local/bin/check_mem.py",  "interval": "10s",  "timeout": "1s"  }
}

通过执行外部应用进行健康检查:这种外部程序具有退出代码,并可能产生一些输出;脚本按照指预置时间间隔来调用(比如,每30秒调用一次),类似于Nagios插件系统,脚本输出限制在4K以内,输出大于4K将截断。默认情况下,脚本超时时间为30秒——可通过timeout来配置。

HTTP类型必须提供http和Interval字段。具体代码如下:

{  "check": {  "id": "api",  "name": "HTTP API on port 5000",  "http": "http://localhost:5000/health",  "interval": "10s",  "timeout": "1s"  }
}

这种检查将按照预设的时间间隔创建一个HTTP “get”请求。HTTP响应代码来标示服务所处状态:任何2xx代码视为正常,429表示警告——有很多请求;其他值表示失败。
这种类型的检查应使用curl或外部程序来处理HTTP操作。默认情况下,HTTP Checks中,请求超时时间等于调用请求的间隔时间,最大10秒。有可能使用客制的HTTP check,可以自由配置timeout时间,输出限制在4K以内,输出大于4K将截断。

TCP类型需要提供tcp和Interval字段。具体代码如下:

{  "check": {  "id": "ssh",  "name": "SSH TCP on port 22",  "tcp": "localhost:22",  "interval": "10s",  "timeout": "1s"  }
}

这种检查将按照预设的时间间隔与指定的IP/Hostname和端口创建一个TCP连接。服务的状态依赖于TCP连接是否成功——如果连接成功,则状态是“success”;否则状态是“critical”。如果一个Hostname解析为一个IPv4和一个IPv6,将尝试连接这两个地址,第一次连接成功则服务状态是“success”。默认情况下,TCP checks中,请求超时时间等于调用请求的间隔时间,最大10秒。也是可以自由配置的。

TTL(Timeto Live生存时间)类型只需提供ttl,具体配置如下:

{  "check": {  "id": "web-app",  "name": "Web App Status",  "notes": "Web app does a curl internally every 10 seconds",  "ttl": "30s"  }
}

这种checks为给定TTL保留了最后一种状态,checks的状态必须通过HTTP接口周期性更新,如果外部接口没有更新状态,那么状态就会被认定为不正常。 TTL checks同时会将其最后已知状态更新至磁盘,这允许Agent通过重启后恢复到已知的状态。通过TTL端上一次check来维持健康状态的有效性。

其他更多consul功能,我们可以参考http://www.liangxiansen.cn/2017/04/06/consul/

2.3consul和grpc结合使用

先从GitHub下载consul包

$ go get -u -v github.com/hashicorp/consul

将grpc服务注册到consul上

  1. 创建 proto文件, 指定 rpc 服务
  2. 启动 consul 服务发现
  3. 启动server
    1. 获取consul 对象。
    2. 使用 consul对象,将 server 信息,注册给 consul
    3. 启动服务
  4. 启动client
    1. 获取consul 对象。
    2. 使用consul对象,从consul 上获取健康的 服务。
    3. 再访问服务 (grpc远程调用)

代码示例:
proto文件:

syntax = "proto3";package pb;message Person {string name = 1;int32 age = 2;
}// 添加 rpc服务
service hello {rpc sayHello (Person) returns (Person);
}

服务端:

package mainimport ("google.golang.org/grpc""day02/pb""context""net""fmt""github.com/hashicorp/consul/api"
)// 定义类
type Children struct {
}// 绑定类方法, 实现借口
func (this *Children)SayHello(ctx context.Context, p *pb.Person) (*pb.Person, error) {p.Name = "hello  " + p.Namereturn p, nil
}func main()  {// 把grpc服务,注册到consul上.// 1. 初始化consul 配置consulConfig := api.DefaultConfig()// 2. 创建 consul 对象consulClient, err := api.NewClient(consulConfig)if err != nil {fmt.Println("api.NewClient err:", err)return}// 3. 告诉consul, 即将注册的服务的配置信息reg := api.AgentServiceRegistration {ID:"bj38",Tags:[]string{"grcp", "consul"},Name:"grpc And Consul",Address:"127.0.0.1",Port:8800,Check:&api.AgentServiceCheck{CheckID:"consul grpc test",TCP:"127.0.0.1:8800",Timeout:"1s",Interval:"5s",},}// 4. 注册 grpc 服务到 consul 上consulClient.Agent().ServiceRegister(&reg)//以下为 grpc 服务远程调用// 1.初始化 grpc 对象,grpcServer := grpc.NewServer()// 2.注册服务pb.RegisterHelloServer(grpcServer, new(Children))// 3.设置监听, 指定 IP/portlistener, err := net.Listen("tcp", "127.0.0.1:8800")if err != nil {fmt.Println("Listen err:", err)return}defer listener.Close()fmt.Println("服务启动... ")// 4. 启动服务grpcServer.Serve(listener)}

客户端:

package mainimport ("google.golang.org/grpc""day02/pb""context""fmt""github.com/hashicorp/consul/api""strconv"
)func main()  {// 初始化 consul 配置consulConfig := api.DefaultConfig()// 创建consul对象 -- (可以重新指定 consul 属性: IP/Port , 也可以使用默认)consulClient, err := api.NewClient(consulConfig)// 服务发现. 从consuL上, 获取健康的服务services, _, err := consulClient.Health().Service("grpc And Consul", "grcp", true, nil)// 简单的负载均衡.addr := services[0].Service.Address + ":" + strconv.Itoa(services[0].Service.Port)//以下为 grpc 服务远程调用///// 1. 链接服务//grpcConn, _ := grpc.Dial("127.0.0.1:8800", grpc.WithInsecure())// 使用 服务发现consul 上的 IP/port 来与服务建立链接grpcConn, _ := grpc.Dial(addr, grpc.WithInsecure())// 2. 初始化 grpc 客户端grpcClient := pb.NewHelloClient(grpcConn)var person pb.Personperson.Name = "Andy"person.Age = 18// 3. 调用远程函数p, err := grpcClient.SayHello(context.TODO(), &person)fmt.Println(p, err)
}

3go-micro框架

做了这么久的铺垫,接着让我们来进入主题,go-micro的学习。

3.1go-micro安装

首先我们先来安装一下go-micro开发环境。安装步骤如下:

#安装go-micro
go get -u -v github.com/micro/go-micro
#安装工具集
go get -u -v github.com/micro/micro
#安装protobuf插件
go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
go get -u github.com/micro/protoc-gen-micro

或者通过docker镜像安装:

$ docker pull microhq/micro

安装之后输入micro命令,显示如下就证明安装成功

3.2go-micro使用

首先我们先来创建一个go micro框架的项目,创建项目我们使用micro命令,micro类似于beego框架中的beego,可以创建微服务,web项目等,具体用法如下:

new      Create a new Micro service by specifying a directory path relative to your $GOPATH
#创建 通过指定相对于$GOPATH的目录路径,创建一个新的微服务。USAGE:
#用法
micro new [command options][arguments...]
#指定服务的命名空间
--namespace "go.micro"    Namespace for the service e.g com.example
#服务类型,可以是微服务src,或者web项目web,或者是api等
--type "srv"          Type of service e.g api, fnc, srv, web
#服务的正式定义全面
--fqdn                  FQDN of service e.g com.example.srv.service (defaults to namespace.type.alias)
#别名是在指定时作为组合名的一部分使用的短名称  别名
--alias                 Alias is the short name used as part of combined name if specified

创建一个web项目

micro new --type "web" micro/rpc/web
Creating service go.micro.web.web in /home/itcast/go/src/micro/rpc/web
.
#主函数
├── main.go
#插件文件
├── plugin.go
#被调用处理函数
├── handler
│   └── handler.go
#前端页面
├── html
│   └── index.html
#docker生成文件
├── Dockerfile
├── Makefile
└── README.md#编译后将web端呼叫srv端的客户端连接内容修改为srv的内容
#需要进行调通

创建微服务

$micro new --type "srv" t1/t1
#"srv" 是表示当前创建的微服务类型
#micro是相对于go/src下的文件夹名称 可以根据项目进行设置
#srv是当前创建的微服务的文件名
Creating service go.micro.srv.srv in /home/itcast/go/src/t1/t1.
#主函数存放位置
├── main.go
#插件
├── plugin.go
#服务提供函数的实现
├── handler
│   └── example.go
#订阅服务
├── subscriber
│   └── example.go
#proto协议
├── proto/example
│   └── example.proto
#docker生成文件
├── Dockerfile
#编译文件
├── Makefile
└── README.md#插件提示,已安装,可忽略
download protobuf for micro:brew install protobuf
go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
go get -u github.com/micro/protoc-gen-microcompile the proto file example.proto:cd /home/itcast/go/src/micro/rpc/srv
protoc --proto_path=. --go_out=. --micro_out=. proto/example/example.proto

go-micro框架创建完成后即可对其文件中的代码进行相应修改,实现自己的项目需求。

go-micro框架相关推荐

  1. 牌类游戏使用微服务重构笔记(四): micro框架使用经验

    项目依赖 推荐使用go module, 我选择go module的最主要原因是足够简单,可以脱离gopath,就跟写nodejs一样,随便在一个地方新建一个文件夹就可以撸代码了,clone下来的源码也 ...

  2. C# WPF Caliburn.Micro框架下利用Mef加载其它项目界面

    01 - 前言 MEF是微软自家的托管可扩展框架,在这里我把它用成了ioc容器.在Caliburn.Micro框架下,view和viewmodel被注入到CompositionContainer容器中 ...

  3. C# WPF MVVM模式Caliburn.Micro框架下事件发布与订阅

    01 - 前言 处理同模块不同窗体之间的通信和不同模块之间不同窗体的通信,Caliburn提供了一种事件机制,可以在应用程序中低耦合的模块之间进行通信,该机制基于事件聚合器服务,允许发布者和订阅者之间 ...

  4. f12控制台如何查看consul_基于 Consul 的 Go Micro 客户端服务发现是如何实现的

    基于 Consul 的 Go Micro 客户端服务发现是如何实现的 由 学院君 创建于1年前, 最后更新于 1年前 版本号 #1 上篇分享我们介绍了基于 Consul 作为注册中心的 Go Micr ...

  5. C# WPF MVVM模式Prism框架下事件发布与订阅

    01 - 前言 处理同模块不同窗体之间的通信和不同模块之间不同窗体的通信,Prism提供了一种事件机制,可以在应用程序中低耦合的模块之间进行通信,该机制基于事件聚合器服务,允许发布者和订阅者之间通过事 ...

  6. C# WPF MVVM模式Prism框架从零搭建(经典)

    01 - 前言 目前最新的PRISM的版本是8.1.97,本节以6.3.0.0 讲解,可以在Github上获取PRISM的源码. Prism Github地址:https://github.com/P ...

  7. 找不到服务器micro,Go Micro服务发现

    服务发现,就是通过什么办法可以找到需要调用的服务的地址(ip和端口),因为只有拿到服务的地址,我们才可以连接服务,发送接口调用请求. 上一个章节,我们没说明两个服务直接是如何找到对方的,只是使用服务名 ...

  8. go-micro框架介绍

    go-micro介绍及环境搭建 一.micro框架介绍 1.1.概述 Micro是一个简化分布式开发的微服务生态系统,该系统为开发分布式应用程序提供了高效,便捷的模块构建.主要目的是简化分布式系统的开 ...

  9. MICRO和GO-MICRO

    createdtime 20211124 updatedtime 20211126 author venki.chen 一.是什么 1. 定义,是做什么用的? go micro是什么? go-micr ...

  10. micro、M3O微服务系列(一)

    本系列以go,micro3为主 文章目录 软件开发的预测 什么是微服务 为什么使用微服务 什么是micro 理清微服务的关键字 微服务必然涉及的服务发现 使用go和micro构建全球服务网络 隧道 路 ...

最新文章

  1. VmWare 与 宿主主机通信 STEP BY STEP (适用于刚開始学习的人)
  2. 引导类、扩展类、系统类加载器的使用及演示
  3. Go语言字符串和正则表达式
  4. 服务器启动时Webapp的web.xml中配置的加载顺序
  5. 音视频中的CBR,VBR,ABR
  6. Java 面向对象的设计原则
  7. kafka基础之核心概念
  8. mac eclipse 安装lombok_别再写getter,setter方法了,用Lombok来简化你的代码吧
  9. 如何在Ubuntu上安装MariaDB
  10. linux的vmstat命令,vmstat命令参数详解
  11. 计算机芯片级维修包括哪些,电脑芯片级维修教程
  12. mpa和pis_压力单位MPa/psi/bar之间的换算?
  13. R语言中常用的生物多样性指数的计算(Alpha,Beta,Gamma,功能多样性,系统发育多样性)
  14. 资源变现小程序添加折扣充值和折扣影票插件
  15. 1190 -- 找x
  16. element实现form表单动态添加email效果
  17. V_rep与vs2019开发环境配置
  18. 大类资产配置(三)市场择时能力模型T-M
  19. fMRI与MRI区别+名词解释+MRI中T1和T2的含义与区分
  20. 安全多方计算之六:秘密共享

热门文章

  1. 计算几何-Ang-Rad-Vector
  2. mysql收货地址表_收货地址表结构 以及创建修改流程
  3. php扩展geoIP的使用
  4. 【总结】解决MAPPO(Multi-Agent PPO)问题技巧
  5. Kruskal 重构树
  6. django-连接Oracle数据库
  7. 生物化学《第四章蛋白质》
  8. 菜鸡编程自学第一天-C语言
  9. java 软尾 铝_软尾入门车款:JAVA FURIA 27.5上市
  10. [Outlook] outlook如何实现自动CC和BCC邮件发送