欢迎光临
我们一直在努力

(1)从零开始:Windows网关+RabbitMQ+Linux+MySQL的全链路实践

前言:

  项目的背景来自于个人对于未来的职业规划和一次偶然的头脑风暴:大概三个月多前,我开始学习Android和Kotlin,目的是为了让之前的一个个人项目完成从PC端到移动端的迁移。在学习过程中,由于条件的限制,我没有足够的设备进行完整的APK分发和APP实机测试流程,于是我转而投向了电脑上的各类模拟器。由于模拟器本身可以看作一个可交互虚拟机,因此我选择在其中进行相关的APP调试。而调试的过程中由于个人的职业规划偏向后端,所以我开始尝试改变其中简单的JSON临时储存,改用MySQL这类专业数据库。MySQL作为数据库,传统的图形化界面(比如Windows,虽然有许多类似DataGrip的辅助工具,但是我个人还是喜欢使用自动化的脚本和命令行)难以有效的进行维护和开发,于是作为后端的重要技术之一,Linux的学习也就自然提上了日程,并使用了VMwareWorkstationPro运行Linux虚拟机。如上,我在对于MySQL练习,APK分发模拟,Linux虚拟机配置的过程中,产生了一个构想:Windows这类操作系统中拥有丰富的可用端口,结合之前我接触到的本地域名和HTML知识,是否可以通过多个虚拟机在单台宿主机上的运行,借助不同的端口和本地域名,模拟一个较为完整的通讯模型?于是,项目的设计开始了。经过暑假对各种知识的学习,基础的设计架构得以不断迭代到一个理论可行的版本。现在,我将开始对项目逐步实践并进行总结,作为个人的技术记录的同时,也发布到网络上供人避免实践过程的各种错误或者进行可能的借鉴。

一.关于Linux和虚拟环境:

  对于我来说,配置Linux虚拟机和最开始的使用部分还是让我花了一些时间,从VMware本身的下载到对于虚拟机内容的逐步熟悉再到对于Linux的具体操作,中间有不少问题,在这里我会挑选几个进行详细描述。

1.关于Linux命令行:

  Linux提供了丰富的系统指令供我们进行具体的操作,由于内容过多,我在此仅进行一小部分的讨论,用以记录个人对Linux命令行的学习和理解,以常见且实用的更新指令为例子:在执行sudo apt update 代码后会出现类似的部分输出:

其中我们发现,tsinghua这个镜像站出现在了我们的update队列中,对于Windows用户来说,使用powershell或者CMD进行命令行式的软件下载时,往往需要我们进人工的path和域名指定才能顺利避开使用官方网址带来的严重延迟或者根本链接不上的情况,如果拿我个人距离就是在使用AndroidStudio时对于gradle的下载在没有指定对应的国内镜像站或者使用一些VPN的情况下会变得非常困难。幸运的是,Linux给出了它自己的解——由于目前的发行版众多,维护一个类似于Google Store那种的庞大平台是很难的,因此在发行版运营自己的仓库的同时,各个公司,高校,科研单位等会搭建镜像站,比如我们现在看到的tsinghua就是在国内比较流行的一个,其余还有ali,tencent,中科大等,这里不多赘述。Linux会根据我们所在的地理位置获取最近的镜像服务器,在 /etc/apt/sources.list 文件中写入一个或多个镜像站地址。然后尝试获取内容,如果失败,就会换到下一个网址。同样的,我们在install相应的软件时,也遵循类似逻辑 ,所以Linux在这里确实给了我相对于Windows最直观的体验提升  。                                

2.关于文本编辑器和双端开发:

  作为Linux上的主流编辑器Vim和nano各有优劣,由于我是新手,我最开始选择了nano。通过使用如下命令,我们得以进行文本的编辑

cd /mnt/hgfs/publicfiles/scripts
nano producer.py

如你所见,我们现在进入了脚本文件的内部,并可以进行对于文本的编辑,具体的使用我不展开

