The first two articles introduced the background of this series of articles and the service splitting of the mall system according to the business functions , Each of these services can be divided into the following three categories :
- api service - BFF layer , External provision HTTP Interface
- rpc service - Internally dependent microservices , Realize a single business function
- rmq service - Responsible for processing streaming tasks , Such as consumption kafka wait
- admin service - Provide for internal management background HTTP Interface , Generally, the data operation permission is relatively high
If you haven't read the first two articles, you can view them through the following portal
go-zero Micro service practical series ( One 、 The opening )
go-zero Micro service practical series ( Two 、 Service split )
The first two articles are more theoretical , So that after the article was sent out, some students felt that it was more watery , I really understand your eagerness to write code , I also had a profound reflection, hahaha . Therefore, from the beginning of this article, we will enter the code phase that is expected by all . however , The so-called sharpening a knife does not miss the woodcutter , In the real production development process , We usually spend a lot of time on understanding requirements and designing protocols , If the requirements are not understood thoroughly or the agreement design is unreasonable, it will greatly increase the possibility of project rework , You have to refactor before you even go online . So it is worthwhile to invest more time in the early stage . When we understand the requirements thoroughly , After the project structure and agreement are clearly defined , In fact, writing code is a matter of pushing the boat with the current , That's a lot faster . Idle time , Let's start today's content .
API Definition
You may have encountered such a scenario in your work , The code is updated but the document is not updated , Thus, some problems will arise and some wrangling will happen . The essence of this problem is that services and documents are separated . What we expect is that the document is the protocol , Agreement as a service , This idea and go-zero Of api The definitions coincide .
We defined BFF layer ,BFF Is to provide HTTP The unified exit of the interface , So here we are API The definition of is mainly aimed at BFF Service API The definition of .
API The compatibility of
We define or modify API You must consider forward compatibility , The following situations are forward compatible :
- Add new API Interface protocol
- Request parameters to add fields , It is necessary to ensure that the new and old clients handle this field differently
- Add a field to the response result , This field information will only be displayed in the new version client
The following situations are forward incompatible :
- Delete or rename service 、 Field 、 Such method , essentially , If the client code can reference something , Then deleting or renaming it is an incompatible change , In this case, it must be modified major Version number
- Modify field type , This causes the code generated by the client library to change , Therefore, it is necessary to add major Version number , For compiled static languages , Compilation errors may occur
- Modify the visible behavior of an existing request , Clients often rely on API Behavior and semantics , Even if such behavior is not explicitly supported or documented . therefore , in the majority of cases , modify API The behavior or semantics of the data will be regarded as destructive by consumers
- Add... To the resource message Read / write in Field
home page API Definition
The home page function is mainly divided into four parts , Search for 、Banner chart 、 Limited time rush purchase and recommended product list , Clicking the search box will jump to the search page , The recommended part is displayed in pages , Users can load the next page by constantly sliding up . By analyzing the homepage, we need to provide three interfaces , Namely Banner Interface , Time limited snap up interface and recommended interface .
The recommended interface should be noted here , It is recommended that the data returned by the interface should support paging , Here, the paging adopts the cursor method ,Ps The parameter is the number of data pieces returned per page , The default page returns 20 Data , Note that the server must be verified again Ps value , prevent Ps Performance problems caused by malicious values , such as Ps Yes 10000, When it is an illegal value, you need to set Ps Set to default ,Cursor Is the cursor value , The cursor is the last piece of data on each page RecommendTime.
Return value Products Defines the returned product list ,IsEnd Indicates whether it is the last page , The client judges IsEnd Is it true Decide whether to terminate the request ,RecommendTime The recommended time for the last piece of data returned for this page , The push list returns in reverse order of the recommended time .
RecommendRequest {
Cursor int64 `json:"cursor"`
Ps int64 `form:"ps,default=20"` // The size of each page
}
RecommendResponse {
Products []*Product `json:"products"`
IsEnd bool `json:"is_end"` // Is the last page
RecommendTime int64 `json:"recommend_time"` // The recommended time of the last item in the product list
}
Product {
ID int64 `json:"id"` // goods ID
Name string `json:"name"` // The product name
Description string `json:"description"` // Commodity Description
Price float64 `json:"price"` // commodity price
Stock int64 `json:"stock"` // stock
Category string `json:"category"` // classification
Status int64 `json:"status"` // state :1- normal ,2- Off the shelf
CreateTime int64 `json:"create_time"` // Creation time
UpdateTime int64 `json:"update_time"` // Update time
}
Snapping up has a countdown function , Let's return to the start time of rush buying , The client counts down the remaining time .
FlashSaleResponse {
StartTime int64 `json:"start_time"` // Start time of rush buying
Products []*Product `json:"products"`
}
classification API Definition
You can switch between different categories in the classification list tab To choose different categories , At the same time, you can sort according to different dimensions under each category , And support paging .
The sorting method of the classified product list is the same as that of the recommended interface , They all use the cursor , At the same time, the classified goods list needs to be sorted according to different classification and sorting attributes , For this sort of list that needs sorting, we will generally use redis Of sorted set To achieve ,score For the attribute to be sorted , Like sales ,member For the corresponding product id.
CategoryListRequest {
Cursor int64 `form:"cursor"` // Paging cursor
Ps int64 `form:"ps,default=20"` // The size of each page
Category string `form:"category"` // classification
Sort string `form:"sort"` // Sort
}
CategoryListResponse {
Products []*Product `json:"products"`
IsEnd bool `json:"is_end"`
LastVal int64 `json:"last_val"`
}
mention sorted set Here is a writer who uses sorted set A pit once trodden on . The common pose we use for caching is cache aside Pattern , Read cache first , If the cache hits, the data will be returned directly from the cache , If the cache is read miss 了 , Then back to the source DB Middle reading data , And in order to read data faster later , from DB The data read in is pushed back into the cache , And will set an expiration time for the cache .
In order to ensure the consistency of cache and database data , When we add new data, we need to write this data to the cache to ensure that the cache is consistent with the database data , The general code will be written like this , Through the first Exists Determine the corresponding cache key Whether there is , If it exists, go to sorted set Add a piece of data , If it does not exist, it will not be processed , Wait until the next time you read the list, reload the list data into the cache . We found that sometimes the list data in the cache will become a , But there are actually many pieces of data , At that time, I felt very strange , The problem is finally located through troubleshooting , Turned out to be Exists Operation and Zadd The two operations are not caused by atomic operations , That is to say Exists Cache when Key It hasn't expired yet , But in Exists After and during Zadd Before this key Out of date , And then execute Zadd As a result, only the newly added data is in the cache list . The solution to this problem is very simple , Don't use Exists Judge key Whether there is , But through Expire Here it is key Renewal , If key Nonexistence Expire return 0,key There are Expire return 1, Renewal succeeded . We have also stepped through many holes in the use of cache , Especially in high concurrency scenarios , This follow-up article will introduce in detail .
The shopping cart API Definition
Here we limit the number of shopping carts , We limit the shopping cart to a maximum of 200 A commodity , This is done so that placing an order when all is selected will not cause excessive write magnification , Because of the addition of 200 Restrictions on , So the shopping cart list doesn't need to be paged .
The shopping cart list request and return are defined as follows :
CartListRequest {
UID int64 `form:"uid"`
}
CartListResponse {
Products []*CartProduct `json:"products"`
}
CartProduct {
Product *Product `json:"product"`
Count int64 `json:"count"` // Purchase quantity
}
Product evaluation API Definition
The function of product evaluation also needs to support paging , Use the cursor to page , At the same time, reverse the order according to the comment time
The comment list is defined as follows :
ProductCommentRequest {
ProductID int64 `form:"product_id"`
Cursor int64 `form:"cursor"`
Ps int64 `form:"ps,default=20"`
}
ProductCommentResponse {
Comments []*Comment `json:"comments"`
IsEnd bool `json:"is_end"` // Is the last page
CommentTime int64 `json:"comment_time"` // Time of the last comment in the comment list
}
Comment {
ID int64 `json:"id"` // Comment on ID
ProductID int64 `json:"product_id"` // goods ID
Content string `json:"content"` // Comment content
Images []*Image `json:"images"` // Comment on the picture
User *User `json:"user"` // User information
CreateTime int64 `json:"create_time"` // Comment on time
UpdateTime int64 `json:"update_time"` // Update time
}
User {
ID int64 `json:"id"` // user ID
Name string `json:"name"` // user name
Avatar string `json:"avatar"` // Head portrait
}
Image {
ID int64 `json:"id"`
URL string `json:"url"`
}
The above lists some of the core API The definition of , The mall has many function points , It is difficult to define all in a short time , The author will continue to improve after work . When defining the data returned by the interface, we should try to converge and only return the necessary data .
Well defined api after , We use the following command to regenerate the project code , The following information is output to indicate that the generation is successful
$ goctl api go -api api.api -dir .
etc/api-api.yaml exists, ignored generation
internal/config/config.go exists, ignored generation
api.go exists, ignored generation
internal/svc/servicecontext.go exists, ignored generation
internal/handler/homebannerhandler.go exists, ignored generation
internal/handler/flashsalehandler.go exists, ignored generation
internal/handler/recommendhandler.go exists, ignored generation
internal/handler/categorylisthandler.go exists, ignored generation
internal/handler/cartlisthandler.go exists, ignored generation
internal/handler/productcommenthandler.go exists, ignored generation
internal/logic/homebannerlogic.go exists, ignored generation
internal/logic/flashsalelogic.go exists, ignored generation
internal/logic/recommendlogic.go exists, ignored generation
internal/logic/categorylistlogic.go exists, ignored generation
internal/logic/cartlistlogic.go exists, ignored generation
internal/logic/productcommentlogic.go exists, ignored generation
Done.
RPC Definition
because BFF Only responsible for data assembly , The real source of data is that each micro service passes through RPC Interface provide , Next, let's define the proto. The order list page shown below consists of two parts of data , They are order data and commodity data , That's our BFF Need to rely on order-rpc and product-rpc To complete the assembly of the page data , Let's define order-rpc and product-rpc
order.proto The definition is as follows ,service The name is Order, Added Orders Get order list rpc Interface .
syntax = "proto3";
package order;
option go_package="./order";
service Order {
rpc Orders(OrdersRequest) returns(OrdersResponse);
}
message OrdersRequest {
int64 user_id = 1;
int32 status = 2;
int64 cursor = 3;
int32 ps = 4;
}
message OrdersResponse {
repeated OrderItem orders = 1;
bool is_end = 2;
string create_time = 3;
}
message OrderItem {
string order_id = 1;
int64 quantity = 2;
float payment = 3;
int64 product_id = 4;
int64 user_id = 5;
int64 create_time = 6;
}
Use the following command to regenerate the code , Note that you need to rely on protoc-gen-go and protoc-gen-go-grpc Two plug-ins , If it is installed, an error will be reported by executing the following command
$ goctl rpc protoc order.proto --go_out=. --go-grpc_out=. --zrpc_out=.
After the generation is completed, start order-rpc service , Output is as follows :
$ go run order.go
Starting rpc server at 127.0.0.1:8080...
{"level":"warn","ts":"2022-06-09T15:42:21.680+0800","logger":"etcd-client","caller":"[email protected]/retry_interceptor.go:62","msg":"retrying of unary invoker failed","target":"etcd-endpoints://0xc000029c00/127.0.0.1:2379","attempt":0,"error":"rpc error: code = DeadlineExceeded desc = latest balancer error: last connection error: connection error: desc = \"transport: Error while dialing dial tcp 127.0.0.1:2379: connect: connection refused\""}
{"@timestamp":"2022-06-09T15:42:21.682+08:00","caller":"zrpc/server.go:90","content":"context deadline exceeded","level":"error"}
panic: context deadline exceeded
What circumstance ? It's a mistake , Fortunately, the log output is quite detailed , From the log, you can see that it seems to be local etcd Has not started , Then we'll take the local etcd start-up , Run again after startup order rpc service , Already listening on the default 8080 On port
$ go run order.go
Starting rpc server at 127.0.0.1:8080...
product.proto The definition is as follows
syntax = "proto3";
package product;
option go_package="./product";
service Product {
rpc Products(ProductRequest) returns(ProductResponse);
}
message ProductRequest {
string product_ids = 1;
}
message ProductResponse {
repeated ProductItem products = 1;
}
message ProductItem {
int64 product_id = 1;
string name = 2;
string description = 3;
string image_url = 4;
}
Execute the following command to generate product rpc Code for
$ goctl rpc protoc product.proto --go_out=. --go-grpc_out=. --zrpc_out=.
Be careful ,goctl Generated rpc The service listens on by default 8080 port , Because we are now testing locally , So the product rpc The default port is changed to 8081, And then start the service .
Name: product.rpc
ListenOn: 127.0.0.1:8081
Etcd:
Hosts:
- 127.0.0.1:2379
Key: product.rpc
$ go run product.go
Starting rpc server at 127.0.0.1:8081...
Because of our BFF Need to rely on order.rpc and product.rpc, We need to add the configuration file first , as follows :
Name: api-api
Host: 0.0.0.0
Port: 8888
OrderRPC:
Etcd:
Hosts:
- 127.0.0.1:2379
Key: order.rpc
ProductRPC:
Etcd:
Hosts:
- 127.0.0.1:2379
Key: product.rpc
And then in ServiceContext Add RPC The client of , as follows :
type ServiceContext struct {
Config config.Config
OrderRPC order.Order
ProductRPC product.Product
}
func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config: c,
OrderRPC: order.NewOrder(zrpc.MustNewClient(c.OrderRPC)),
ProductRPC: product.NewProduct(zrpc.MustNewClient(c.ProductRPC)),
}
}
Finally, just click on the order interface logic Add logic to the method , This is just a demonstration , So it's going to be easier :
func (l *OrderListLogic) OrderList(req *types.OrderListRequest) (resp *types.OrderListResponse, err error) {
orderRet, err := l.svcCtx.OrderRPC.Orders(l.ctx, &order.OrdersRequest{UserId: req.UID})
if err != nil {
return nil, err
}
var pids []string
for _, o := range orderRet.Orders {
pids = append(pids, strconv.Itoa(int(o.ProductId)))
}
productRet, err := l.svcCtx.ProductRPC.Products(l.ctx, &product.ProductRequest{ProductIds: strings.Join(pids, ",")})
if err != nil {
return nil, err
}
var orders []*types.Order
for _, o := range orderRet.Orders {
if p, ok := productRet.Products[o.ProductId]; ok {
orders = append(orders, &types.Order{
OrderID: o.OrderId,
ProductName: p.Name,
})
}
}
return &types.OrderListResponse{Orders: orders}, nil
}
Then request the order interface in the browser , You can see that the following data is output , Description from BFF To RPC The link of has been opened :
http://127.0.0.1:8888/v1/order/list?uid=123
{
"orders": [
{
"order_id": "20220609123456",
"status": 0,
"quantity": 0,
"payment": 0,
"total_price": 0,
"create_time": 0,
"product_id": 0,
"product_name": " Test product name ",
"product_image": "",
"product_description": ""
}
],
"is_end": false,
"order_time": 0
}
Table structure definition
Data isolation is required between different microservices , Each microservice has exclusive database resources , adopt RPC Call to get data dependencies , The overall structure is shown in the figure below :
Through the above pairs API We have a general understanding of what data fields are required , Let's start to design the data table , The table creation statement is placed in the project root directory data.sql In file , This file is constantly updated , The main involved libraries and tables are defined as follows :
The user table mainly stores user information , stay user The library may be extended in the future, such as user points , User level and other functions
CREATE DATABASE user;
USE user;
CREATE TABLE `user` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT ' user ID',
`username` varchar(50) NOT NULL DEFAULT '' COMMENT ' user name ',
`password` varchar(50) NOT NULL DEFAULT '' COMMENT ' User password ,MD5 encryption ',
`phone` varchar(20) NOT NULL DEFAULT '' COMMENT ' cell-phone number ',
`question` varchar(100) NOT NULL DEFAULT '' COMMENT ' Password recovery problem ',
`answer` varchar(100) NOT NULL DEFAULT '' COMMENT ' Get back the password ',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ' Creation time ',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ' Update time ',
PRIMARY KEY (`id`),
KEY `ix_update_time` (`update_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=' User table ';
The commodity warehouse mainly involves commodity table and commodity classification table :
CREATE DATABASE product;
USE product;
CREATE TABLE `product` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT ' goods id',
`cateid` smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT ' Category Id',
`name` varchar(100) NOT NULL DEFAULT '' COMMENT ' Name of commodity ',
`subtitle` varchar(200) DEFAULT NULL DEFAULT '' COMMENT ' Product subtitle ',
`images` text COMMENT ' Picture address ,json Format , For expansion ',
`detail` text COMMENT ' Goods details ',
`price` decimal(20,2) NOT NULL DEFAULT 0 COMMENT ' Price , Company - Yuan keeps two decimal places ',
`stock` int(11) NOT NULL DEFAULT 0 COMMENT ' Inventory quantity ',
`status` int(6) NOT NULL DEFAULT 1 COMMENT ' Goods state .1- On sale 2- Off the shelf 3- Delete ',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ' Creation time ',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ' Update time ',
PRIMARY KEY (`id`),
KEY `ix_cateid` (`cateid`),
KEY `ix_update_time` (`update_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=' Commodity list ';
CREATE TABLE `category` (
`id` smallint(6) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT ' classification id',
`parentid` smallint(6) NOT NULL DEFAULT 0 COMMENT ' Parent category id When id=0 It is the root node , Primary categories ',
`name` varchar(50) NOT NULL DEFAULT '' COMMENT ' Category name ',
`status` tinyint(4) NOT NULL DEFAULT 1 COMMENT ' Category status 1- normal ,2- obsolete ',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ' Creation time ',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ' Update time ',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=' List of commodity categories ';
The shopping cart
CREATE DATABASE cart;
USE cart;
CREATE TABLE `cart` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT ' The shopping cart id',
`userid` bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT ' user id',
`proid` bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT ' goods id',
`quantity` int(11) NOT NULL DEFAULT 0 COMMENT ' Number ',
`checked` int(11) NOT NULL DEFAULT 0 COMMENT ' Whether to choose ,1= Checked ,0= Uncheck ',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ' Creation time ',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ' Update time ',
PRIMARY KEY (`id`),
KEY `ix_userid` (`userid`),
KEY `ix_proid` (`proid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=' Shopping cart table ';
Order related :
CREATE DATABASE order;
USE order;
CREATE TABLE `orders` (
`id` varchar(64) NOT NULL DEFAULT '' COMMENT ' Order id',
`userid` bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT ' user id',
`shoppingid` bigint(20) NOT NUMBER DEFAULT 0 COMMENT ' Receipt information sheet id',
`payment` decimal(20,2) DEFAULT NULL DEFAULT 0 COMMENT ' Actual payment amount , Unit is the yuan , Keep two decimal places ',
`paymenttype` tinyint(4) NOT NULL DEFAULT 1 COMMENT ' Payment type ,1- Pay online ',
`postage` int(10) NOT NULL DEFAULT 0 COMMENT ' The freight , Unit is the yuan ',
`status` smallint(6) NOT NULL DEFAULT 10 COMMENT ' The order status :0- Cancelled -10- Unpaid ,20- Paid ,30- To be delivered 40- To be received ,50- Successful trade ,60- Deal closed ',
`payment_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT ' Time of payment ',
`send_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT ' Delivery time ',
`end_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT ' Completion time ',
`close_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT ' Closing time ',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ' Creation time ',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ' Update time ',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=' The order sheet ';
CREATE TABLE `orderitem` (
`id` bigint(20) UNSIGNED NOT NULL COMMENT ' Order sub table id',
`orderid` varchar(64) NOT NULL DEFAULT '' COMMENT ' Order id',
`userid` bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT ' user id',
`proid` bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT ' goods id',
`proname` varchar(100) NOT NULL DEFAULT '' COMMENT ' Name of commodity ',
`proimage` varchar(500) NOT NULL DEFAULT '' COMMENT ' Product image address ',
`currentunitprice` decimal(20,2) NOT NULL DEFAULT 0 COMMENT ' Unit price of goods when generating order , Unit is the yuan , Keep two decimal places ',
`quantity` int(10) NOT NULL DEFAULT 0 COMMENT ' The number ',
`totalprice` decimal(20,2) NOT NULL DEFAULT 0 COMMENT ' Commodity price , Unit is the yuan , Keep two decimal places ',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ' Creation time ',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ' Update time ',
PRIMARY KEY (`id`),
KEY `ix_orderid` (`orderid`),
KEY `ix_userid` (`userid`),
KEY `ix_proid` (`proid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=' Order details ';
CREATE TABLE `shopping` (
`id` bigint(20) UNSIGNED NOT NULL COMMENT ' Receipt information sheet id',
`orderid` varchar(64) NOT NULL DEFAULT '' COMMENT ' Order id',
`userid` bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT ' user id',
`receiver_name` varchar(20) NOT NULL DEFAULT '' COMMENT ' Receiving name ',
`receiver_phone` varchar(20) NOT NULL DEFAULT '' COMMENT ' Receiving landline ',
`receiver_mobile` varchar(20) NOT NULL DEFAULT '' COMMENT ' Receiving mobile phone ',
`receiver_province` varchar(20) NOT NULL DEFAULT '' COMMENT ' Province ',
`receiver_city` varchar(20) NOT NULL DEFAULT '' COMMENT ' City ',
`receiver_district` varchar(20) NOT NULL DEFAULT '' COMMENT ' District / county ',
`receiver_address` varchar(200) NOT NULL DEFAULT '' COMMENT ' Detailed address ',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ' Creation time ',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ' Update time ',
PRIMARY KEY (`id`),
KEY `ix_orderid` (`orderid`),
KEY `ix_userid` (`userid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=' Receipt information sheet ';
Payment related :
CREATE DATABASE pay;
USE pay;
CREATE TABLE `payinfo` (
`id` bigint(20) UNSIGNED NOT NULL COMMENT ' Payment information form id',
`orderid` varchar(64) NOT NULL DEFAULT '' COMMENT ' Order id',
`userid` bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT ' user id',
`payplatform` tinyint(4) NOT NULL DEFAULT 0 COMMENT ' payment platform :1- Alipay ,2- WeChat ',
`platformnumber` varchar(200) NOT NULL DEFAULT '' COMMENT ' Payment serial number ',
`platformstatus` varchar(20) NOT NULL DEFAULT '' COMMENT ' Payment status ',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ' Creation time ',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ' Update time ',
PRIMARY KEY (`id`),
KEY `ix_orderid` (`orderid`),
KEY `ix_userid` (`userid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=' Payment information form ';
Conclusion
This article describes how to define API, And according to the defined api File by goctl Generate service code , The whole project involves api A lot , There is no way to define it all at once , It will be continuously supplemented in the future .
Then it demonstrates how to do this in BFF Call in service RPC service , Connect the entire call link , This is just for demonstration, so the code is dead , Back RPC The returned data will be obtained from the cache or database .
Finally, the main libraries and tables involved in the whole project are defined , We have adopted the microservice architecture , Data between services is isolated , Each service has its own database .
The preliminary preparations have been basically completed here , The latter is mainly to complete the business functions according to the requirements , And optimize for high concurrency .
Due to the limited level of the author , There will inevitably be misunderstandings , If you find something you can improve , I hope I can get your valuable advice .
in addition , If you're interested , You are very welcome to join us , Let's finish this project together , Contribute to the community .
I hope this article can help you , thank you .
Every Monday 、 Thursday update
Code warehouse https://github.com/zhoushuguang/lebron
Project address
https://github.com/zeromicro/go-zero
Welcome to use go-zero
and star Support us !
WeChat ac group
Focus on 『 Microservice practice 』 Official account and click Communication group Get community group QR code .
go-zero Micro service practical series ( 3、 ... and 、API Definition and table structure design ) More articles about
- Micro service practical series --Nginx Official website ( turn )
This is a Nginx A series written on the official website , There are seven articles in total , as follows Introduction to Microservices (this article) Building Microservices: Using ...
- Micro service practice ( 3、 ... and ): In-depth inter process communication of microservice architecture - DockOne.io
original text : Micro service practice ( 3、 ... and ): In-depth inter process communication of microservice architecture - DockOne.io [ Editor's words ] This is the third article in a series of creating your own applications using microservice architecture . The first chapter introduces the microservice architecture pattern , Compared with the single mode , And discuss how to make ...
- Chris Richardson Micro service practical series
Micro service practice ( One ): The advantages and disadvantages of microservice architecture Micro service practice ( Two ): Use API Gateway Micro service practice ( 3、 ... and ): In-depth inter process communication of microservice architecture Micro service practice ( Four ): Feasible solutions and practical cases of service discovery Microservice practice ( 5、 ... and ) ...
- ASP.NET Core Micro service practical series
Hope to give you 3-5 Minutes of fragmented learning , Maybe by subway . Wait for the bus , Many a little make a mickle , Little strokes fell great oaks , Hard coding , If you eat an egg and think it tastes good , I hope you like it , Thank you for your attention . Preface Here is a record of where individuals struggle and grow up , This article is just a series of contents and ideas ...
- SpringCloud Micro service practice —— Chapter III service governance
Spring Cloud Eureka Service governance It is the core and basic module in the microservice architecture . It is used to realize the automatic registration and discovery of each microservice instance . Service registration : In the service governance framework , Will build a registry , Each service unit is registered with ...
- Micro service practical series ( 7、 ... and )- gateway springcloud gateway
1. Scene description springcloud When it was first launched, it used netflix Family bucket , For routing zuul, But it is said that zull1.0 There are big performance problems when accessing large amounts of data ,2.0 It's not integrated into springcloud It's in , ...
- Go + gRPC-Gateway(V2) Build a series of micro services , Applet login authentication service : Chapter one ( Enclosed development demo)
brief introduction The applet can easily obtain the user id provided by wechat through the login ability provided by wechat official , Quickly build the user system within the applet . series Cloud native API gateway ,gRPC-Gateway V2 On The business process Official development access document ...
- Micro service practice ( 3、 ... and ): With MySQL For example , Understand those so-called database military regulations in principle
Link to the original text : Microservicing database design and separation of reading and writing ( source : Liu Chao's popular Cloud Computing ) Database is always the most critical part of application , At the same time, the higher the concurrency , Databases often become bottlenecks , If the database tables and indexes are not well designed at the beginning , Then the later database is horizontal ...
- Spring-cloud Micro service practice 【 3、 ... and 】:eureka Registry Center ( in )
recall , In the last article , We created two springboot project , And in consumer Project approval restTemplate Conduct HTTP signal communication , Successfully visited producer Provided interface , Think about this reality ...
- Micro service practical series ( Two )- Registry Center Springcloud Eureka client
1. Scene description A few days ago, I introduced springcloud Of Eureka Registry Center (springcloud- Rapid building of registry ), Combine today springboot-web introduce eureka Client service registration . 2. Explain ...
Random recommendation
- Get started POI La ...
library For the sake of efficiency, we built such a library : Now the version number 1.14( January 14 update version ..) http://pan.baidu.com/s/1c0SoGfu [source] http://pan.baidu.com ...
- Big data processing objects CLOG BLOG
File The use of file classes decimal type ( Normalize the form of decimal ) longtext type ( Store character big data ) Save the text file to the database InputStream FileInputStream CLOG Class ...
- A typical check is for float Precision understanding code
-rand()%); vy = ); vz = ); pList_particle[i].m_velocity = Vector3(vx,vy,vz); ... 1,3 Line code vx and vz The range of can be determined by ...
- 【 everyday scrum】NO.7
Yesterday: Learning and designing route programming Today: Write code Problem:. When designing and querying tour routes , The whole logic is very confusing , Imagine all kinds of trees , Graph and network traversal problem , But after many exchanges with students and online inquiry ...
- Slony-I The deletion of :
Continued :http://www.cnblogs.com/gaojian/p/3196244.html ordinary Slony-I Set instance How to delete slony What about the relevant content . I'll find another machine , install slony, ...
- basic API-StdIn.java
/************************************************************************* * Compilation: javac StdI ...
- The finger of the sword Offer39 Find and in the array for sum Two numbers of
/************************************************************************* > File Name: 39_TwoNum ...
- I*k->AK
Convert convolution to product : function A = GetA(I,m,n) %GetA get A which transforms [email protected] to A*k % I is the input imageP; ...
- [Mac] mac linux Multi thread download tool axel
> I have done some statistics on file downloading before , Discover Google Chrome chrome And fox firefox, It is usually a single thread download file ,360 Browsers are multi-threaded downloads . Now switch to mac On , Found no 360 Which browser , It's like ...
- python-day65-django Basics
One .MTV Model 1. Official statement : Django Of MTV Represent the : Model( Model ): Objects responsible for business objects and databases (ORM) Template( Template ): Responsible for how to display the page to users View( View ): In charge of the business ...