gRPC 一揽子方案

2022-10-22,

gRPC是Google开发的高性能、通用的、开源的远程过程调用( RPC)技术框架,主要面向移动应用开发并基于HTTP/2协议标准而设计,基于Protobuf(Protocol Buffers)序列化协议开发。

关闭虚拟机的selinux    vim /etc/selinux/config
把SELINUX=enforcing改为SELINUX=disabled,保存退出,重启生效,永久关闭
查看selinux状态   getenforce

阿里云ios镜像
https://mirrors.aliyun.com/centos/7/isos/x86_64/

一、 Centos7 -- 设置代理服务器上网

1.1 永久代理设置

vim /etc/profile

http_proxy=http://192.168.0.101:1080
https_proxy=http://192.168.0.101:1080
ftp_proxy=http://192.168.0.101:1080
export http_proxy
export https_proxy
export ftp_proxy

source /etc/profile使设置立即生效

1.2 临时设置(重连后失效)

在命令行中直接输入下列命令即可
export http_proxy=http://192.168.0.101:1080
export https_proxy=http://192.168.0.101:1080
export ftp_proxy=http://192.168.0.101:1080

1.3 单次设置(建议使用)

直接在pip时设置代理
pip3 install --proxy http://代理地址:代理端口号 软件名称
curl www.google.com --proxy http://192.168.0.101:1080
windows的cmd临时访问外网
SET HTTP_PROXY=http://127.0.0.1:1080
SET HTTPS_PROXY=http://127.0.0.1:1080
windows的cmd永久代理外网(不推荐)
netsh winhttp import proxy source=ie

二、 安装Git,Docker,docker-compose及Docker镜像的创建使用

2.1 yum install git -y

git config --global user.name "xxx"
git config --global user.email xxx@local.com
git config --global --list

2.2 使用官方安装脚本自动安装docker

curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
systemctl enable docker
systemctl start docker
配置阿里云镜像
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://xxxxxxxxx.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
sudo docker run hello-world测试docker ps -a

2.3 安装docker-compose

curl -L "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose -v
docker pull mysql
docker images

2.4制作docker镜像

docker commit [containerID] [新镜像名称]

docker run it golang:latest

2.5 Dockerfile

```
#启动编译环境
FROM golang:1.18.2
#编译到其他镜像中(例alpine)
#FROM golang:1.18.2-alpine AS builder
#配置编译环境
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
#拷贝源代码到镜像中
COPY . source /go/src/coolcar/server
#编译
WORKDIR /go/src/coolcar/server
RUN go install ./gateway/...

FROM alpine:3.13
COPY --from=builder /go/bin/gateway /bin/new/gateway

#设置暴露对外端口
EXPOSE 8080
#设置服务入口
#ENTRYPOINT [ "/go/bin/gateway" ]
ENTRYPOINT [ "/bin/new/gateway" ]
#CMD [ "executable" ]
```
#编译镜像
docker build -t coolcar/gateway -f ../deployment/gateway/Dockerfile .
#执行镜像
docker run -p 8080:8080 coolcar/gateway

三、 docker安装Mysql8、Golang、nvm、nodejs、npm

3.1 安装Mysql8

docker run -p 3306:3306 --name mysql --privileged=true --restart unless-stopped \
-v $PWD/conf:/etc/mysql/conf.d \
-v $PWD/logs:/logs \
-v $PWD/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-d mysql

docker logs cccxxx查看docker单个镜像状态
docker container update --restart=always cccxxx
docker start cccxxx 启动容器
docker exec -it cccxxx /bin/bash进入容器
grant all privileges on *.* to 'root'@'%' IDENTIFIED BY 'root' with grant option;
ALTER user 'root'@'%' IDENTIFIED BY 'root';
create user 'root'@'127.0.0.1' identified by 'root';
grant all privileges on *.* to 'root'@'127.0.0.1' with grant option;
grant all privileges on *.* to 'root'@'localhost' with grant option;
ALTER user 'root'@'localhost' IDENTIFIED BY 'root';
flush privileges;

mysql8以上查看会话隔离级别
select @@transaction_isolation;

3.2 安装Golang

wget https://studygolang.com/dl/golang/go1.18.2.linux-amd64.tar.gz
tar -xvf go1.18.2.linux-amd64.tar.gz
vim ~/.bashrc
export GOROOT=/root/go
export GOPATH=/root/projects/go
export PATH=$PATH:$GOROOT/bin:$GOPAHT/bin
source ~/.bashrc
go env -w GOPROXY=https://goproxy.cn,direct
go env -w GO111MODULE=on

3.3、安装nvm,nodejs,npm

wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
source ~/.bashrc
nvm -v
//cd ~/.nvm
//touch .bash_profile
//export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
//[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm

nvm list-remote
安装nvm install v14.14.0    删除nvm uninstall v14.14.0
nvm ls
nvm use v14.14.0
node -v && npm -v

四、protoc的使用

