一、概念
微服务是一种软件架构风格,将大型复杂的应用程序拆分成一系列小型、独立的服务,每个服务都可以独立部署、运行和维护。每个微服务都有自己的数据库、业务逻辑和接口,它们之间通过轻量级"通信机制"相互协作,实现整个应用程序的功能。通过微服务架构,可以提高应用程序的可伸缩性、灵活性、可维护性和可测试性,同时降低开发和部署的复杂度。——资料参考来自百度
通俗地来说,微服务就是一系列独立且专注于单一功能的小型服务程序。在PyCharm这个开发环境中,我们可以将其理解为通过Python语言和相关的框架(如Flask或Django)开发的独立模块。每个模块都承担着特定的职责,并且只聚焦于解决一个具体的问题。微服务的设计理念强调的是服务的专一性和规模适度,每个服务都是围绕特定业务需求构建的,就像Python中的一个项目模块一样。
以下是使用Python实现微服务的示例:
使用Flask或Django等Web框架创建RESTful API服务。例如,使用Flask创建一个用户管理服务:
from flask import Flask, request
app = Flask(__name__)
@app.route('/users', methods=['GET'])
def get_users():
# 获取所有用户的逻辑
pass
@app.route('/users', methods=['POST'])
def create_user():
# 创建新用户的逻辑
pass
if __name__ == '__main__':
app.run()
二、常见的通信机制
微服务架构中的通信机制主要包括同步通信和异步通信两大类。从通讯模式角度考虑是一对一还是一对多?具体细分参见下表
同步通信:
HTTP/REST:这是一种基于HTTP协议的通信风格,它将每个服务抽象为资源,并通过HTTP方法(如GET、POST、PUT、DELETE等)对资源进行操作。HTTP/REST具有简单、易用的特点,广泛应用于微服务间的通信。
RPC:远程过程调用(Remote Procedure Call)允许客户端像调用本地方法一样调用远程服务。与HTTP/REST相比,RPC通常具有更高的性能和更低的网络开销。常见的RPC框架有gRPC、Dubbo等。
异步通信:
消息队列:服务之间通过消息队列进行异步通信,可以提高系统的解耦和并发能力。常见的消息队列中间件有RabbitMQ、Kafka等。
事件驱动:服务之间通过发布-订阅模式进行事件驱动的通信,可以实现高度解耦和可扩展性。
三、最底层通信原理
最底层通信原理主要是基于网络协议的。以Socket为例,它是一种基于TCP/IP协议的通信方式,可以实现不同服务之间的数据传输。
socket支持两种传输方式,tcp和udp(Tcp在发包前需要先建立连接,udp直接发包不需要建立连接。)
Tcp套接字:SOCK_STREAM,udp套接字:SOCK_DGRAM
Socket通信包括服务器端和客户端,服务器端创建一个Socket并绑定到指定端口,然后监听客户端的连接请求;客户端创建一个Socket并连接到服务器端的地址(IP)和端口(port),之后双方就可以进行数据传输了。
注意:Socket的send和receive 的消息包必须是ASCII字节。如果想传输字符串或者字典列表,需要先进行编码,可以用utf-8编码方式。
Socket底层实现可以分为TCP长连接、TCP短连接和UDP无连接三种方式。下面分别阐述这三种方式的实现原理和代码示例。
TCP长连接
TCP长连接是指在客户端与服务器之间建立一个持久的连接,通信双方可以在这个连接上进行多次数据传输。在TCP长连接中,客户端和服务器之间的连接会一直保持打开状态,直到一方主动关闭连接或者网络中断。
Python代码示例:
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 8080))
server_socket.listen(5)
while True:
client_socket, client_address = server_socket.accept()
print(f"客户端{client_address}已连接")
while True:
data = client_socket.recv(1024)
if not data:
break
print(f"收到来自{client_address}的数据: {data.decode()}")
client_socket.sendall(data)
client_socket.close()
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 8080))
client_socket.sendall("Hello, Server!".encode())
data = client_socket.recv(1024)
print(f"收到来自服务器的数据: {data.decode()}")
client_socket.close()
TCP短连接
TCP短连接是指客户端与服务器之间每次通信时都创建一个新的连接,通信完成后立即关闭连接。这种方式适用于一次性的数据传输,不需要保持连接状态。
Python代码示例:
server.py
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 8080))
server_socket.listen(5)
while True:
client_socket, client_address = server_socket.accept()
print(f"客户端{client_address}已连接")
data = client_socket.recv(1024)
print(f"收到来自{client_address}的数据: {data.decode()}")
client_socket.sendall(data)
client_socket.close()
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 8080))
client_socket.sendall("Hello, Server!".encode())
data = client_socket.recv(1024)
print(f"收到来自服务器的数据: {data.decode()}")
client_socket.close()
UDP无连接
UDP无连接是指客户端与服务器之间不需要建立连接,直接发送数据包。这种方式适用于实时性要求较高的场景,如音视频通话、在线游戏等。
Python代码示例:
server.py
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(('localhost', 8080))
while True:
data, client_address = server_socket.recvfrom(1024)
print(f"收到来自{client_address}的数据: {data.decode()}")
server_socket.sendto(data, client_address)
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client_socket.sendto("Hello, Server!".encode(), ('localhost', 8080))
data, server_address = client_socket.recvfrom(1024)
print(f"收到来自服务器的数据: {data.decode()}")
client_socket.close()
四、怎么选型轻量级
关于socket的tcp长连接和短连接之间的差异:
1)长连接在接收到客户端的连接请求后,会循环处理业务逻辑
2)长连接的服务需要闭环通道释放机制,否则会造成通道积压的问题,随着新的连接建立,进而导致内存使用率逐步递增。
3)长连接从客户端的角度,可以实现主动关闭通道
4)长连接从客户端的角度可以在同一连接下重复处理业务
在工作中如何正确选型和实现轻量级,需要我们清楚微服务轻量级通信机制的原理:通信时尽可能少的资源利用率。 比方说对外协议服务于大量用户用长连接的话会导致服务端存储的消息通道过大,进而导致内存溢出,此时应选用短链接。对于内部频繁调用的业务接口请求,为避免频繁申请建立连接,导致效率低,应选用长连接。