[Frodo-V2.0] 拥抱Golang, go~!​zhikai.pro

Frodo-v2.0 没有添加新功能,而是将后端最重要的部分,后台API使用golang重构,python现在只负责前台模板的渲染。这样原本的单服务应用就成了多服务。本文将简介v2.0的调整思路和golang异步的特性,新版本的部署文档请参看项目地址

{

'user': 'LouisYZK',

'repo': 'Frodo',

'right': 0

}

主要重构的模块为:博文、用户、标签等的后台CRUD接口

缓存清理模块

JWT认证模块

why golang?

golang是年轻的语言,新世纪的静态语言。设计理念很好地平衡了C++和 javascript/python等动态语言的优劣,独具特色的goroutine设计范式旨在告别多线程式的并发。而web后台和微服务是go语言用的的最多的领域,故我将后台纯api部分拿go来重写。

我是2019年开始使用kubernetes时开始接触的go语言,当时项目有需求想要扩展一个k8s的api, 官方给的意见是如果想真正的contributor,最好使用golang开发。go语言的代表一定是docker和kubernetes这一最主流的容器与容器编排工具。

其次,使用go语言对我并不痛苦,他的风格介于静态和动态语言,因此你要使用指针来避免冗余的对象复制,同时你也能使用便捷的如python里的动态数据结构。比类C的好处在于他不是那么地接近底层,只需考虑必要的指针操作和类型问题。

而python也越来越多地提倡使用显示类型,在v1.0中就已经使用了类型检查,在python中虽然不能带来性能的提升,但有利于调试和对接静态语言。因此golang的语并不会带来困难。

带类型的python与golang风格十分相似:

async def get_user_by_id(id: int) -> User:

user: User = await User.async_first(id)

return user

在golang中类型是强制的:

func GetUsers(page int) (users []User) {

DB.Where(...).First(&user)

return

}

再来看C++, 明显的不同时类型的位置不一样:

User* getUserById(int id) {

user = User{id}

User::first(&user)

return user

}

最后,最重要的是golang的圈子如何,跟python-web比,golang可选择的余地并不是很多,但也足够用。这次选择的框架是gin和gorm都是轻量且简单的框架。

Challenge

golang的轮子

写习惯动态原因的人(尤其是python/js)会感觉golang数据结构的麻烦:map/struct不能动态添加新属性

没有in这一经常使用的特性

任意类型interface{}到其他类型的转换并没有那么简单

struct,map, json之间的转换并不是很自然

值传递和地址传递时刻要注意

没有方便的集合运算,如交并差,如排序,如格式化生成等。

...

庆幸的是,go语言的开源社区做的很不错,可以直接饮用github的他人完成的包,很多轮子都有现成的实现,首先可以去 https://godoc.org/ 去搜索官方支持的轮子,这些一般是稳定的,受官方认可的,同时可以方便地查看他们的文档。如集合运算我就使用了goset这个库。如果没有在官方找到,可以直接寻求github,直接引用仓库地址即可。(感觉golang包模块很方便吗?目前看来是的,但其实坑也不少...)

多服务网络结构部署没想到V2.0版本麻烦最多是在部署上...

这样我们的博客系统就有两个服务了,golang和uvicorn分别占两个端口,静态文件中做相应的调整,但因为我的部署只能暴露一个端口(因为域名问题,见下图),这样只能借助nginx来转发了。

上图结构有几个配置上的难点:静态资源寻址、路由配置。v1.0但语言版本时比较好配置直接都映射本地地址即可。现在需要明确地分服务在nginx配置转发。同时静态资源上,也要将原先的本地地址更换为域名地址。

golang部分功能还要调用python的服务,如「动态」的api的还是保留在python里,post的 api在golang, 而创建「文章」后需要创建动态,这时golang需要调用python的服务。(这其实很正常,很大的项目也避免不了互相通信的需要。)好在在一台机器上此问题容易解决的多。

等等,缓存会冲突吗? 在「数据篇」中讲到Frodo是有缓存机制的,现在发现python的前台和golang的后台都依赖缓存,这点需要严格的key的统一来保证两个缓存数据的一致性。

Golang的异步与并发

既然将原来python的服务换为golang, 前面提到的异步特性golang能满足吗?其实思想是一致的,只是从asycio和可等待对象变为了goroutine, 拿「博文」创建接口举例:

func CreatePost(data map[string]interface{}) {

post := new(Post)

post.Title = data["title"].(string)

post.Summary = data["summary"].(string)

post.Type = data["type"].(int)

post.CanComment = data["can_comment"].(int)

post.AuthorID = data["author_id"].(int)

post.Status = data["status"].(int)

tags := data["tags"].([]string)

content := data["content"]

DB.Create(&post)

fmt.Println(post)

go post.SetProps("content", content) // go设置内容

go post.UpdateTags(tags) // go 更新标签

go post.Flush() // go 清除缓存

go CreateActivity(post) // go 创建动态

}

可以看到连续使用了4个go分发不能阻塞的任务,这些都是goroutine, 配套的有对他们管理的通信工具和同步原语,每个goroutine也可以继续分发协程,如其中的更新标签:

func (post *Post) UpdateTags(tagNames []string) {

var originTags []Posttag

var originTagNames []string

DB.Where("post_id = ?", post.ID).Find(&originTags)

for _, item := range originTags {

var tag Tag

DB.Select("name").Where("id = ?", item.TagID).First(&tag)

originTagNames = append(originTagNames, tag.Name)

}

_, _, deleteTagNames, addTagNames := goset.Difference(originTagNames, tagNames)

for _, tag := range addTagNames.([]string) {

go CreateTags(tag)

go CreatePostTags(post.ID, tag)

}

for _, tag := range deleteTagNames.([]string) {

go DeletePostTags(post.ID, tag)

}

}

