前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Swoole与Go系列教程之HTTP服务的应用

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

原创
作者头像
码农先森
发布2024-07-02 22:42:07
1280
发布2024-07-02 22:42:07

大家好,我是码农先森。

写在前面

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
复制
<?php

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

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

2、启动

代码语言:php
复制
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、访问

代码语言:php
复制
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
复制
<?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、启动

代码语言:php
复制
MacBook-Pro:demo$ php socket.php 
服务器监听在 localhost:8080...

3、访问

代码语言:php
复制
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
复制
<?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、启动

代码语言:php
复制
MacBook-Pro:demo$ php swoole_http.php 
Swoole HTTP服务器已启动

3、访问

代码语言:php
复制
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

代码语言: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、启动

代码语言:go
复制
MacBook-Pro:demo$ go run main.go

3、访问

代码语言:go
复制
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 语言是高并发领域的一支独秀,天然支持高并发,并且能够充分的利用物理资源。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 写在前面
  • HTTP 协议原理
  • 原生 PHP 的实现
    • 使用 PHP 的内置 HTTP 模块启动服务
      • 使用 Socket 的方式启动 HTTP 服务
      • Swoole 扩展的实现
      • Go 语言的实现
      • 总结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档