Swoole与Go系列教程之HTTP服务的应用

简介: PHP 曾是Web开发领域佼佼者,随着业务壮大,异步和高并发方面不足显现。Swoole 曾经尝试填补空白,但局限性也比较的明显。Go 语言的崛起,简洁语法和并发优势吸引大厂使用,吸引了大多数程序员的转型。

大家好,我是码农先森。

写在前面

PHP 曾是Web开发领域佼佼者,随着业务壮大,异步和高并发方面不足显现。Swoole 曾经尝试填补空白,但局限性也比较的明显。Go 语言的崛起,简洁语法和并发优势吸引大厂使用,吸引了大多数程序员的转型。疫情、战争、大环境的恶化等因素加剧了互联网行业内卷,PHP 程序员陷入了困境,因此转型 Go 语言是不二的选择。我从 PHP 转型Go,深知转型之难。因此致力于帮助其他 PHP 程序员转型,分享经验。困境时需抱团取暖,才能走过黎明前的黑暗。

HTTP 协议原理

HTTP 协议是一种用于传输超文本(如HTML)的应用层协议。它是Web通信的基础,负责在客户端和服务器之间传递请求和响应。HTTP 使用 TCP 作为传输协议,通常使用 80 端口进行通信。如下图所示 HTTP 协议在 TCP/IP 网络模型中是处于应用层,是 TCP/IP 协议的一个子集。

请在此添加图片描述
HTTP 协议撑起了互联网的大半江山,可以说没有 HTTP 协议就没有当下的互联网。作为一名 Web 程序的开发者,深入掌握和理解 HTTP 协议尤为重要。下面这张图是表示了 HTTP 的请求报文、响应报文格式,其实相对于其他的协议来说,HTTP 协议是比较简单了,同时也是最常用的。

请在此添加图片描述

原生 PHP 的实现

使用 PHP 的内置 HTTP 模块启动服务

php -S 内置服务器实际上是基于CLI(Command Line Interface)SAPI。当执行php -S命令时,PHP 会以命令行模式启动一个轻量级服务器,监听指定的IP地址和端口。但是,这种内置的服务器并不适合用于生产环境,它是为了便于开发和测试而提供的工具。如果是在生产环境上,建议部署 PHP-FPM,再通过 Nginx 做反向代理的方式实现。

1、代码文件 index.php

<?php

// 设置HTTP响应头,告知浏览器返回的是文本内容
header('Content-Type: text/plain');

// 输出 "Hello, World!" 作为响应
echo "Hello, World! For PHP Module";

2、启动

MacBook-Pro:demo$ php -S 127.0.0.1:8080
[Sat Jul 22 10:30:42 2023] PHP 8.2.5 Development Server (http://127.0.0.1:8080) started

3、访问

MacBook-Pro:demo$ curl http://127.0.0.1:8080
Hello, World! For PHP Module

使用 Socket 的方式启动 HTTP 服务

Socket 是一种用于在网络中进行通信的编程接口。它允许程序在网络上通过 IP 地址和端口号与其他计算机建立连接,从而实现数据的传输和交换。 Socket 是一种低层次的网络编程接口,支持 TCP、UDP、IPv4、IPv6 协议,不能直接支持应用层协议,例如 HTTP 协议等。因此,这里通过使用 Socket 创建一个 TCP 服务器来处理 HTTP 请求。

1、代码文件 socket.php

<?php
$host = 'localhost';  // 如果需要,可以将此处更改为你服务器的IP地址
$port = 8080;         // 服务器监听的端口

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
   
   
    echo "无法创建Socket: " . socket_strerror(socket_last_error()) . PHP_EOL;
    exit(1);
}

socket_bind($socket, $host, $port) or die('无法绑定到指定地址');

socket_listen($socket);
echo "服务器监听在 $host:$port..." . PHP_EOL;

while (true) {
   
   
    $client = socket_accept($socket);

    // 读取客户端的请求
    $request = socket_read($client, 4096);

    // 处理请求(为简单起见,我们只处理GET请求)
    if (preg_match("/GET (.*) HTTP\/1\.1/", $request, $matches)) {
   
   
        $uri = $matches[1];
        $response = "HTTP/1.1 200 SUCCESS\r\n\r\nHello World! For PHP Socket\r\n";
    }

    // 将响应发送给客户端
    socket_write($client, $response);

    // 关闭客户端连接
    socket_close($client);
}

2、启动

MacBook-Pro:demo$ php socket.php 
服务器监听在 localhost:8080...

3、访问

MacBook-Pro:demo$ curl http://127.0.0.1:8080
Hello World! For PHP Socket

Swoole 扩展的实现

Swoole 使用底层 C++ 实现,充分利用了异步非阻塞的网络模型,能够处理大量并发连接,极大地提高了 HTTP 服务的性能。通过事件循环和异步处理,避免了 PHP 单进程模型的瓶颈。

请在此添加图片描述
每一个用户的 HTTP 请求,将由 Master 进程分配到 Worker 进程进行处理,不阻塞主进程的执行;同时,每个 Worker 进程内部会将请求协程化,避免阻塞 worker 进程,这种模式极大的提高了服务的处理能力,如下图源代码中对应使用协程来实现发送数据。