下载go的依赖包
4. 下载protoc:https://github.com/protocolbuffers/protobuf/releases

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
//protoc -I . helloworld.proto --go-grpc_out=plugins=grpc:.
//protoc -I . helloworld.proto --go_out=plugins=grpc:.
protoc -I . --go_out=plugins=grpc:. helloworld.proto
//protoc --go_out=. helloworld.proto
protoc --go-grpc_out=. helloworld.proto

git clone https://github.com/grpc/grpc-go.git E:\Go\src\google.golang.org\grpc
git clone https://github.com/golang/net.git E:\Go\src\golang.org\x\net
git clone https://github.com/golang/text.git E:\Go\src\golang.org\x\text
git clone https://github.com/google/go-genproto.git E:\Go\src\google.golang.org\genproto
git clone https://github.com/protocolbuffers/protobuf-go.git E:\Go\src\google.golang.org\protobuf
git clone https://github.com/golang/protobuf.git E:\Go\src\github.com\golang\protobuf
//git clone https://github.com/google/go-genproto.git C:\Users\Downloads\google.golang.org\genproto

protoc --go_out=plugins=grpc:. helloworld.proto测试正常生成
grpc的四种数据流:简单模式,服务端数据流模式,客户端数据流模式,双向数据流模式

protoc -I . --go_out=plugins=grpc:. helloyo.proto
protobuf的数字标识符顺序不能错
proto文件中的import失效
File->Settings->Languages&Frameworks->Protocol Buffers,IDEA本身勾选了自动配置,去掉自动配置,手动添加路径(精确到proto目录),然后import就可以了。
grpc验证器protoc-gen_validate
//go get -d github.com/envoyproxy/protoc-gen-validate
//make build
git clone https://github.com/envoyproxy/protoc-gen-validate E:\Go\src\github.com\golang\protoc-gen-validate
cd E:\Go\src\github.com\golang\protoc-gen-validate
go install .
GOPATH的bin目录E:\Go下生成protoc-gen-validate.exe,复制到GOROOT下即可。
protoc -I .  --go_out=plugins=grpc:. --validate_out="lang=go:." helloworld.proto

五、YapiDocker镜像

git clone https://github.com/Ryan-Miao/docker-yapi.git
cd docker-yapi
docker-compose up
docker ps -a
docker container update --restart=always fffxxx
192.168.0.222:9090
会报错Error: Cannot find module '/my-yapi/vendors/server/app.js'
解决方法,先要处理步骤如下:
1.路径:vim  /root/dokcer-yapi/docker-compose.yml 
2.去掉注释#号 command: "yapi server",
3.加注释command: "node /my-yapi/vendors/server/app.js" 这个前面加#号
4.再去执行:docker-compose up 
再访问192.168.0.222:9090填写信息
数据库地址mongo数据库名test 数据库用户名test 密码test123456
自动执行后:
log: mongodb load success...
初始化管理员账号成功,账号名:"admin@admin.com",密码:"xxx.org"
部署成功,请切换到部署目录,输入: "node vendors/server/app.js" 指令启动服务器, 然后在浏览器打开 http://127.0.0.1:3000 访问
5.加注释#号 command: "test server",
6.去掉注释command: "node /my-test/vendors/server/app.js" 这个前面加#号
再执行docker-compose up 访问192.168.0.222:3000

chrome 安装 yapi 扩展教程
1下载解压扩展zip 2开发者模式下打开chrome://extensions .点击加载已解压的扩展程序
https://github.com/YMFE/cross-request/archive/master.zip

六、ORM 对象关系映射 

主要作用是在关系型数据库和对象之间作一个映射(把面向对象的概念跟数据库中表的概念对应起来)。
举例来说:定义一个对象,那就对应着一张表,这个对象的实例,就对应着表中的一条记录。
常用orm(gorm,ent,sqlx,xorm,gendry)

七、Gorm使用

https://gorm.io/zh_CN/docs/index.html
updates语句不会更新零值,但是update语句会更新
//db.Model(&User{ID:1}).Update("Name", "") //更新零值
//db.Model(&User{ID:1}).Updates(User{Email: &empty}) //不更新零值
//解决仅更新非零值字段的方法有两种
  /*
  1. 将string 设置为 *string
  2. 使用sql的NULLxxx来解决
  */
查询方式条件有三种 1. string 2. struct 3. map
  //通过where查询
  //var user User
  //var users []User
  //db.Where("name = ?", "cdddd").First(&user)
  //db.Where(&User{MyName:"cdddd1", Age: 0}).Find(&users) //struct的零值不查询
  //db.Where(map[string]interface{}{"name": "cdddd", "age":0}).Find(&users)

八、Golang日志打印调试

  //newLogger := logger.New(
  //  log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
  //  logger.Config{
  //    SlowThreshold: time.Second,   // 慢 SQL 阈值
  //    LogLevel:      logger.Info, // Log level
  //    Colorful:      true,         // 禁用彩色打印
  //  },
  //)
  //获取用户列表
  log.Println("测试日志1")
  //log.Info(ctx,"测试日志2")