但是nano本身的使用却有个问题:python作为一个需要严格控制缩进的语言,对于文本格式有较高的要求。在最开始的几次编写中,由于nano对于自动缩进功能的一些缺陷和我个人的能力问题,我在运行时需要频发的修改.py脚本,这让我非常烦躁。于是我选择使用Windows宿主机上的PyCharm,结合之前我在学习python时留下的一些环境进行对脚本的开发。当然,这会带来一个问题——如何将脚本文件进行双端共享?幸运的是,VMware为我们提前解决了问题:

通过VMware提供的共享文件夹功能,我们得以轻松的实现双端开发,当然还有一些别的路径,比如远程开发,这里选择使用publicfiles是因为当前项目体量较小,而且操作较为方便。所以我们现在可以同时享受Linux的脚本自动化操作和Windows上IDE带来的舒适开发环境。

3.关于Linux上的python环境:

  当我在Linux上尝试编写并运行python脚本时,有一个问题就很自然的出现了:Linux本身自带python作为系统工具用来运行诸如前文提到的apt等指令,但是对于我们具体的开发,还需要进行虚拟环境,也就是venv的搭建。我们可以用pip3指令(或者pip)进行对于对应包的安装,安装应当包含Windows和Linux两端。

pip install flask pika requests mysql-connector-python ##Windows/PyCharm
pip3 install pika mysql-connector-python ##Linux

之后,就需要对venv进行创建,需要注意的问题在于,venv和terminal之间的关系。在实际的开发过程中,我需要开启多个终端,但是每个终端对应的虚拟环境需要单独激活。所以为了避免项目和环境之间关系的错乱,我建议对不同的目录创建不同的环境,并进行有效保存,当然,这也是venv的主要目的之一,但作为新手,我确实被venv的管理混乱折磨过,所以在这里做个提醒。

python3 -m venv myenv ##创建名为myenv的虚拟环境
source myenv/bin/activate ##激活

二.关于MySQL和RabbitMQ

  在当前的后端开发或者说整个计算机行业来说,就我个人体会,消息队列和数据库是每个人的必修课,学习,实践,工作或多或少都应该会用到相关知识。对该项目来说,MySQL和RabbitMQ本身的操作其实并不算过于复杂,至少是可以接受的,主要的问题在于如何将它们融入一个更大的项目中,同时确保它们得到正确且高效的使用。虽然真实的开发环境会更加复杂,但即使是当前的模拟环境仍会带来许多对我这个初学者来说很陌生的知识,下面挑选几个具体实例。

1.关于MySQL中SQL操作和python脚本的结合

  MySQL作为一个关系型数据库,它为我们日常的CRUD提供了有效的工具,其中的各类型SQL语句自然是格外重要,得益于python提供的跨平台能力,我们得以进行基于脚本的自动化SQL,这于我们之前提到的双端开发相对应。接下来我会基于一个简单的实例记录我作为一个新人的理解:

#!/usr/bin/env python3 ##shebang声明,供python解释器进行识别

import mysql.connector
from mysql.connector import Error ##导入库

DB_CONFIG = {
"host": "localhost",
"user": "root",
"password": "password",
"database": "employees" ##一些基本的MySQL配置,可随着情况改变
}

def main():
conn = None
try:
conn = mysql.connector.connect(**DB_CONFIG)
if conn.is_connected(): ##作条件判断,通过conn.is_connected()作为一个bool值提供判断依据,防止无意义的消耗

cursor = conn.cursor() ##游标定义

sql = """
SELECT d.dept_name, COUNT(de.emp_no) AS employee_count
FROM departments d
JOIN dept_emp de ON d.dept_no = de.dept_no
WHERE de.to_date = '9999-01-01'
GROUP BY d.dept_name
ORDER BY employee_count DESC; ##一些基本的查询语句,可以随情况进行改变
"""

cursor.execute(sql) ##执行

