go 微服务的创建与调用

安装 proto

$cd /usr/local 
$sudo wget https://github.com/protocolbuffers/protobuf/releases/download/v3.20.1/protoc-3.20.1-linux-x86_64.zip
$sudo mkdir protoc
$cd protoc
$sudo unzip ../protoc-3.20.1-linux-x86_64.zip
$cd bin
$sudo cp protoc /xxx #复制到$GOPATH/bin目录下
$protoc --version

安装 protoc-gen-go

我是在 deepin 的linux系统里安装的,go 项目管理使用了 go mod。

按网络上找的教程

go get github.com/golang/protobuf/protoc-gen-go

执行上述命令就会在 $GOPATH/bin 目录下生成 protoc-gen-go 可执行文件。
我按上述操作一直无法生成 protoc-gen-go 可执行文件,只是把 github.com/golang/protobuf/protoc-gen-go 及所需的包 下载到了 $GOPATH/pkg/mod 目录下了。
后面一直百度查询与尝试,成功在 $GOPATH/bin 目录下生成 protoc-gen-go 可执行文件

  1. go get google.golang.org/protobuf/cmd/protoc-gen-go
  2. go install google.golang.org/protobuf/cmd/protoc-gen-go
    上述两个命令 是在项目下执行的(项目下有 go.mod 文件)

安装 protoc-gen-micro

go get github.com/micro/micro/v2/cmd/protoc-gen-micro

go install github.com/micro/micro/v2/cmd/protoc-gen-micro

上述操作直接在 $GOPATH/bin 目录生成了 protoc-gen-micro 可执行文件,生成的 protoc-gen-micro 是v2版本的。
上述两个命令 是在项目下执行的(项目下有 go.mod 文件)

生成 v3 版本的

go install github.com/asim/go-micro/cmd/protoc-gen-micro/v3@latest

将 .proto 文件转换成 store.pb.go 文件

新增文件 store.proto ,在 目录 frame.service 下

syntax = "proto3";
package store.srv;

service Store{
    rpc GetStoreDetail(StoreIdRequest) returns(StoreInfoResponse);
}

// 请求参数
message StoreIdRequest {
    string id = 1;
}

// 返回参数
message StoreInfoResponse{
    string id = 1;
}
}

protoc --proto_path=. --go_out=. store.proto

执行上述命令,报错:

protoc-gen-go: unable to determine Go import path for "store.proto"

Please specify either:
        • a "go_package" option in the .proto source file, or
        • a "M" argument on the command line.

See https://developers.google.com/protocol-buffers/docs/reference/go-generated#package for more information.

--go_out: protoc-gen-go: Plugin failed with status code 1.

解决方式:
在 student.proto 文件内加上一行:

option go_package = “./proto”;

文件最终内容如下:

syntax = "proto3"; // 指定版本
package store.srv; // 指定包名
option go_package = "./proto";  // 指定生成位置

service Store{
    rpc GetStoreDetail(StoreIdRequest) returns(StoreInfoResponse);
}

// 请求参数
message StoreIdRequest {
    string id = 1;
}

// 返回参数
message StoreInfoResponse{
    string id = 1;
}
protoc --proto_path=. --go_out=. store.proto 命令解析

protoc 命令详解

$ protoc
用法: protoc [OPTION] PROTO_FILES
解析proto文件并根据给定的选项生成输出:
  -IPATH, --proto_path=PATH   指定搜索目录,可多次指定,默认为当前工作目录。
  --version                   显示版本信息并退出
  -h, --help                  显示帮助文档并退出
  --encode=MESSAGE_TYPE       从标准输入读取给定类型的文本格式消息,从标准输出写入二进制文件。消息类型必须在原始文件或导入中定义。
  --decode=MESSAGE_TYPE       从标准输入中读取给定类型的二进制消息,向标准输出中写入文本格式。消息类型必须定义在proto文件或其导入的文件中。
  --decode_raw                从标准输入读取任意协议消息,向标准输出写入原始标记或文本格式的值。
  --descriptor_set_in=FILES   指定文件分隔符列表,每个都包含了一个文件描述符集合。
  -oFILE,                     写入FileDescriptorSet
  --include_imports           当使用--descriptor_set_out时, 同时包含输入文件的依赖项
  --include_source_info       当使用--descriptor_set_out时无需剥离FileDescriptorProto中的SourceCodeInfo
  --dependency_out=FILE       指定依赖输出文件
  --error_format=FORMAT       设置打印错误格式,默认gcc,可选msvs。
  --print_free_field_numbers  打印给定proto文件中消息定义的可用字段号
  --plugin=EXECUTABLE         指定使用插件的可执行文件
  --cpp_out=OUT_DIR           产生C++头文件和源文件
  --csharp_out=OUT_DIR        产生C#源文件
  --java_out=OUT_DIR          产生Java源文件
  --javanano_out=OUT_DIR      产生Java Nano源文件
  --js_out=OUT_DIR            产生JavaScript源文件
  --objc_out=OUT_DIR          产生Objective C头文件和源文件
  --php_out=OUT_DIR           产生PHP源文件
  --python_out=OUT_DIR        产生Python源文件
  --ruby_out=OUT_DIR          产生Ruby源文件
  @<filename>                 从文件中读取选项和文件名

–proto_path=PATH 指定搜索目录,可多次指定,默认为当前工作目录。
–go_out=. 产生GO源文件目录,默认为当前工作目录。
store.proto 转换执行的 proto 文件

生成 store.pb.micro.go 文件