golang没有类似asyncio.gather(*coros)式的分发,采用for循环是一样的实现。目前我已经把简单的系统拆成了两个不同技术类型的服务,可以见到部署难题渐显,接下来的更新就是虚拟化解决环境依赖难题和自动化部署了~

python加go_[Python异步博客开发] 加入Golang, go~!相关推荐

  1. 阿里云运行python项目_荐个人博客开发-06:Nginx + uWSGI + Django项目部署到阿里云服务器运行...

    版本:Python-3.8.1 + Django-2.2 + 阿里云服务器 Ubuntu-16.04 在正式部署前,需要确认几点: 服务器上已经安装相应的 Python MySQL Nginx uWS ...

  2. pythonapi异步_Python-FastAPI异步博客开发记录--异步篇

    异步篇最接近Frodo的初衷了.通信与数据的内容使用传统框架的思路是相同的.而异步思路只改变了若干场景的实现方法.Zhikai-Yang Space​zhikai.proLouisYZK/Frodo​ ...

  3. 使用Python爬取CSDN历史博客文章列表,并生成目录

    使用Python爬取CSDN历史博客文章列表,并生成目录 这篇博客将介绍如何使用Python爬取CSDN历史博客文章列表,并生成目录. 2020年 2020年04月 cv2.threshold() 阈 ...

  4. python数据挖掘领域工具包 - wentingtu - 博客园

    python数据挖掘领域工具包 - wentingtu - 博客园 python数据挖掘领域工具包 - wentingtu - 博客园 python数据挖掘领域工具包 原文:http://qxde01 ...

  5. Python Web企业门户网站—系列博客教程介绍

    本系列教程将使用Python Web的Django框架实现企业门户网站的制作.本教程一共分为8篇博文,将从最基础的Python语法讲起,然后使用Django3逐步搭建一个完整的企业门户网站项目实例.如 ...

  6. python爬虫爬取csdn博客专家所有博客内容

    python爬虫爬取csdn博客专家所有博客内容: 全部过程采取自动识别与抓取,抓取结果是将一个博主的所有 文章存放在以其名字命名的文件内,代码如下 #coding:utf-8import urlli ...

  7. 这几天有django和python做了一个多用户博客系统(可选择模板) 没完成,先分享下...

    这个TBlog已经全新改版了,更名为UUBlog 新版地址: 用Python和Django实现多用户博客系统--UUBlog 断断续续2周时间吧,用django做了一个多用户博客系统,现在还没有做完, ...

  8. Django 3.2.5博客开发教程:体验django模板

    上面我们有说过,用户发送请求的时候,视图会返回一个响应,响应可以是一个重定向,一个404错误,一个XML文档,一张图片或者是一个HTML内容的网页.前面几个返回的信息比较有限,我们重点更多是放在HTM ...

  9. Django 3.2.5博客开发教程:实现模板之前的分析与准备

    在之前的体验django模板.体验数据查询以及一些常用的模板使用方法文章里,向大家介绍了如何将数据库的数据展现到网页上,和一些简单的模板使用方法.之后我们就开始实现各种页面的展现. 在此之前,我们先从 ...

最新文章

  1. 存储过程 psal emp.sal%type是什么意思
  2. 区块链BaaS云服务(11)招商银行ABS区块链平台
  3. 测试 / 单元测试的重要性
  4. Aizu 2170 Marked Ancestor
  5. AD-查找符合指定条件的用户Get-User
  6. java设计模式适配器模式_Java中的适配器设计模式
  7. 4007-基于邻接表的新边的增加(C++,附思路)
  8. graphpad如何加标注_如何以YOLOv3训练自己的数据集 以小蕃茄为例
  9. 坚守本心,你公司的OA解决了以下问题吗?
  10. Python: 组合管理与蒙特卡洛方法实现
  11. presscad图层LIsp_presscad2010免费版
  12. 酒店客房管理系统(C语言)
  13. 服务器系统怎么安装网卡驱动,网卡驱动怎么安装,教您网卡驱动的安装操作
  14. ubuntu 20.04 耳机没有声音
  15. 无线信号的接收流程和接收机中基本结构的具体功能
  16. 《SolidWorks 2014中文版机械设计从入门到精通》——第 1 章 认识SolidWorks 1.1 SolidWorks概述...
  17. kaggle操作入门
  18. win10出现打印机无法打印,而其他显示正常,重启没反应
  19. 晨光科力普基于GitLab CI/CD持续集成服务的应用
  20. 数控编程软件可模拟刀具在三维曲面上的实时加工过程

热门文章

  1. 计算机控制技术黄勤,微型计算机控制技术 教学课件 黄勤 第3章微型计算机控制系统的常用控制.ppt...
  2. java 中适配器原理_Java经典设计模式中关于适配器模式原理以及用法详解
  3. seir模型启发式算法_好文荐读|选址问题的启发式方法
  4. 哪些学校招计算机类在职研究生,2020计算机科学与技术在职研究生有哪些院校可以报考?...
  5. linux7.3怎么修改时区,CentOS7校准核对服务器时区和手动修改时间
  6. 年轻人不讲武德,居然在简历中藏木马!
  7. pyqt漂亮gui界面模板_一种基于模板的C代码自动生成方法
  8. sqlserver 字段中只有年月 加上中文年月_PowerBI 10月更新,全新图标正式亮相
  9. html弧形列表效果,web前端入门到实战:html5网页特效-弧形菜单
  10. for、enumerat、range、xrange