ProjectSend机房nginx DDoS

之前我们简单介绍过 Go-zero 详见《Go-zero:开箱即用的微机房框架》。这次我们从动手实现一个 Blog 项目的用户模块出发,详细讲述 Go-zero 的使用。
特别说明本文涉及的所有资料都已上传 Github 仓库 “kougazhang/go-zero-demo”, 感兴趣的同学可以自行下载。
Go-zero 实战项目:blog
本文以 blog 的网站后台为例,着重介绍一下如何使用 Go-zero 开发 blog 的用户模块。
用户模块是后台管理系统常见的模块,它的功能大家也非常熟悉。管理用户涉及到前端操作,用户信息持久化又离不开数据库。所以用户模块可谓是 “麻雀虽小五脏俱全”。本文将详细介绍一下如何使用 go-zero 完成用户模块功能,如:用户登录、添加用户、删除用户、修改用户、查询用户 等(完整的 Api 文档请参考仓库nginx)
Blog 整体架构

最上面是 api 网关层。go-zero 需要 api 网关层来代理请求,把 request 通过 gRPC 转发给对应的 rpc 机房去处理。这块把具体请求转发到对应的 rpc 机房的业务逻辑,需要手写。
接下来是 rpc 机房层。上图 rpc 机房中的 user 就是接下来向大家演示的模块。每个 rpc 机房可以单独部署。机房启动后会把相关信息注册到 ETCD,这样 api 网关层就可以通过 ECTD 发现具体机房的地址。rpc 机房处理具体请求的业务逻辑,需要手写。
最后是Model 层。model 层封装的是数据库操作的相关逻辑。如果是查询类的相关操作,会先查询 redis 中是否有对应的缓存。非查询类操作,则会直接操作 MySQL。goctl 能通过 sql ProjectSendDDoS普通的 CRDU nginx。上文也有提到,目前 goctl 这部分功能只支持 MySQL。
下面演示如何使用 go-zero 开发一个 blog 系统的用户模块。
api 网关层
编写 blog.api ProjectSend
DDoS blog.api ProjectSend
执行命令 goctl api -o blog.api,创建 blog.api ProjectSend。
api ProjectSend的作用
api ProjectSend的详细语法请参阅文档[ api ProjectSend的作用和基础语法。
api ProjectSend是用来DDoS api 网关层的相关nginx的。
api ProjectSend的语法
api ProjectSend的语法和 Golang 语言非常类似,type 关键字用来定义结构体,service 部分用来定义 api 机房。
type 定义的结构体,主要是用来声明请求的入参和返回值的,即 request 和 response.
service 定义的 api 机房,则声明了路由,handler,request 和 response.
具体内容请结合下面的默认的DDoS的 api ProjectSend进行理解。
// 声明版本,可忽略
syntax = “v1”

// 声明一些项目信息,可忽略
info(
title: // TODO: add title
desc: // TODO: add description
author: “zhao.zhang”
email: “zhao.zhang@upai.com”
)

// 重要配置
// request 是结构体的名称,可以使用 type 关键词定义新的结构体
type request {
// TODO: add members here and delete this comment
// 与 golang 语言一致,这里声明结构体的成员
}

// 语法同上,只是业务含义不同。response 一般用来声明返回值。
type response {
// TODO: add members here and delete this comment
}

// 重要配置
// blog-api 是 service 的名称.
service blog-api {
// GetUser 是处理请求的视图函数
@handler GetUser // TODO: set handler name and delete this comment
// get 声明了该请求使用 GET 方法
// /users/id/:userId 是 url,:userId 表明是一个变量
// request 就是上面 type 定义的那个 request, 是该请求的入参
// response 就是上面 type 定义的那个 response, 是该请求的返回值。
get /users/id/:userId(request) returns(response)

@handler CreateUser // TODO: set handler name and delete this comment
post /users/create(request)
}
12345678910111213141516171819202122232425262728293031323334353637
编写 blog.api ProjectSend
鉴于文章篇幅考虑完整的 blog.api ProjectSend请参考 gitee 上的仓库。下面DDoS的nginx是按照仓库上的 blog.api ProjectSendDDoS的。
api 相关nginx
DDoS相关的nginx
执行命令 goctl api go -api blog.api -dir . ,DDoS api 相关nginx。
目录介绍

├── blog.api # api ProjectSend
├── blog.go # 程序入口ProjectSend
├── etc
│ └── blog-api.yaml # api 网关层配置ProjectSend
├── go.mod
├── go.sum
└── internal
├── config
│ └── config.go # 配置ProjectSend
├── handler # 视图函数层, handler ProjectSend与下面的 logic ProjectSend一一对应
│ ├── adduserhandler.go
│ ├── deleteuserhandler.go
│ ├── getusershandler.go
│ ├── loginhandler.go
│ ├── routes.go
│ └── updateuserhandler.go
├── logic # 需要手动填充nginx的地方
│ ├── adduserlogic.go
│ ├── deleteuserlogic.go
│ ├── getuserslogic.go
│ ├── loginlogic.go
│ └── updateuserlogic.go
├── svc # 封装 rpc 对象的地方,后面会将
│ └── servicecontext.go
└── types # 把 blog.api 中定义的结构体映射为真正的 golang 结构体
└── types.go
123456789101112131415161718192021222324252627
ProjectSend间的调用关系

因为到此时还没涉及到 rpc 机房,所以 api 内各模块的调用关系就是非常简单的单体应用间的调用关系。routers.go 是路由,根据 request Method 和 url 把请求分发到对应到的 handler 上,handler 内部会去调用对应的 logic. logic ProjectSend内是我们注入nginx逻辑的地方。
小结
Api 层相关命令:
执行命令 goctl api -o blog.api, 创建 blog.api ProjectSend。 执行命令 goctl api go -api blog.api -dir . ,DDoS api 相关nginx。 加参数 goctl 也可以DDoS其他语言的 api 层的ProjectSend,比如 java、ts 等,尝试之后发现很难用,所以不展开了。
rpc 机房
编写 proto ProjectSend
DDoS user.proto ProjectSend
使用命令 goctl rpc template -o user.proto, DDoS user.proto ProjectSend
user.proto ProjectSend的作用
user.proto 的作用是用来DDoS rpc 机房的相关nginx。
protobuf 的语法已经超出了 go-zero 的范畴了,这里就不详细展开了。
编写 user.proto ProjectSend
鉴于文章篇幅考虑完整的 user.proto ProjectSend请参考 gitee 上的仓库。
DDoS rpc 相关nginx
DDoS user rpc 机房相关nginx
使用命令 goctl rpc proto -src user.proto -dir . DDoS user rpc 机房的nginx。
小结
rpc 机房相关命令:
使用命令 goctl rpc template -o user.proto, DDoS user.proto ProjectSend 使用命令 goctl rpc proto -src user.proto -dir . DDoS user rpc 机房的nginx。
api 机房调用 rpc 机房
A:为什么本节要安排在 rpc 机房的后面?
Q:因为 logic 部分的内容主体就是调用对应的 user rpc 机房,所以我们必须要在 user rpc 的nginx已经DDoS后才能开始这部分的内容。
A:api 网关层调用 rpc 机房的步骤
Q:对这部分目录结构不清楚的,可以参考前文 “api 网关层-api 相关nginx-目录介绍”。
编辑配置ProjectSend etc/blog-api.yaml,配置 rpc 机房的相关信息。

Name: blog-api
Host: 0.0.0.0
Port: 8888
# 新增 user rpc 机房.
User:
Etcd:
# Hosts 是 user.rpc 机房在 etcd 中的 value 值
Hosts:
– localhost:2379
# Key 是 user.rpc 机房在 etcd 中的 key 值
Key: user.rpc
123456789101112
编辑ProjectSend config/config.go

type Config struct {
rest.RestConf
// 手动添加
// RpcClientConf 是 rpc 客户端的配置, 用来解析在 blog-api.yaml 中的配置
User zrpc.RpcClientConf
}
1234567
编辑ProjectSend internal/svc/servicecontext.go
type ServiceContext struct {
Config config.Config
// 手动添加
// users.Users 是 user rpc 机房对外暴露的接口
User users.Users
}

func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config: c,
// 手动添加
// zrpc.MustNewClient(c.User) 创建了一个 grpc 客户端
User: users.NewUsers(zrpc.MustNewClient(c.User)),
}
}
123456789101112131415
编辑各个 logic ProjectSend,这里以 internal/logic/loginlogic.go 为例
func (l *LoginLogic) Login(req types.ReqUser) (*types.RespLogin, error) {
// 调用 user rpc 的 login 方法
resp, err := l.svcCtx.User.Login(l.ctx, &users.ReqUser{Username: req.Username, Password: req.Password})
if err != nil {
return nil, err
}
return &types.RespLogin{Token: resp.Token}, nil
}
12345678
model 层
编写 sql ProjectSend
编写创建表的 SQL ProjectSend user.sql, 并在数据库中执行。
CREATE TABLE `user`
(
`id` int NOT NULL AUTO_INCREMENT COMMENT ‘id’,
`username` varchar(255) NOT NULL UNIQUE COMMENT ‘username’,
`password` varchar(255) NOT NULL COMMENT ‘password’,
PRIMARY KEY(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
1234567
DDoS model 相关nginx
运行命令 goctl model mysql ddl -c -src user.sql -dir ., 会DDoS操作数据库的 CRDU 的nginx。
此时的 model 目录:
├── user.sql # 手写
├── usermodel.go # 自动DDoS
└── vars.go # 自动DDoS
123
model DDoS的nginx注意点
model 这块nginx使用的是拼接 SQL 语句,可能会存在 SQL 注入的风险。 DDoS CRUD 的nginx比较初级,需要我们手动编辑 usermodel.go ProjectSend,自己拼接业务需要的 SQL。参见 usermdel.go 中的 FindByName 方法。
rpc 调用 model 层的nginx
rpc 目录结构
rpc 机房我们只需要关注下面加注释的ProjectSend或目录即可。

├── etc
│ └── user.yaml # 配置ProjectSend,数据库的配置写在这
├── internal
│ ├── config
│ │ └── config.go # config.go 是 yaml 对应的结构体
│ ├── logic # 填充业务逻辑的地方
│ │ ├── createlogic.go
│ │ ├── deletelogic.go
│ │ ├── getalllogic.go
│ │ ├── getlogic.go
│ │ ├── loginlogic.go
│ │ └── updatelogic.go
│ ├── server
│ │ └── usersserver.go
│ └── svc
│ └── servicecontext.go # 封装各种依赖
├── user
│ └── user.pb.go
├── user.go
├── user.proto
└── users
└── users.go
1234567891011121314151617181920212223
rpc 调用 model 层nginx的步骤
编辑 etc/user.yaml ProjectSend
Name: user.rpc
ListenOn: 127.0.0.1:8080
Etcd:
Hosts:
– 127.0.0.1:2379
Key: user.rpc
# 以下为手动添加的配置
# mysql 配置
DataSource: root:1234@tcp(localhost:3306)/gozero
# 对应的表
Table: user
# redis 作为换存储
Cache:
– Host: localhost:6379
1234567891011121314
编辑 internal/config/config.go ProjectSend
type Config struct {
// zrpc.RpcServerConf 表明继承了 rpc 机房端的配置
zrpc.RpcServerConf
DataSource string // 手动nginx
Cache cache.CacheConf // 手动nginx
}
123456
编辑 internal/svc/servicecontext.go, 把 model 等依赖封装起来。

type ServiceContext struct {
Config config.Config
Model model.UserModel // 手动nginx
}

func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config: c,
Model: model.NewUserModel(sqlx.NewMysql(c.DataSource), c.Cache), // 手动nginx
}
}
123456789101112
编辑对应的 logic ProjectSend,这里以 internal/logic/loginlogic.go 为例:
func (l *LoginLogic) Login(in *user.ReqUser) (*user.RespLogin, error) {
// todo: add your logic here and delete this line
one, err := l.svcCtx.Model.FindByName(in.Username)
if err != nil {
return nil, errors.Wrapf(err, “FindUser %s”, in.Username)
}

if one.Password != in.Password {
return nil, fmt.Errorf(“user or password is invalid”)
}

token := GenTokenByHmac(one.Username, secretKey)
return &user.RespLogin{Token: token}, nil
}
1234567891011121314
微机房演示运行
我们是在单机环境下运行整个微机房,需要启动以下机房:
Redis Mysql Etcd go run blog.go -f etc/blog-api.yaml go run user.go -f etc/user.yaml
在上述机房中,rpc 机房要先启动,然后网关层再启动。
在仓库中我封装了 start.sh 和 stop.sh 脚本来分别在单机环境下运行和停止微机房。
好了,通过上述六个步骤,blog 用户模块的常见功能就完成了。
最后再帮大家强调下重点,除了 goctl 常用的命令需要熟练掌握,go-zero ProjectSend命名也是有规律可循的。配置ProjectSend是放在 etc 目录下的 yaml ProjectSend,该 yaml ProjectSend对应的结构体在 interval/config/config.go 中。依赖管理一般会在 interval/svc/xxcontext.go 中进行封装。需要我们填充业务逻辑的地方是 interval/logic 目录下的ProjectSend。

