微服务

作者: 雪上霜 | 来源:发表于2020-05-23 07:27 被阅读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中间件

  • 定义服务注册总接口Registry,定义方法。
    • Name():插件名,例如传etcd
    • Init(opts ...Options):初始化不一样的时候可以使用选项设计模式。
    • Regiter():服务注册
    • Unregistr():服务反注册,例如服务端停了,注册列表销毁。
    • GetService:服务发现(IP []port string)
  • 抽象出一些结构体
    • Node:单个节点的结构体,包含id,ip,port,weight(权重)
    • Service:里面有服务名,节点列表。一个服务多台服务器支撑。
  • 选项设计模式实现参数初始化
  • 插件的管理类
    • 可以用一个大map管理,key字符串,value是Registry接口对象
    • 用户自定义去调用,自定义插件
    • 实现注册中心得初始化,供系统使用。
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

相关文章

  • 菜鸟带你看传说中的微信开发!

    1.微信开发原理微信客户端->微信服务器->开发绑定的服务器。微信开发步骤: 2.微信验证服务器原理(验证服务器的...

  • 胡健豪:如何运营微信矩阵

    微信矩阵是怎么回事,其实就是1个微信服务号+N个微信订阅号。微信服务号和订阅号的差别在于,服务号提供公司服务,订阅...

  • zabbix微信 | 微信对接自己服务器(2)

    上接使用微信告警 企业号微信对接自己服务器 1.本地服务器与微信服务器的信任 本地具有独立外网ip服务器获取微信服...

  • 微服务的微

    微服务的微,是指服务粒度的微么? 微服务可能是由此得名的。但在微服务架构思想中,服务粒度的微,不应该放在首要强调的...

  • 微信服务

    1.微信sdk 样例 http://demo.open.weixin.qq.com/jssdk/

  • 实战 Docker+Kubernetes 微服务容器化(一)-初

    1 微服务-导学 2 软件架构的进化 3 什么是微服务 多微才算微 微服务的特征 微服务诞生背景 4 画出微服务架...

  • SDtalk-10:阿里茶山服务设计实践-4

    2015年的茶山:服务设计微日记 《服务设计微日记》以微日记的故事写作形式,引用每天生活和工作的真实服务设计案例及...

  • 微服务应该具备的功能

    微服务应该具备的功能 >> 微服务应该具备的功能微服务,可以拆分为“微”和“服务”二字。“微”即小的意思,那到底多...

  • 微信开发——内网穿透

    微信开发需要与微信服务器交互,要保证微信服务器能向我们的服务器POST数据,我们的服务器需要能够在公网访问。这里简...

  • 【服务设计】服务设计微日记

    服务设计如同一部电影,有各个角色,出场顺序也不一样,服务流程贯穿应用场景,且有故事性,各个利益相关者都有主次之分。...

网友评论

      本文标题:微服务

      本文链接:https://www.haomeiwen.com/subject/iudcohtx.html