微服务:将一个服务写成多个模块。
![](https://img.haomeiwen.com/i7898366/6536fdf8232f5690.png)
![](https://img.haomeiwen.com/i7898366/3cc5f85e2317b419.png)
![](https://img.haomeiwen.com/i7898366/f085cece997106dd.png)
系统性能方案:
![](https://img.haomeiwen.com/i7898366/b2afff89a394d3a7.png)
![](https://img.haomeiwen.com/i7898366/f002cb82cf1f47a2.png)
![](https://img.haomeiwen.com/i7898366/22c662b8159c43b6.png)
服务管理框架与服务是通过心跳包的方式保持通信。
RPC:
![](https://img.haomeiwen.com/i7898366/6eb63d10c98f8fdb.png)
![](https://img.haomeiwen.com/i7898366/fa62b10f2a647f78.png)
![](https://img.haomeiwen.com/i7898366/a8a7ba4a3727ea66.png)
![](https://img.haomeiwen.com/i7898366/efca5866928f1187.png)
![](https://img.haomeiwen.com/i7898366/5fabbc9e9b269cdf.png)
![](https://img.haomeiwen.com/i7898366/e8f61048d35a7fb4.png)
![](https://img.haomeiwen.com/i7898366/6bfea3ea6eaadf22.png)
![](https://img.haomeiwen.com/i7898366/6097254d3793cf93.png)
![](https://img.haomeiwen.com/i7898366/512ff42b86aaf4c8.png)
![](https://img.haomeiwen.com/i7898366/a540ced846b56c9c.png)
![](https://img.haomeiwen.com/i7898366/67edeffcbc38b924.png)
![](https://img.haomeiwen.com/i7898366/a74712b5cceb57cc.png)
![](https://img.haomeiwen.com/i7898366/af0da22b78ae9f93.png)
![](https://img.haomeiwen.com/i7898366/5be6fdba0b2d8e8c.png)
![](https://img.haomeiwen.com/i7898366/8dd72b40e817296f.png)
![](https://img.haomeiwen.com/i7898366/cfcb6139014fc3f8.png)
![](https://img.haomeiwen.com/i7898366/6445ea61ac837117.png)
![](https://img.haomeiwen.com/i7898366/183d8c399c088f79.png)
![](https://img.haomeiwen.com/i7898366/6589e073c210989e.png)
![](https://img.haomeiwen.com/i7898366/47b569e19b7f2ef6.png)
![](https://img.haomeiwen.com/i7898366/3002bbdcd90ec723.png)
![](https://img.haomeiwen.com/i7898366/37707fc197b39dd3.png)
![](https://img.haomeiwen.com/i7898366/f24b64bb2e47fc1f.png)
![](https://img.haomeiwen.com/i7898366/06e839edb92ed0af.png)
![](https://img.haomeiwen.com/i7898366/17d52aa36f3446e7.png)
![](https://img.haomeiwen.com/i7898366/492a0d5f9af72ced.png)
![](https://img.haomeiwen.com/i7898366/43c0249e9dde2274.png)
![](https://img.haomeiwen.com/i7898366/f01207b52e15cad9.png)
![](https://img.haomeiwen.com/i7898366/e9f04eb7a028ca55.png)
![](https://img.haomeiwen.com/i7898366/904b88b5796339b0.png)
![](https://img.haomeiwen.com/i7898366/248f6c7522f0aa39.png)
![](https://img.haomeiwen.com/i7898366/ae500d3532136448.png)
![](https://img.haomeiwen.com/i7898366/d1d0b31b483123d5.png)
![](https://img.haomeiwen.com/i7898366/a7b388f0bebf2ae7.png)
![](https://img.haomeiwen.com/i7898366/1d4e8fae7f9115a9.png)
![](https://img.haomeiwen.com/i7898366/077683454e0fbd8f.png)
raft
![](https://img.haomeiwen.com/i7898366/1013a928f1240fc7.png)
![](https://img.haomeiwen.com/i7898366/71d41121f3ea9b14.png)
![](https://img.haomeiwen.com/i7898366/6e0b72ac9cdcdc58.png)
![](https://img.haomeiwen.com/i7898366/29b40f88148bb546.png)
![](https://img.haomeiwen.com/i7898366/5d40823088272b7a.png)
![](https://img.haomeiwen.com/i7898366/acfa7678133d5c83.png)
![](https://img.haomeiwen.com/i7898366/d0e64b4c834c67d6.png)
![](https://img.haomeiwen.com/i7898366/fc0eaadac7839928.png)
![](https://img.haomeiwen.com/i7898366/eb089c535a10f264.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))
}
![](https://img.haomeiwen.com/i7898366/844e75269dacade2.png)
服务注册
![](https://img.haomeiwen.com/i7898366/b2794b4cb2fb7be1.png)
分析,类似于session中间件
- 定义服务注册总接口Registry,定义方法。
- Name():插件名,例如传etcd
- Init(opts ...Options):初始化不一样的时候可以使用选项设计模式。
- Regiter():服务注册
- Unregistr():服务反注册,例如服务端停了,注册列表销毁。
- GetService:服务发现(IP []port string)
- 抽象出一些结构体
- Node:单个节点的结构体,包含id,ip,port,weight(权重)
- Service:里面有服务名,节点列表。一个服务多台服务器支撑。
- 选项设计模式实现参数初始化
- 插件的管理类
- 可以用一个大map管理,key字符串,value是Registry接口对象
- 用户自定义去调用,自定义插件
- 实现注册中心得初始化,供系统使用。
![](https://img.haomeiwen.com/i7898366/87925e72e884e7ad.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启动,查值
![](https://img.haomeiwen.com/i7898366/a432ffa63f981edc.png)
![](https://img.haomeiwen.com/i7898366/8ee43c09deb3f8d3.png)
![](https://img.haomeiwen.com/i7898366/dfc9e365a55b69b2.png)
![](https://img.haomeiwen.com/i7898366/b566a50383881e70.png)
![](https://img.haomeiwen.com/i7898366/fadb54fbdf284b16.png)
![](https://img.haomeiwen.com/i7898366/7c3e633249119262.png)
![](https://img.haomeiwen.com/i7898366/8df68052293a8be9.png)
![](https://img.haomeiwen.com/i7898366/31e8b35033804fad.png)
![](https://img.haomeiwen.com/i7898366/2e8f1347ac871c8d.png)
![](https://img.haomeiwen.com/i7898366/7c3ce84724b08e52.png)
![](https://img.haomeiwen.com/i7898366/58a3ee2303db8fde.png)
![](https://img.haomeiwen.com/i7898366/61aa4f865e2a8381.png)
![](https://img.haomeiwen.com/i7898366/110aae20fe728bb6.png)
![](https://img.haomeiwen.com/i7898366/7eecca8e7e2f447f.png)
![](https://img.haomeiwen.com/i7898366/604b3e34344d6708.png)
![](https://img.haomeiwen.com/i7898366/31ea00a34b62f9ea.png)
![](https://img.haomeiwen.com/i7898366/07c807c93ee45d50.png)
![](https://img.haomeiwen.com/i7898366/eac26fd49832624e.png)
![](https://img.haomeiwen.com/i7898366/b96f23aa725dd57f.png)
![](https://img.haomeiwen.com/i7898366/d921149b1ba5f730.png)
![](https://img.haomeiwen.com/i7898366/75f4bd45591c2f3d.png)
![](https://img.haomeiwen.com/i7898366/b8475e29140a7396.png)
![](https://img.haomeiwen.com/i7898366/dcd708d1582c17c9.png)
![](https://img.haomeiwen.com/i7898366/f1f7ede55565e6cf.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){}
}
![](https://img.haomeiwen.com/i7898366/d6825471f5b9918c.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:"-"
:序列化和反序列化时忽略。
![](https://img.haomeiwen.com/i7898366/10b34e3bb5129f8f.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)
}
![](https://img.haomeiwen.com/i7898366/03e3e3955a378575.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)
}
![](https://img.haomeiwen.com/i7898366/7e6526b0e0e88da9.png)
![](https://img.haomeiwen.com/i7898366/fa615bbb449f012a.png)
![](https://img.haomeiwen.com/i7898366/15dd808945f17f2c.png)
![](https://img.haomeiwen.com/i7898366/c10f1191259bb4b6.png)
![](https://img.haomeiwen.com/i7898366/f4b8cb5c4c14f7b3.png)
![](https://img.haomeiwen.com/i7898366/a5470bfd23fd3d34.png)
![](https://img.haomeiwen.com/i7898366/dbb5b646492b7645.png)
![](https://img.haomeiwen.com/i7898366/64d3f4ff1d2bfa72.png)
![](https://img.haomeiwen.com/i7898366/edc635301b79c52a.png)
![](https://img.haomeiwen.com/i7898366/5a3f34fc0b32706e.png)
![](https://img.haomeiwen.com/i7898366/365d0ef9d51c6d7a.png)
![](https://img.haomeiwen.com/i7898366/5ee68ed71482320e.png)
![](https://img.haomeiwen.com/i7898366/e8a3b828a6a9cded.png)
![](https://img.haomeiwen.com/i7898366/5ff5038aaeefffa1.png)
![](https://img.haomeiwen.com/i7898366/448edc8577b6c93f.png)
![](https://img.haomeiwen.com/i7898366/56712af9f41b93fd.png)
![](https://img.haomeiwen.com/i7898366/a11f513bccee7b7f.png)
![](https://img.haomeiwen.com/i7898366/1aa68b0ba38d3b93.png)
hello.proto
syntax = "proto3";
//结构体
message InfoRequest{
string username = 1;
}
message InfoResponse{
string msg = 2;
}
//接口
service Hello{
rpc Info(InfoRequest)returns (InfoResponse){}
}
![](https://img.haomeiwen.com/i7898366/bd0539b3cf99bb50.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)
}
}
命令访问方式:
![](https://img.haomeiwen.com/i7898366/57522dfa5eb40305.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服务
![](https://img.haomeiwen.com/i7898366/ab0219dc2a533e22.png)
2、启动server代码。
![](https://img.haomeiwen.com/i7898366/97936fdb8fb0f3bf.png)
微服务项目
![](https://img.haomeiwen.com/i7898366/0fa92c7e7b1892cc.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
网友评论