go zap日志 下载或自动下载go get -u go.uber.org/zap
  logger, _ := zap.NewProduction()
  defer logger.Sync()
  zap.ReplaceGlobals(logger)
  url := "https://www.baidu.ocm"
  //使用自带logger
  logger.Info("failed to tetch URL:%s",zap.String("url",url), zap.Int("nums",3) )
  //使用sugar
  //sugar := logger.Sugar()
  //sugar.Infow("failed to tetch URL", "url",url,"attept",3)
  //sugar.Infof("failed to tetch URL:%s",url)
  输出日志到指定文件
  func NewLogger() (*zap.Logger, error) {
    cfg := zap.NewProductionConfig()
    cfg.OutputPaths = []string{
      "./myproject.log",  //默认src下,build后执行编译后文件在对应目录
    }
    return cfg.Build()
  }//使用logger, err := NewLogger(),其他代码相同

  九 redis的安装

    docker run -p 6379:6379 -d redis:latest redis-server
    查看redis日志docker logs 999xxx
    docker exec -it 999xxx /bin/bash 进入容器,连接redis-cli -h 192.168.0.222,查看keys *
    docker container update --restart=always 999xxx 实现容器自启动
    //docker start 999xxx 启动容器

  十 consul服务注册发现的安装和配置

  Linux下consul 

docker run -d -p 8500:8500 -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8600:8600/udp consul consul agent -dev -client=0.0.0.0
  docker container update --restart=always 777xxx
  访问http://192.168.0.222:8500/  (注:8500是https端口,8600是dns端口)
  安装dig工具yum install bind-utils -y
  dig @192.168.0.222 -p 8600 consul.service.consul SRV
  进入consul容器docker exec -it 777xxx /bin/sh

  win10下使用consul

  1、win + r,输入 cmd, 然后 回车
  2、切换到 d盘:d:,回车
  3、指定到目录cd D:\Soft\Study\Consul
  4、启动命令 .\consul.exe agent -dev;
  访问地址为:http://localhost:8500 或 http://127.0.0.1:8500
  5、指定IP访问 .\consul.exe agent -dev -client 192.168.0.101
  访问地址为:192.168.0.101:8500

  经本地测试(consul和服务不在统一IP下服务检查不通过)
  win10下安装Consul
  在https://www.consul.io/downloads下载64位执行文件
  解压放到D:\Consul下

  consul的api接口

  1. 添加服务
  https://www.consul.io/api-docs/agent/service#register-service
  2. 删除服务
  https://www.consul.io/api-docs/agent/service#deregister-service
  3. 设置健康检查
  https://www.consul.io/api-docs/agent/check
  4. 同一个服务注册多个实例
  5. 获取服务
  https://www.consul.io/api-docs/agent/service#list-services

  添加一个服务

  http://192.168.0.222:8500/v1/agent/service/register
  Headers Content-Type application/json
  {
    "Name":"xxshop-web",
    "ID":"xxshop-web",
    "Tags":["xxshop", "cdddd", "imooc", "web"],
    "Address":"127.0.0.1",
    "Port":50051
  }

  删除一个服务

  http://192.168.0.222:8500/v1/agent/service/deregister/xxshop-web

十一 负载均衡
    算法种类:轮询法、随机法、源地址哈希法、加权轮询法、加权随机法、最小连接法等

十二 配置中心nacos https://nacos.io/zh-cn/docs/quick-start.html

  docker run --name nacos-standalone -e MODE=standalone -e JVM_XMS=512m -e JVM_XMX=512m -e JVM_XMN=256m -p 8848:8848 -d nacos/nacos-server:latest
  docker container update --restart=always e9b95515448f

  192.168.0.222:8848/nacos/index.html nacos nacos
NacosSDK仓库https://github.com/nacos-group/nacos-sdk-go/blob/master/README_CN.md
Yaml转Json在线https://json2yaml.com/convert-yaml-to-json

十三 MySQL默认值选型(是空,还是 NULL)https://zhuanlan.zhihu.com/p/73997266

NULL 本身是一个特殊值,MySQL 采用特殊的方法IS NULL / IS NOT NULL来处理 NULL 值,建议默认值不要使用 NULL。
数值类型,以 INT 列为例
1) 在 min / max / sum / avg 中 NULL 值会被直接忽略掉,如下是测试结果,可能 min / max / sum 还比较可以理解,但 avg 也会忽略不合适
2) 对 NULL 做加减操作,如 1 + NULL,结果仍是 NULL
3) order by 以升序检索字段的时候 NULL 会排在最前面(倒序相反)
字符类型,在使用 NULL 值的时候
1) 统计包含 NULL 字段的值,NULL 值不包括在里面
1) 如果你用 length 去统计一个 VARCHAR 的长度时,NULL 返回的将不是数字而是NULL

十四 内网穿透:续断、花生壳

续断: https://cloud.zhexi.tech/auth/signin
安装PC客户端-新建隧道(配置内网主机、端口)- 拿到隧道网址