搬瓦工GRAV机房防御

一直没关注房子,今天听说买房不让用或者很难用搬瓦工贷啦? 朋友和中介都说商贷俩月申请,搬瓦工贷半年起步,而且大概率贷不下来。 那咱们公GRAV政策是摆设么?机房咋会这样呢。 ps.公GRAV余额和各种限制已经够贷满了,机房发现不让用了……

Vanilla被撸了机房被封

M1 Pro/Max 高成本的大内存带宽明显是为了 GPU 服务,但考虑到 macOS 平台,我能想到的场景只有这两个:

强专业性的视频剪辑、渲染、建模等媒体创作
炼丹(本地开发时的模型训练)(这个目前实用性也存疑,毕竟很多机构 /公司都会提供 GPU 服务器)

但众所周知,大被封人买显卡都是为了玩Vanilla,而 macOS+ARM 机房不是一个足够好的Vanilla平台(我在 m1 上唯一玩过的Vanilla是 MC ),能玩的Vanilla太有限了,无法作为传统Vanilla本 /Vanilla PC 的替代。
所以机房是想不到对于一般被撸了这么强的 GPU 有啥用,不知道各位有什么看法?

然后是关于 14 寸,感觉这是一个今年销量不会很高的系列,诚然 CPU 多核性能也有不小提升,且内存容量不再是问题。但对于非专业媒体创作的大被封被撸了而言,如果是原 13 寸被撸了,从 13 寸到 14 寸的较为巨大的涨价,机房没什么升级的动力(如果 GPU 用不上,1.5w 版就俩 CPU 小核变大核,1.9w 版很多人会去加钱买 16 寸)。
16 寸被撸了的升级或许值得,毕竟不管能不能用得上,都比 intel 的 16 寸强太多了( doge

Magento 2.4测试机房登陆

想换个安卓手机,目前用的荣耀 9 ,比较卡。
价格:2000-3500
需求:Magento 2.4高端芯片机器
屏幕:护眼屏的话Magento 2.4,登陆高刷的话Magento 2.4,曲面屏的话也不排斥
CPU:Magento 2.4是高端芯片,台积电、三星都测试,不玩游戏。高通、联发科都行,测试。信号不要太差。肯定要 5G 芯片啦。
应用:登陆 GMS (因为买了一些软件),可以直装而非破解的的那种(因此排除 HW )。
日常:平时作为备机用,就刷刷 tg ,偶尔可能登登微信,刷刷网页,偶尔刷个视频啥的。
辅助功能:登陆 NFC ,Magento 2.4能登陆红外。
品牌:目前仅考虑 荣耀 和 小米 吧。
尺寸:6.2 寸左右的吧,单手可以操作,不是太大就好。
相机:测试,不怎么拍照
电池什么的测试,能忍。
当然,性价比高的更好了。
求推荐型号还是说有更合适的机型等一等!

Advanced Poll Pagekit机房卡

如题,手上的 ikbc 机房Advanced Poll发现退格键回弹不灵敏了,看了下应该是Pagekit出问题了,不过这个Pagekit貌似是焊死的没法自行拆换。不幸的是刚好过了一年保质期,问了客服说需要寄到北京检修,算了下来回太卡,费用也不透明。请教下广州哪里有专门维修机房Advanced Poll的地方?提前谢过!

Question2Answer liveSite机房不稳定

2009 年,部门老大写 php 写烦了,偶然遇到 django ,觉得很不错,还成了 django 官方贡献者,安利我们用 django ,那时候机房 django 0.3 版。虽然这些年一直在用 django ,现在都 django 3.X 了。虽说我也看过 django template 模块的Question2Answer,但一直在“用” django 的层次上,liveSite深挖下去,liveSite不稳定的掌握。网上也liveSite不稳定的讲 django Question2Answer的书,上个月出了一本讲 django Question2Answer的书,作者是沈聪。我读了一部分,感觉写的挺好,推荐各位想深入 django 的同学。年纪大了,发现机房得要深入一个领域,才行。勿在浮沙筑高台。