rows = cursor.fetchall() ##使用

print("\\emp_nums of departments:")
print("-" * 40)
for row in rows:
print(f"department: {row[0]:<20} emp_nums: {row[1]}")
print("-" * 40)

except Error as e:
print(f"failed:{e}") ##输出错误,作为debug的依据

finally:
if conn and conn.is_connected():
if cursor:
cursor.close()
conn.close()

if __name__ == "__main__": ##通过检测这里进行对于main()的循环,达到自动化
main()

当然,脚本本身的功能性可以进行不断的扩展,比如通过加入crontab,也就是Linux系统自带的一个定时功能,实现定时执行,其余还有很多会在之后的文章中,随着我的学习实践陆续提及。

2.关于RabbitMQ和跨平台通讯

  其实在选择RabbitMQ前我产生的主要疑问在于:为什么不能使用Linux自己的消息队列?我在之前的项目中曾经用到过Windows的消息队列,而且由于Qt的使用经验,我经常会和各种信号,或者“消息”打交道,最初的想法是将Linux自身的API进行调用从而获取MySQL的活动信号,然后传回Windows,同理Windows本身也会调用自身API进行和Linux的沟通——最开始我认为这只不过是以往经验的一次复用,但很明显这是一个思维的误区。

  在Windows中,我们有完善的hook和pipe技术并结合窗口消息队列实现单机内部的开发,当然这也是我之前接触过的,所以比较熟悉,对于Linux这个我新接触的领域,我只粗看了SystemV这种POSIX这种比较基本的机制,但它们都只能在单机范围内发挥高效的功能,回顾我们的实验环境,Linux虚拟机和Windows宿主机在这时就需要一个合格的中间件才能实现跨平台通讯。对于正常的企业开发来说,Kafka绝对会是个好的选择,但是由于Kafka部署和运行操作带来的高成本和项目本身体量的限制,百万级高并发的场景难以模拟,于是更简单的RabbitMQ进入了我的视野,接下来我会进行对于RabbitMQ的具体操作(当然,写这篇的时候我对它的了解还很有限):

  我在这里会省略关于安装RabbitMQ的具体步骤,但是有一点要提醒:不要忘记下载Erlang环境,RabbitMQ基于Erlang编写,我们刚搭建的Linux虚拟环境是没有对应运行条件的。同样的,如果你是Windows上的使用者,

  对我来说使用RabbitMQ的首要问题就是如何将Linux和Windows两个不同平台的信息在Windows上汇集并进行管理,基于当前环境,我们假定Linux作为生产者,Windows作为消费者(其实我个人认为很多时候生产者和消费者的身份会发生转换,这里先不谈),我先演示一个基础的模型:

sudo rabbitmqctl add_user begoniazhao 0905 ##创建用户,指定用户名begoniazhao和密码0905
sudo rabbitmqctl set_user_tags begoniazhao administrator ##设置指定用户的权限为管理员
sudo rabbitmqctl set_permissions -p / myuser ".*" ".*" ".*" ##具体的权限设置,比如读写等等。

现在我,也就是begoniazhao用户已经被创建了,不同于RabbitMQ自带的guest,也就是默认用户,guest只能在localhost上进行访问,就好像是你自己创建一个本地8080端口的HTML,本机确实可以流畅访问,但是对于项目追求的对真实环境的模拟是远远不够的,这也是RabbitMQ发挥用处的场景

sudo ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:3f:1b:0b brd ff:ff:ff:ff:ff:ff
inet 192.168.153.128/24 brd 192.168.153.255 scope global dynamic noprefixroute ens33
valid_lft 1405sec preferred_lft 1405sec
inet6 fe80::20c:29ff:fe3f:1b0b/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether d6:57:bf:f5:5d:65 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
##当前运行的就是Linux自带的IP show 指令,可以看到
##一串域名192.168.153.128,那就是我们需要的Linux虚拟机IP,下面我们要用到它

  下面结合具体的消费者consumer.py脚本为示例

