微服务:将一个服务写成多个模块。
image.png
image.png
image.png
系统性能方案:
image.png
image.png image.png
服务管理框架与服务是通过心跳包的方式保持通信。
RPC:
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
raft
image.pngimage.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
zookeeper:太重量级了,用于管理公司整个架构的大脑。
euerka:是主从式存储,不是分布式的,主从同步问题有延迟。
这里选用etcd。
选项设计模式
package main
import "fmt"
//结构体
type Options struct {
strOption1 string
strOption2 string
strOption3 string
intOption1 int
intOption2 int
intOption3 int
}
//选项设计模式
//声明一个函数类型的变量,用于传参
type Option func(opts *Options)
//初始化结构体
func InitOptionsl(opts ...Option){
options := &Options{}
//变量opts,得到每一个函数
for _,opt := range opts{
//调用函数,在函数里给传进去的对象赋值
opt(options)
}
fmt.Printf("init options %#v\n",options)
}
//定义具体给某个字段赋值的设计模式
func WithStrOption1(str string)Option{
return func(opts *Options) {
opts.strOption1 = str
}
}
func WithStrOption2(str string)Option{
return func(opts *Options) {
opts.strOption2 = str
}
}
func WithStrOption3(str string)Option{
return func(opts *Options) {
opts.strOption3 = str
}
}
func WithIntOption1(i int)Option{
return func(opts *Options) {
opts.intOption1 = i
}
}
func WithIntOption2(i int)Option{
return func(opts *Options) {
opts.intOption2 = i
}
}
func WithIntOption3(i int)Option{
return func(opts *Options) {
opts.intOption3 = i
}
}
func main(){
InitOptionsl(WithStrOption1("str1"),WithStrOption2("str2"),WithStrOption3("str3"),WithIntOption1(1),WithIntOption2(2),WithIntOption3(3))
}
image.png
服务注册
image.png
分析,类似于session中间件
- 定义服务注册总接口Registry,定义方法。
- Name():插件名,例如传etcd
- Init(opts ...Options):初始化不一样的时候可以使用选项设计模式。
- Regiter():服务注册
- Unregistr():服务反注册,例如服务端停了,注册列表销毁。
- GetService:服务发现(IP []port string)
- 抽象出一些结构体
- Node:单个节点的结构体,包含id,ip,port,weight(权重)
- Service:里面有服务名,节点列表。一个服务多台服务器支撑。
- 选项设计模式实现参数初始化
- 插件的管理类
- 可以用一个大map管理,key字符串,value是Registry接口对象
- 用户自定义去调用,自定义插件
- 实现注册中心得初始化,供系统使用。
etcd续期:
package etcd
import (
"context"
"fmt"
"github.com/coreos/etcd/clientv3"
"log"
"time"
)
func main(){
cli,err := clientv3.New(clientv3.Config{
Endpoints:[]string{"127.0.0.1:2379"},
DialTimeout:time.Second,
})
if err != nil{
log.Fatal(err)
}
defer cli.Close()
//设置续期5秒
resp,err := cli.Grant(context.TODO(),5)
if err != nil{
log.Fatal(err)
}
//将k-v设置到etcd
_,err = cli.Put(context.TODO(),"root","admin",clientv3.WithLease(resp.ID))
if err != nil{
log.Fatal(err)
}
//若想一直有效,设置自动续期
ch,err = cli.KeepAlive(context.TODO(),resp.ID)
if err != nil{
log.Fatal(err)
}
for {
c := <-ch
fmt.Println("c:",c)
}
}
etcd启动,查值
image.png image.png image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
1、编写proto文件
//版本号
syntax = "proto3"
//指定包名
package proto;
//定义结构体
message UserRequest{
//定义用户名
string name = 1;
}
//响应结构体
message UserResponse{
int32 id = 1;
string name = 2;
int32 age = 3;
//repeated修饰符是可变数组,go转切片
repeated string hobby = 4;
}
//service定义方法
service UserInfoService{
rpc GetUserInfo(UserRequest)returns(UserResponse){}
}
image.png
这里windows下一定要使用protoc.exe命令,同时参考此命令
protoc --plugin=protoc-gen-go=/f/gopath/bin/protoc-gen-go.exe --go_out=./ test.proto
要指定protoc-gen-go.exe 如果不指定.exe会报错protoc-gen-go不是内部命令。
json:"-"
:序列化和反序列化时忽略。
package main
import (
"context"
"fmt"
pb "github.com/cold-rivers-snow/study/lwz/gRPC/proto"
"google.golang.org/grpc"
"net"
)
//1、需要监听
//2、需要实例化gRPC服务端
//3、在个RPC上注册微服务
//4、启动服务端
type UserInfoService struct {
}
var u = UserInfoService{}
//实现方法
func (s *UserInfoService)GetUserInfo(ctx context.Context,req *pb.UserRequest)(resp *pb.UserResponse,err error){
//通过用户名查询用户信息
name := req.Name
//数据库里查用户信息
if name == "zs"{
resp = &pb.UserResponse{
Id:1,
Name:name,
Age:22,
Hobby:[]string{"Sing","Run"},
}
}
return
}
func main(){
//地址
addr := "127.0.0.1:8000"
//监听
listener,err := net.Listen("tcp",addr)
if err != nil{
fmt.Printf("监听异常:%s\n",err)
}
fmt.Printf("监听端口:%s\n",addr)
//2、实例化grpc
s := grpc.NewServer()
//3、在grpc上注册微服务
pb.RegisterUserInfoServiceServer(s,&u)
//4、启动服务端
s.Serve(listener)
}
image.png
package main
//1、连接服务器
//2、实例化grpc客户端
//3、调用
import (
"context"
"fmt"
pb "github.com/cold-rivers-snow/study/lwz/gRPC/proto"
"google.golang.org/grpc"
)
func main(){
//1、连接
conn,err := grpc.Dial("127.0.0.1:8000",grpc.WithInsecure())
if err != nil{
fmt.Printf("连接异常:%s\n",err)
}
defer conn.Close()
//2、实例化grpc客户端
client := pb.NewUserInfoServiceClient(conn)
//3、组装请求参数
req := new(pb.UserRequest)
req.Name = "zs"
//4、调用接口
response,err := client.GetUserInfo(context.Background(),req)
if err != nil{
fmt.Println("响应异常:%s\n",err)
}
fmt.Println("响应结果:%v\n",response)
}
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png image.png
image.png
image.png
image.png
image.png
image.png
hello.proto
syntax = "proto3";
//结构体
message InfoRequest{
string username = 1;
}
message InfoResponse{
string msg = 2;
}
//接口
service Hello{
rpc Info(InfoRequest)returns (InfoResponse){}
}
image.png
参考文章
server.go
package main
import (
"context"
"fmt"
pb "github.com/cold-rivers-snow/study/lwz/my-micro/01/proto"
"github.com/micro/go-micro"
"log"
)
//1、声明结构体
type Hello struct {
}
func (h *Hello)Info(ctx context.Context, req *pb.InfoRequest, rep *pb.InfoResponse) error{
rep.Msg = "你好" + req.Username
return nil
}
func main(){
//1、得到服务端实例
service := micro.NewService(
//设置微服务服务名,用于访问
//micro call hello Hello Info {"username":"zhangsan}
micro.Name("hello"),
)
//2、初始化
service.Init()
//3、服务注册
err := pb.RegisterHelloHandler(service.Server(),new(Hello))
if err != nil{
fmt.Println(err)
}
//4、启动服务
if err = service.Run(); err != nil{
log.Fatal(err)
}
}
命令访问方式:
image.png
API访问方式
api.proto
syntax = "proto3";
//结构体
message CallRquest{
string name = 1;
}
message CallResponse{
string message = 2;
}
service Example{
rpc Call(CallRquest)returns (CallResponse){};
}
message EmptyRquest{
}
message EmptyResponse{
}
service Foo{
rpc Bar(EmptyRquest)returns (EmptyResponse){};
}
proto文件执行命令:protoc.exe -I . --micro_out=. --go_out= . --plugin=protoc-gen-go=D:/code/ubuntu_code/Go/bin/protoc-gen-go.exe --plugin=protoc-gen-micro=D:/code/ubuntu_code/Go/bin /protoc-gen-micro.exe ./api.proto
server.go
package main
import (
"context"
"fmt"
pb "github.com/cold-rivers-snow/study/lwz/my-micro/02/proto"
"github.com/micro/go-micro"
"github.com/micro/go-micro/errors"
"log"
)
type Example struct {
}
type Foo struct {
}
func (e *Example)Call(ctx context.Context, req *pb.CallRquest, rsp *pb.CallResponse) (error){
log.Print("收到Example.Call请求")
if len(req.Name) == 0{
return errors.BadRequest("go.micro.api.example","no name")
}
rsp.Message = "Example.Call接收到了你的请求"+req.Name
return nil
}
func (f *Foo)Bar(ctx context.Context, req *pb.EmptyRquest, rsp *pb.EmptyResponse) (error){
log.Print("接收到Foo.Bar请求")
return nil
}
func main(){
//实例
service := micro.NewService(micro.Name("go.micro.api.example"))
service.Init()
err := pb.RegisterExampleHandler(service.Server(),new(Example))
if err != nil{
fmt.Println(err)
}
err = pb.RegisterFooHandler(service.Server(),new(Foo))
if err != nil{
fmt.Println(err)
}
if err = service.Run();err != nil{
log.Fatal(err)
}
}
api访问:
1、启动api服务
image.png
2、启动server代码。
image.png微服务项目
image.pnguser.proto
syntax = "proto3";
package pb;
//定义需要的结构体
message User{
int32 id = 1;
string name = 2;
string address = 3;
string phone = 4;
}
message InsertUserReq{
int32 id = 1;
string name = 2;
string address = 3;
string phone = 4;
}
message InsertUserRep{
int32 id = 1;
string name = 2;
string address = 3;
string phone = 4;
}
message DeleteUserReq{
int32 id = 1;
}
message DeleteUserRep{
}
//改
message ModifyUserReq{
int32 id = 1;
string name = 2;
string address = 3;
string phone = 4;
}
message ModifyUserRep{
}
//查
message SelectUserReq{
int32 id = 1;
}
message SelectUserRep{
User users = 1;
}
//定义方法
service UserService{
//增
rpc InsertUser(InsertUserReq)returns(InsertUserRep){};
//删
rpc DeleteUser(DeleteUserReq)returns(DeleteUserRep){};
//改
rpc ModifyUser(ModifyUserReq)returns(ModifyUserRep){};
//查
rpc SelectUser(SelectUserReq)returns(SelectUserRep){};
}
proto导出命令:
protoc.exe -I . --micro_out=../src/share/pb --go_out=../src/share/pb --plugin=protoc-gen-go=D:/code/ubuntu_code/Go/bin/protoc-gen-go.exe --plugin=protoc-gen-micro=D: /code/ubuntu_code/Go/bin/protoc-gen-micro.exe user.proto
网友评论