OSS的Nacos配置
{
  "name": "oss-web",
  "host": "192.168.0.101",
  "tags":["xxshop", "imooc", "cdddd", "oss", "web"],
  "port": 8029,
  "oss":{
    "key":"xxx",
    "secrect":"xxx",
    "host":"http://py-go.oss-cn-beijing.aliyuncs.com",
    "callback_url":"http://xxx.52http.net/oss/v1/oss/callback",
    "upload_dir":"xxshop-images/"
  },
  "jwt": {
    "key": "xxx"
  },
  "consul": {
    "host": "192.168.0.222",
    "port": 8500
  }
}

十五 常见的分布式锁实现方案

1. 基于mysql的悲观锁和乐观锁

a悲观锁
SELECT @@autocommit
SET autocommit=0
SELECT @@autocommit
SELECT * from inventory WHERE goods=421 for update;
COMMIT;
/*
1默认行锁,2无索引时会随机为表锁3只锁住要更新的for update语句4无满足条件结果,不会锁表
*/
b乐观锁
表中加个version字段,根据version版本条件执行更新命令(注意Select指定字段防止model更新忽略0值)。
tx.Model(&model.Inventory{}).Select("Stocks", "Version").Where("goods = ? and version= ?", goodInfo.GoodsId, inv.Version).Updates(model.Inventory{Stocks: inv.Stocks, Version: inv.Version+1});

2. 基于redis的分布式锁

https://github.com/go-redsync/redsync
问题解决:如果出现redsync无效,原因for循环里读写数据库,删除锁前要commit
分布式锁需要解决的问题:lua脚本保持原子性
互斥性:(setnx将获取和设置值变成原子性操作) 任意时刻只能有一个客户端拥有锁,不能同时多个客户端获取
安全性:(保存复杂值)锁只能被持有该锁的用户删除,而不能被其他用户删除,设置的值只有当时的g知道,在删除时取出和保存的值对比
死锁:(过期时间前刷新)获取锁的客户端因为某些原因而宕机,而未能释放锁,其他客户端无法获取此锁,需要有机制来避免该类问题的发生
  代码异常,导致无法运行到release
  你的当前服务器网络出问题 - 脑裂
  断电
容错:当部分节点宕机,客户端仍能获取锁或者释放锁
redlock红锁,len(r.pools)/2 + 1redis集群先得到奇数且未过期获取锁,其他的释放锁

3. 第三方的开源库,例如zookerper的分布式锁

十六 Elasticsearch是一个分布式可扩展的实时搜索和分析引擎。

    分布式实时文件存储,并将每一个字段编入索引,使其可以被搜索。
    实时分析的分布式搜索引擎。
    可以扩展到上百台服务器,处理PB级别的结构化或非结构化数据。
文档https://www.elastic.co/guide/en/elasticsearch/reference/current/search-your-data.html

16.1 关闭并禁用防火墙

systemctl stop firewalld.service
systemctl disabled firewalld.service
systemctl status firewalld.service

16.2 新建es的config配置文件夹,data目录,设置权限

mkdir -p /data/elasticsearch/config
mkdir -p /data/elasticsearch/data
chmod 777 -R /data/elasticsearch
#写入配置到elasticsearch.yml中
echo "http.host: 0.0.0.0" >> /data/elasticsearch/config/elasticsearch.yml
#安装es
docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
  -e "discovery.type=single-node" \
  -e ES_JAVA_OPTS="-Xms128m -Xmx256m" \
  -v /data/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
  -v /data/elasticsearch/data:/usr/share/elasticsearch/data \
  -v /data/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
  -d elasticsearch:7.10.1;
docker container update --restart=always elasticsearch;
查看http://192.168.0.222:9200
docker exec -it elasticsearch /bin/bash
查看容器内IP地址docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' elasticsearch;
docker logs elasticsearch
find /var/lib/docker/ -name jvm.options
/var/lib/docker/overlay2/58a77058e682eecac5194f90d8952317147e4ef1e9fc86057f349217fe019aa7/diff/usr/share/elasticsearch/config/jvm.options
#docker彻底删除容器和镜像
docker stop elasticsearch
docker rm elasticsearch
docker images
docker rmi 555xxx
#通过docker安装kibana
docker run -d --name kibana -e ELASTICSEARCH_HOSTS="http://192.168.0.222:9200" -p 5601:5601 kibana:7.10.1;
docker container update --restart=always 946xxx;
访问http://192.168.0.222:5601
问题Kibana server is not ready yet
docker logs kibana
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 946xxx;
docker exec -it 946xxx /bin/bash

16.3 es的doc、  document、field、 mapping、DSL(Descriptor Structure Laguage)
对应mysql的table、  row、 column、schema、 sql语句

16.4 Elasticsearch相关操作

GET _cat/indices //查询所有
GET account       //查询指定数据
#创建和更新(替换)
POST user/_doc/1
{
  "name":"cdddd1",
  "company":"gotest1"
}
POST user/_create/2
{
  "name":"cdddd2",
  "company":"gotest1"
}
PUT account/_doc/1
{
  "name":"cdddd",
  "age":18,
  "company":[
    {
      "name":"gotest1",
      "address":"beijing"
    },
    {
      "name":"gotest2",
      "address":"shanghai"
    }
  ]
}
#更新
POST user/_update/1
{
  "doc":{
    "age":18
  }
}
#删除
DELETE user/_doc/2
DELETE user
#查询
GET user/_doc/1
GET user/_source/1

