在当今的技术环境下,微服务架构已经广泛流行并深刻地改变了应用程序的构建和交互方式。
传统上,应用程序之间的通信往往依赖于明确指定 IP 地址与端口号的组合,然而随着微服务理念的推进,服务名称调用逐渐成为主流,这使得我们不得不重新审视应用程序是否还需要指定端口这一问题。
传统架构
图片
从传统的单体应用架构来看,指定端口是实现网络通信的关键步骤。
例如,一个基于 Java 的 Web 应用程序部署在服务器上,开发人员需要为其指定一个特定的端口,如 8080,这样客户端才能通过访问服务器的 IP 地址加上该端口号来请求相应的资源。
在这种模式下,端口的指定明确了应用程序在网络中的接入点,就如同给一座房子确定了一个独一无二的门牌号,方便外界与之进行交互。它使得网络请求能够准确地找到对应的应用程序实例,从而实现数据的传输与处理。
然而,微服务架构带来了全新的思路。在微服务架构中,众多小型的、独立的服务相互协作以构建复杂的应用系统。如果依然采用传统的 IP + 端口的调用方式,会面临诸多问题。
首先,微服务的数量众多且动态变化,服务的启动、停止、更新以及扩展都可能频繁发生。这意味着需要不断地管理和协调大量的端口分配,以避免端口冲突,这无疑是一项复杂且容易出错的任务。
其次,在一个复杂的微服务集群中,服务的 IP 地址可能由于容器编排、自动伸缩等机制而动态变化,依赖固定的 IP + 端口进行调用会使整个系统变得脆弱且难以维护。
微服务架构
图片
随着系统架构升级进化,当大家来到微服务的时代中,服务名称调用机制就展现出了诸多优势。
借助于服务发现组件,如 Consul、Eureka 、Nacos 等,每个微服务在注册中心注册自身时,使用一个具有语义的服务名称而非具体的 IP 和端口。
当一个服务需要调用另一个服务时,它只需向服务发现组件查询目标服务的名称,服务发现组件就会返回可用的服务实例的实际网络地址信息(包括 IP 和端口),然后进行调用。
这种方式将服务的网络细节进行了抽象和封装,使得服务之间的调用更加灵活和可靠。开发人员无需关注具体的端口分配情况,降低了系统的复杂性和维护成本,提高了系统的可扩展性和弹性。
但这并不意味着端口在当今的应用程序中就完全失去了作用。尽管在微服务内部的服务间调用可以通过服务名称来实现,但是端口仍然不可或缺。
例如,在微服务架构中,我们通常都会有一个网关服务对外提供服务,而这个网关服务通常跟流量入口绑定,比如 Nginx、K8s 里的 Ingress、阿里云的 SLB 等。而这些流量入口将流量转到网关服务时,就需要网关服务提供明确的端口了。
在 SpringBoot 应用中如何启动随机端口?
其实很简单,大家都知道 SpringBoot 中可以通过 server.port 指定端口,如果要启动随机端口,将 server.port 设置为 0 即可。
server.port 设置为 0 后,可以让操作系统为我们动态分配一个可用的端口无需我们在手动指定。
最后
OK,传统架构中,大家可能还需要用服务的 ip + 端口来进行通信,在微服务架构中,除了网关应用还需要提供明确的端口号外,业务应用的 ip + 端口号已经被服务发现、注册组件所隐去,大家基本已经不再关心业务应用的端口号了。
在这里也是做一个投票,问一下大家是否愿意在自己的项目中将 server.port设置为0。