微服务

2020-05-23  本文已影响0人  雪上霜

微服务:将一个服务写成多个模块。


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.png
image.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中间件

image.png

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:"-":序列化和反序列化时忽略。

image.png
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.png

user.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

上一篇 下一篇

猜你喜欢

热点阅读