GET user/_search?q=cdddd

GET user/_search
{
  "query": {
    "match_all": {
    }
  },
  "from":"2",
  "size":"5"
}
GET user/_search
{
  "query": {
    "match": {
      "address":"street"
    }
  },
  "from":"2",
  "size":"5"
}
GET user/_search
{
  "query": {
    "match": {
      "name":"cdddda2"
    }
  }
}
GET user/_search
{
  "query": {
    "match": {
      "name":{
        "query":"cdddda otherw",
        "fuzziness":1,
      }
    }
  }
}
GET resume/_search
{
  "query": {
    "multi_match": {
      "query":"go",
      "fields":["title^2", "desc"]
    }
  }
}
GET resume/_search
{
  "query": {
    "query_string": {
      "default_field":"FIELD",
      "query":"this AND that OR thus"
    }
  }
}
GET account/_search
{
  "query": {
    "term": {
      "name":{
        "value":"cdddd",
        "boost":1.0
      }
    }
  }
}
GET user/_search
{
  "query": {
    "terms": {
      "name":["cdddda2", "cdddda3"]
    }
  }
}
GET account/_search
{
  "query": {
    "range": {
      "age":{
        "gte":10,
        "lte":20
      }
    }
  }
}
GET user/_search
{
  "query": {
    "fuzzy": {
      "name":"cdddd"
    }
  }
}
GET user/_search
{
  "query": {
    "fuzzy": {
      "name":"bobbza"
    }
  }
}
#指明分词器查询
GET user/_search
{
  "query": {
    "match": {
      "name":{
        "query":"cdddda otherw",
        "analyzer":"keyword",
      }
    }
  }
}
GET user/_search
{
  "query":{
    "bool":{//bool连接,复合查询
      "must":[
        {
          "term":{
            "state":"us"
          }
        },
        {
          "range":{
            "age":{
              "gte":10,
              "lte":30
            }
          }
        }
      ],//必须匹配,加分
      "should":[
        {
          "match":{
            "firstname":"cdddd"
          }
        }
      ],//非必须匹配,加分
      "must_not":[
        {
          "term":{
            "gender":"m"
          }
        }
      ],//不匹配,过滤
      "filter":[
        {
          "range":{
            "age":{
              "gte":25,
              "lte":30
            }
          }
        }
      ] //必须匹配,过滤
    }
  }
}

#match模糊分词查询,match_all查询所有,match_phrase短语查询(精准但分词查询),multi_match多字段查询,
query_string所有字段中查询,term不分词查询,terms不分词配备多个值查询,range查询,exist字段是否存在,fuzzy模糊纠错查询,复合查询
#批量插入和批量查询
#批量操作
POST _bulk
{ "index" : { "_index" : "user", "_id" : "1" }}
{ "name" : "cdddda" }
{ "delete" : { "_index" : "user", "_id" : "2" }}
{ "create" : { "_index" : "user", "_id" : "3" }}
{ "name" : "cddddc" }
{ "update" : { "_id" : "1", "_index" : "user" }}
{ "doc" : { "name" : "cddddb"}}
#批量获取mget
GET _mget
{
    "docs":[
    {
      "_index":"user",
      "_id":"1"
    },
    {
      "_index":"account",
      "_id":"2"
    }
  ]
}

#倒排索引 分词

16.5 mapping 定义索引的字段类型

PUT atest
{
  "mappings": {
    "properties": {
      "number_of_bytes": {
        "type": "integer"
      },
      "time_in_seconds": {
        "type": "float"
      },
      "price": {
        "type": "scaled_float",
        "scaling_factor": 100
      }
    }
  }
}

16.6 Elasticsearch内置分词器analyzer:standard按词切分,simple(按非字母,符号被过滤),stop停用词过滤(the,a,is)
whitespace空格,keyword不分词,patter正则表达式,language(其他语言分词器)

16.7 中文分词器IK安装和配置

https://github.com/medcl/elasticsearch-analysis-ik/releases
下载解压和elasticsearch相同版本7.10.1的ik,放到目录/data/elasticsearch/plugins下并设置权限chmod 777 -R ik
docker exec -it elasticsearch /bin/bash
cd bin查看安装了哪些插件./elasticsearch-plugin list
重启容器docker restart elasticsearch
如果elasticsearch无法重启报异常日志,find /var/lib/docker/ -name jvm.options
删除空白jvm.options文件,再次重启即可

16.8 创建自己的词库和停用词

cd /data/elasticsearch/plugins/ik/config
mkdir custom && cd custom
vim mydic.dic在里面添加词,例如:中华牙膏
vim extra_stopword.dic 添加停用词:的 是 哟 (每行一个词)
cd .. && vim IKAnalyzer.cfg.xml 添加对应字典和停用词路径
<entry key="ext_dict">custom/mydic.dic</entry>
<entry key="ext_stopwords">custom/extra_stopword.dic</entry>
重启容器docker restart elasticsearch