请在此添加图片描述

1、代码文件 swoole_http.php

<?php
// 创建HTTP服务器对象,监听在0.0.0.0:8080端口
$http = new Swoole\Http\Server("0.0.0.0", 8080);

// 设置 Worker 数量
$http->set([
    'worker_num' => 3
]);

// 在启动事件中执行初始化设置
$http->on('start', function ($server) {
   
   
    echo "Swoole HTTP服务器已启动\n";
});

// 监听HTTP请求事件
$http->on('request', function ($request, $response) {
   
   
    // 处理请求
    $response->status(200);
    $response->end("Hello World! For Swoole HTTP\r\n");
});

// 启动HTTP服务器
$http->start();

2、启动

MacBook-Pro:demo$ php swoole_http.php 
Swoole HTTP服务器已启动

3、访问

MacBook-Pro:demo$ curl http://127.0.0.1:8080
Hello World! For Swoole HTTP

Go 语言的实现

Go 语言的轻量级线程Goroutine,能够快速处理大量并发请求。Goroutine 的创建和销毁非常快速,在单个物理线程上可以同时运行成千上万个 Goroutine。并且可以高效的利用多核 CPU,充分的使用物理资源。http.ListenAndServe 启动并监听一个 HTTP 服务,客户端与服务端建立连接后,服务端会交由一个 Goroutine 处理,下面这张图是对应 Go Http 模块源代码的处理逻辑。

请在此添加图片描述

1、代码文件 main.go

package main

import (
    "fmt"
    "net/http"
)

func main() {
   
   
    // 处理请求
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
   
   
        fmt.Fprintf(w, "Hello, World! For Go")
    })

    // 启动HTTP服务,监听在本地的8080端口
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
   
   
        fmt.Println("Error starting server:", err)
    }
}

2、启动

MacBook-Pro:demo$ go run main.go

3、访问

MacBook-Pro:demo$ curl http://127.0.0.1:8080
Hello, World! For Go

总结

  1. 在 PHP 语言层面启动 HTTP 服务并不适合,通常需要结合 PHP-FPM、Nginx 等服务。
  2. Swoole 作为用 C++ 实现的扩展,弥补了 PHP 在异步通信及并发层面的不足,但是,在单进程的模式下无法高效的利用多核 CPU,不能充分的榨干物理资源。
  3. Go 语言是高并发领域的一支独秀,天然支持高并发,并且能够充分的利用物理资源。

欢迎关注、分享、点赞、收藏、在看,我是微信公众号「码农先森」作者。

相关文章
|
13天前
|
监控 Kubernetes Go
全链路追踪 & 性能监控,GO 应用可观测全面升级
当前,大多数面向 Golang 应用的监控能力主要是通过 SDK 方式接入,需要开放人员手动进行埋点,会存在一定问题。对此,可观测 Go Agent 应运而生。本文介绍的阿里云可观测 Go Agent 方案,能通过无侵入的方式实现应用监控能力。
107630 14
|
12天前
|
XML JSON Go
Swoole与Go系列教程之WebSocket服务的应用
在 WebSocket 协议出现之前,Web 应用为了能过获取到实时的数据都是通过不断轮询服务端的接口。轮询的效率、延时很低,并且很耗费资源。
1024 1
Swoole与Go系列教程之WebSocket服务的应用
|
2天前
|
消息中间件 API 数据库
在微服务架构中,每个服务通常都是一个独立运行、独立部署、独立扩展的组件,它们之间通过轻量级的通信机制(如HTTP/RESTful API、gRPC等)进行通信。
在微服务架构中,每个服务通常都是一个独立运行、独立部署、独立扩展的组件,它们之间通过轻量级的通信机制(如HTTP/RESTful API、gRPC等)进行通信。
12 2
|
11天前
|
网络协议 Go
Swoole与Go系列教程之TCP服务的应用
TCP(传输控制协议)的出现是为了解决计算机网络中的数据可靠传输和连接管理的问题。在早期的计算机网络中,特别是在分组交换和互联网的发展初期,网络是不可靠的,存在丢包、错误和延迟等问题。
963 0
Swoole与Go系列教程之TCP服务的应用
|
11天前
|
JSON 应用服务中间件 开发工具
Ngnix的http块自定义服务日志,access.log和error.log,log_format指定日志输出格式设置
Ngnix的http块自定义服务日志,access.log和error.log,log_format指定日志输出格式设置
|
Web App开发 前端开发
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
Every Programmer Should Know These Latency Numbers 1秒=1000毫秒(ms) 1秒=1,000,000 微秒(μs) 1秒=1,000,000,000 纳秒(ns) 1秒=1,000,000,000,000 皮秒(ps) L1 cache reference .
630 0
|
Web App开发 前端开发
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
从hadoop移除机器把需要移除的机器增加到exclueds文件中,强制刷新datanode列表,等待decommission 状态正常后,即可停机下架,如有必要在namenode执行balancer操作。
663 0
|
Web App开发 前端开发 Linux
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
 频繁的文件访问会导致系统的Cache使用量大增   $ free -m   total used free shared buffers cached   Mem: 3955 3926 28 0 55 3459   -...
635 0