import pika ##导入需要的库

credentials = pika.PlainCredentials('begoniazhao', '0905') ##指定用户和密码
connection = pika.BlockingConnection(
pika.ConnectionParameters(host='192.168.153.128', credentials=credentials)
) ##指定对应的LinuxIP地址
channel = connection.channel() ##声名链接通道

channel.queue_declare(queue='hello') ##定义队列为hello

def callback(ch, method, properties, body):
print(f" [x] Received {body}") ##发送信息,至于body,我之后和数据包转发中的header一起说

channel.basic_consume(queue='hello', on_message_callback=callback, auto_ack=True)
##callback回调,接触过Windows消息队列,或者Android开发的JNI和API接口编写会很熟悉,之后会展开说

print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()

  当然,这只是最简单的RabbitMQ,随着后续的学习,我会学到更复杂的部分,那时我会对它产生更深入的理解,并给出更好的记录。

三.关于通讯

  在我的个人理解中,项目基本的通讯应当以Windows作为中间件,或者比喻成邮箱更加形象——Linux作为服务器server,Windows作为web网关前台,Android作为native终端。其中Windows还会承担RabbitMQ的面板功能,因为Windows上的Edge浏览器提供了一个本地HTTP管理面板运行的有效环境,上面提到过的Linux IP在这里又可以发挥作用:

  这里我们发现了一个陌生的端口15672,我这里和5672一块讲解,同时也在这里进行一个提醒:以我使用的Ubuntu发行版为例,如果开启了系统防火墙功能UFW,那么就需要我们进行相关功能的设置,具体来说可以理解为放行某些特定的端口

sudo ufw allow 5672/tcp
sudo ufw allow 15672/tcp
sudo ufw status
##这里我们看到了TCP协议,这也是RabbitMQ得以实现跨平台通讯的关键
##和AMQP一样构成了RabbitMQ这类消息队列的基本逻辑
##之后随着我学习的深入
##我会给出专门的记录和个人理解

  对于5672端口,其实就是RabbitMQ的默认端口(类似于MySQL默认端口为3306),负责链接消费者和生产者,对我们的环境来说就是Windows和Linux,让Windows上的消息得以正确的传到在Linux上运行的RabbitMQserver。而对于15672端口,则是作为HTTP的管理端口,我们之前提到过的guest和自定义的begoniazhao这里会体现出差别——guest作为default的默认用户不能访问15762,它只能在Linux虚拟机上的localhost进行访问,因此我们的begoniazhao作为自定义的管理用户在这里就可以发挥作用。在这里,我们得以发现在项目的模拟环境中,Linux和Windows已经构成了一个仿真的远程服务器和运维环境——Windows的begoniazhao这里就实现了对Linux上RabbitMQ的”远程访问“,而Linux虚拟机成为了”服务器所在的内网“。

后续的一些想法:

  作为一个刚上大二的学生,当前的项目体量其实有些偏大,截至到今天,我对项目的具体构造才开始大概一周不到。幸好,课余时间目前还是比较充足。如果让我说个人的体会,我会说深度不会太大,但是广度确实是我遇到最大的,从网络协议,数据库运维再到不同系统的调试,编程语言的多样性……总得来说,符合预期,实践起来也出现了一些挑战。作为一个学习者,我认为这个项目至少可以锻炼我的工程能力和思考能力,通过不断的学习和实践,总归是有些用的。

  项目的完整实现估计会耗费我至少半个学期,作为一个长期的专栏,后续我会不断更新,大概一两周一篇,记录自己的一些技术总结和想法,如果有人看到这里,我欢迎你指正我的一些错误,当然,如果帮到了你一点点小忙,我也会衷心的为你感到开心。

 

 

赞(0)
未经允许不得转载:171主机测评 » (1)从零开始:Windows网关+RabbitMQ+Linux+MySQL的全链路实践
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址