GET _analyze
{
  "text":"中华牙膏",
  #"analyzer": "ik_smart"
  "analyzer": "ik_max_word"
}
PUT cn
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "ik_smart",
        "search_analyzer": "standard"
      }
    }
  }
}

POST cn/_doc
{
  "name":"中国科学技术大学"
}

GET cn/_search
{
  "query": {
    "match": {
      "name":{
        "query":"中国科学技术大学"
      }
    }
  }
}

十七、事务的CAID

17.1 A原子性(全部成功或全部失败,关注侧重点在状态)

C一致性(只有最初和最终状态可见,中间状态不可见,关注点在数据的可见性)
I隔离性(多个事务互不干扰,隔离级别:读未提交、读已提交、可重复读、串行化)
D持久性(数据持久保存到硬盘)
分布式事务:由本地多个事务组成

17.2 CAP和BASE理论

CAP   C一致性A可用性(Reads and writes always succeed)P分区容错性(部分故障仍然可用)
BASS  基本可用、软状态、最终一致性
常见分布式事务解决方案:
两阶段提交(2PC, Two-phase Commit)
TCC补偿模式(TCC分布式事务)微服务的每个事务都必须实现try,confirm,cancel等3个方法
基于本地消息表实现最终一致性
最大努力通知
基于可靠消息最终一致性方案

十八 MQ 消息队列是一种“先进先出”的数据结构

优点:解耦、削峰、数据分发,缺点:系统可用性降低、系统复杂度提高、一致性问题

18.1 rocketmq安装和配置

mkdir -p /root/project/xxshop_srvs/order_srv
解压install.zip文件到order_srv目录下
chmod 755 -R /root/project
cd /root/project/xxshop_srvs/order_srv/install
vim conf/broker.conf
brokerIP1=192.168.0.222
docker-compose up执行安装
dcoker ps -a出现3个foxiswho/rocketmq:broker,styletang/rocketmq-console-ng,foxiswho/rocketmq:server即可
访问192.168.0.222:8080

18.2 RocketMQ消息队列的基本概念

Producer:消息的发送者;举例:发信者
Consumer:消息接收者;举例:收信者
Broker:暂存和传输消息;举例:邮局
NameServer:管理Broker;举例:各个邮局的管理机构
Topic:区分消息的种类;一个发送者可以发送消息给一个或者多个Topic;一个消息的接收者可以订阅一个或者多个Topic消息
Message Queue:相当于是Topic的分区;用于并行发送和接收消息
rocketmq的消息类型
按照分 1.同步发送 2.异步发送 3.单向发送
按照分 1.普通消息(订阅)2.顺序消息 3.延时消息(订单超时库存归还)4.事务消息
优点:异步处理、解耦、削峰、数据分发
应用场景:订单解耦、秒杀、短信通知,发送邮件,终端状态推送,App推送等

18.3 Go操作rocketmq开发https://github.com/apache/rocketmq-client-go

服务雪崩 超时、重试、幂等性(解决方法:1.数据表唯一索引 2.token机制 3.悲观锁 4.乐观锁 5.分布式锁)
        原因:服务不可用:硬件故障、程序bug、缓存击穿、大量请求,重试加大流量,服务调用者不可用:同步等待造成资源耗尽
        应对策略:应用扩容(加机器、升级硬件),流控(限流、关闭重试),缓存(缓存预加载)
       服务降级(服务接口拒绝服务、页面拒绝服务、延迟持久化、随机拒绝服务),服务熔断
            Sentinel熔断策略:慢调用比例策略、错误比例策略、错误计数策略
docker-compose.yml配置:
version: '3.5'
services:
  rmqnamesrv:
    image: foxiswho/rocketmq:server
    container_name: rmqnamesrv
    ports:
      - 9876:9876
    volumes:
      - ./logs:/opt/logs
      - ./store:/opt/store
    networks:
        rmq:
          aliases:
            - rmqnamesrv

  rmqbroker:
    image: foxiswho/rocketmq:broker
    container_name: rmqbroker
    ports:
      - 10909:10909
      - 10911:10911
    volumes:
      - ./logs:/opt/logs
      - ./store:/opt/store
      - ./conf/broker.conf:/etc/rocketmq/broker.conf
    environment:
        NAMESRV_ADDR: "rmqnamesrv:9876"
        JAVA_OPTS: " -Duser.home=/opt"
        JAVA_OPT_EXT: "-server -Xms256m -Xmx256m -Xmn256m"
    command: mqbroker -c /etc/rocketmq/broker.conf
    depends_on:
      - rmqnamesrv
    networks:
      rmq:
        aliases:
          - rmqbroker

  rmqconsole:
    image: styletang/rocketmq-console-ng
    container_name: rmqconsole
    ports:
      - 8080:8080
    environment:
        JAVA_OPTS: "-Drocketmq.namesrv.addr=rmqnamesrv:9876 -Dcom.rocketmq.sendMessageWithVIPChannel=false"
    depends_on:
      - rmqnamesrv
    networks:
      rmq:
        aliases:
          - rmqconsole