protoc --go_out=. --micro_out=. store.proto

规则与上面生成 store.pb.go 一样。上述命令是 同时生成 store.pb.go,store.pb.micro.go 两个文件

安装 consul 服务发现软件

这个可以直接使用 docker 安装

docker pull consul

运行

docker run -itd --name consul -p 8500:8500 consul:latest

查询日志

docker logs 4e90f273e754

暴露 8500 端口,方便本地查看服务信息
127.0.0.1:8500 / 0.0.0.0:8500 访问,可以查看 consul 的服务信息

正式开启一个微服务项目

上面几步操作完成后 可以生成 store.pb.go,store.pb.micro.go 两个文件。
新建 store 微服务的 实现文件方法:store.service.go

package proto

import (
	"context"
	"fmt"
)

type StoreServiceDemo struct {}

func (s *StoreServiceDemo) GetStoreDetail(context.Context, *StoreIdRequest, *StoreInfoResponse) error {
	fmt.Println("GetStoreDetail")
	rep.Id = req.Id
	rep.StoreName = "StoreName"
	rep.Bindphone = "Bindphone"
	rep.Email = "Email"
	return nil
}

这里的 结构体可以随意命名,但结构体必须实现 store.proto 文件里的 GetStoreDetail 微服务方法。

之后就是写启动微服务的代码了,如下

package main

import (
	"fmt"
	"frame.service/proto"
	"github.com/micro/go-micro/v2"
	"github.com/micro/go-micro/v2/registry"
	"github.com/micro/go-plugins/registry/consul/v2"
)

func main() {
	//连接 consul
	ConsulClient := consul.NewRegistry(registry.Addrs("127.0.0.1:8500"))

	service := micro.NewService(
		micro.Name("go.micro.srv.test"),
		micro.Version("latest"),
		micro.Registry(ConsulClient),		// 服务注册到 consul
	)

	// Register Handler
	_ = proto.RegisterStoreHandler(service.Server(), new(proto.StoreServiceDemo))

	_ = service.Run()
}

上述代码分几步

  1. 连接 consul
  2. 创建 micro 服务:设定服务名称,版本,服务注册位置(这里是把服务注册到连接的 consul)
  3. 注册服务 Store
  4. 启动微服务

之后就可以在 consul 127.0.0.1:8500 上看到新注册的微服务了
在这里插入图片描述

微服务访问

这里我是用 gin 访问成功,新建目录 api,api 下生成 proto 的 store.pb.go 和 store.pb.micro.go 两个文件。代码如下

package main

import (
	"context"
	"encoding/json"
	"log"
	"net/http"

	storeService "frame.service/api/proto"

	"github.com/micro/go-micro/v2"
	"github.com/micro/go-micro/v2/registry"
	"github.com/micro/go-plugins/registry/consul/v2"

	"github.com/gin-gonic/gin"
)

func main() {
	// gin 路由
	router := gin.Default()

	router.GET("/", func(c *gin.Context) {
		// consul 
		consulReg := consul.NewRegistry(func(options *registry.Options) {
			options.Addrs = []string{"127.0.0.1:8500"}
		})
		service := micro.NewService(
			micro.Registry(consulReg),
		)
		
		// 连接 go.micro.srv.test 微服务
		mc := storeService.NewStoreService("go.micro.srv.test", service.Client())

		// 请求 go.micro.srv.test 微服务 的 GetStoreDetail 方法
		resp, err := mc.GetStoreDetail(context.TODO(), &storeService.StoreIdRequest{Id: "123465"})
		if err != nil {
			log.Println(err.Error())
			c.String(http.StatusBadRequest, "hello")
			return
		}

		// 输出结果
		respStr, _ := json.Marshal(resp)
		c.String(http.StatusOK, string(respStr))

	})

	// 启动路由
	router.Run(":8848")
}

gin 访问结果如下:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,针对你的问题,我可以为你提供以下回答: 在 PHP 微服务中,可以通过使用 Guzzle HTTP 客户端库来进行 HTTP 调用。具体来说,你可以通过以下步骤来实现服务调用: 1. 安装 Guzzle HTTP 客户端库 可以通过 Composer 进行安装,命令如下: ``` composer require guzzlehttp/guzzle ``` 2. 创建 Guzzle HTTP 客户端 在 PHP 中使用 Guzzle HTTP 客户端可以方便地进行 HTTP 请求。具体来说,你可以通过以下代码创建一个 Guzzle HTTP 客户端: ```php $client = new \GuzzleHttp\Client(); ``` 3. 发送 HTTP 请求 在创建了 Guzzle HTTP 客户端之后,你就可以使用该客户端发送 HTTP 请求了。具体来说,你可以使用 `request` 方法来发送请求,如下所示: ```php $response = $client->request('GET', 'http://example.com/api/users'); ``` 其中,第一个参数表示请求方法,第二个参数表示请求的 URL。此外,你还可以通过第三个参数来传递请求参数,例如: ```php $response = $client->request('POST', 'http://example.com/api/users', [ 'form_params' => [ 'username' => 'john.doe', 'password' => 'secret', ], ]); ``` 4. 处理响应结果 在发送了 HTTP 请求之后,你可以通过 `getBody` 方法来获取响应结果,例如: ```php $body = $response->getBody(); ``` 此外,你还可以通过 `getStatusCode` 方法来获取响应状态码,例如: ```php $status = $response->getStatusCode(); ``` 以上就是在 PHP 微服务中进行 HTTP 调用的基本步骤,希望对你有所帮助。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值