networks:
  rmq:
    name: rmq
    driver: bridge

十九、Jaeger链路追踪

19.1 jaeger安装和架构
Jaeger组成:Jaeger Client、Agent、Collector、Data Store、Query
分布式追踪系统核心步骤一般有三个:代码埋点,数据存储、查询展示
docker run \
  --rm \
  --name jaeger \
  -p6831:6831/udp \
  -p16686:16686 \
  jaegertracing/all-in-one:latest
访问http://192.168.0.222:16686
OpenTracing语义标准。OpenTracing是一个跨编程语言的标准,此文档会避免具有语言特性的概念而建立共同标准。

二十、 流量控制组件Sentinel中文文档https://sentinelguard.io/zh-cn/docs/introduction.html

二十一、 Kong网关是一个开源的API网关,是一个针对API的管理工具。基于OpenResty(Nginx+Lua)
通过前置的负载均衡配置把请求均匀地分发到各个Server,来应对大量的网络请求。

21.1 安装Postgresql

docker run -d --name kong-database \
-p 5432:5432 \
-e "POSTGRES_USER=kong" \
-e "POSTGRES_DB=kong" \
-e "POSTGRES_PASSWORD=kong" \
-e "POSTGRES_DB=kong" postgres:12
docker container update --restart=always d77xxx;
# 对Postgresql进行Migrations数据初始化
docker run --rm \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=192.168.0.222" \
-e "KONG_PG_PASSWORD=kong" \
-e "POSTGRES_USER=kong" \
-e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
kong kong migrations bootstrap

21.2 安装kong,rpm下载地址https://download.konghq.com/gateway-2.x-centos-7/Packages/k/

yum -y install https://download.konghq.com/gateway-2.x-centos-7/Packages/k/kong-2.8.0.el7.amd64.rpm
systemctl stop firewalld.service
systemctl restart docker

cp /etc/kong/kong.conf.default /etc/kong/kong.conf
vim /etc/kong/kong.conf
#修改如下内容
database = postgres
pg_host = 192.168.0.222
pg_port = 5432
pg_timeout = 5000

pg_user = kong
pg_password = kong
pg_database = kong

#(重点)dns_resolver与consul服务发现的dns地址一致
dns_resolver = 192.168.0.101:8600
admin_listen = 0.0.0.0:8001 reuseport backlog=16384,0.0.0.0:8444 http2 ssl reuseport backlog=16384
proxy_listen = 0.0.0.0:8000 reuseport backlog=16384,0.0.0.0:8443 reuseport backlog=16384

#kong mmigrations bootstrap up -c /etc/kong/kong.conf #这也是初始化生成数据库
如果报错Error ... : New migrations available; run 'kong migrations up' to proceed则需执行kong migrations up
kong start -c /etc/kong/kong.conf

#如果开启了防火墙则要添加防火墙规则
firewall-cmd --zone=public --add-port=8001/tcp --permanent
firewall-cmd --zone=public --add-port=8000/tcp --permanent
firewall-cmd --reload
kong安装正常则http://192.168.0.222:8000或http://192.168.0.222:8001可以访问
8000:用户访问,8001:kong的管理端口,1337:kong地址

21.3 安装konga(类似navicat)

docker run -d -p 1337:1337 --name konga pantsel/konga
docker container update --restart=always c33xxx
访问192.168.0.222:1337 konguser konguser@163.com konguser konguser

21.4 使用kong做服务转发和负载均衡

在SERVICES添加服务 Host goods-web.service.consul, Port 80
在ROUTES设置路由Paths /
分别在IDEA的Run开启goods-web的api服务,修改Port后在Terminal使用go run goods-web/main.go再开启同样api服务
测试多次访问http://192.168.0.222:8000/g/v1/goods,两个服务会自动实现负载均衡

21.5 使用Kong配置jwt

21.5.1 在CONSUMERS新建一个consumer(一个consumer代表一类应用或一个微服务)
21.5.2 在consumers/Credentials/JWT为这个consumer添加jwt(记住key:imooc和keyxxx)
  此处设置的key为\xxshop-api\user-web\api\user.go的Issuer: "imooc",secret为Nacos的users下user-web.json的jwt
21.5.3 在PLUGINS的Jwt-ADD PLUGIN配置全局的plugins,设置headers names:x-token(和gin验证保持一致)
        返回PLUGINS的jwt发现headers names被改,叉掉Unauthorized设置x-token回车
21.5.4 在postman用GEt访问http://192.168.0.222:8000/g/v1/goods,设置Headers的x-token为jwt.io生成的Bearer [token]
    Kong的x-token前要加Bearer+空格+token
    jwt.io生成token:在PAYLOAD添加"iss": "imooc",在VERIFY SIGNATURE设置secret
21.5.5 取消\xxshop-api\goods-web\middlewares\jwt.go//token = strings.Split(token, " ")[1]的注释,再次使用postman即可访问

二十二、 敏捷开发 《敏捷宣言》

我们一直在实践中探寻更好的软件开发方法,身体力行的同时也帮助他人。由此我们建立了如下价值观:
个体和互动 高于 流程和工具;工作的软件 高于 详尽的文档;客户合作 高于 合同谈判;响应变化 高于 遵循计划;
也就是说,尽管右项有价值,我们更重视左项的价值。
Jenkins是一个开源的、提供友好操作界面的持续集成(CI)工具,主要用于持续、自动的构建(部署)/测试软件项目、监控外部任务的运行。

22.1 jenkins的安装和配置(在192.168.0.201上)

yum install java-1.8.0-openjdk* -y
下载jenkins-2.284-1.1.noarch.rpm
rpm -ivh jenkins-2.284-1.1.noarch.rpm
修改jenkins配置
vim /etc/sysconfig/jenkins
JENKINS_USER="root" #这里改为root 会省去很多权限的麻烦
JENKINS_PORT="8088"
启动systemctl start jenkins
http://192.168.0.201:8088
cat /var/lib/jenkins/secrets/initialAdminPassword
admin 8cxxxxxxxxxxxxxxxxxxxxxx
点击右侧的 “选择插件来安装”进入,选择 “无”,进入新建用户页面
gotestjen 123456 gotestjen

22.2 jenkins插件管理

22.2.1 修改插件下载地址,修改default.json文件
sed -i 's/https:\/\/updates.jenkins.io\/download/http:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' /var/lib/jenkins/updates/default.json
sed -i 's/http:\/\/www.google.com/https:\/\/www.baidu.com/g' /var/lib/jenkins/updates/default.json
22.2.2 进入 Manage Jenkins -》 Manage Plugin -> Advanced 最下面有 Update Site 
设置为:https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
浏览器输入 http://192.168.0.201:8088/restart 重启
Manage Jenkins -》 Manage Plugin -> Available安装插件
Localization: Chinese (Simplified),SSH,SSH Credentials,Git
码云上新建一个项目,jenkins新建项目,构建一个自由风格的软件项目,配置-源码管理,添加Git Credentials,应用保存,立即构建
如果报Git错误,则在linux上which git,没有查到yum install -y git

二十三、 centos7 下安装nvm,nodejs,npm,cnpm

git clone git://github.com/creationix/nvm.git ~/nvm
#或者下载nvm安装包https://github.com/nvm-sh/nvm/archive/refs/tags/v0.38.0.tar.gz
#tar -zxvf nvm-0.38.0.tar.gz /root/nvm
command -v nvm
echo "source ~/nvm/nvm.sh" >> ~/.bashrc
#或者vim ~/.bashrc
#export NVM_DIR="$HOME/nvm"
#[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
#[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion
source ~/.bashrc
#nvm uninstall v14.18.1 #卸载
nvm install v14.18.1
nvm use v14.18.1
nvm ls
npm install -g cnpm --registry=https://registry.npm.taobao.org
#必须添加3个软链接,不然jenkins执行构建时会报错,找不到/usr/bin/node
ln -s /root/nvm/versions/node/v14.18.1/bin/node /usr/bin/node
ln -s /root/nvm/versions/node/v14.18.1/bin/npm /usr/bin/npm
ln -s /root/nvm/versions/node/v14.18.1/bin/cnpm /usr/bin/cnpm

二十四、docker安装nginx

mkdir /docker
docker run --name nginx -d -p 80:80 nginx:latest

docker cp nginx:/etc/nginx /docker/nginx/config/ 
docker cp nginx:/usr/share/nginx/html /docker/nginx/data/
docker cp nginx:/var/log/nginx /docker/nginx/logs/

docker rm nginx -f

docker run --name nginx -p 80:80 \
-v /docker/nginx/config/nginx/:/etc/nginx \
-v /docker/nginx/data/html:/usr/share/nginx/html \
-v /docker/nginx/logs/:/var/log/nginx \
-d nginx:latest
docker container update --restart=always nginx

访问http://192.168.0.222出现nginx页面
docker exec -it 36cf57cf68bd /bin/bash进入容器

二十五、jenkins centos7 安装golang

mkdir ~/go && cd ~/go
wget https://golang.google.cn/dl/go1.18.3.linux-amd64.tar.gz
tar -C /usr/local -zxvf  go1.18.3.linux-amd64.tar.gz
vim /etc/profile
# 在最后一行添加
export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin
source /etc/profile
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.io

echo "配置go语言环境变量"
export GOROOT=/usr/local/go 
export PATH=$PATH:$GOROOT/bin
echo "开启go module"
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.io
echo "运行go build构建"
chmod 777 -R goods-web
mkdir -vp goods-web/target/goods-web
cp goods-web/config-pro.yaml goods-web/target/goods-web/config-pro.yaml

echo "执行go build 生成可执行文件"
go build -o goods-web/target/goods_web_main goods-web/main.go
echo "构建完成"
 

《gRPC 一揽子方案.doc》

下载本文的Word格式文档,以方便收藏与打印。