php socket应用 | rpc应用

大神的见解:https://www.cnblogs.com/52fhy/p/9293015.html

第一章 socket基础编码

1.1 服务端代码

	<?php
	header("content-type:text/html;charset=UTF-8"); 
	//确保在连接客户端时不会超时
	set_time_limit(0);
	//设置IP和端口号
	$address = "127.0.0.1";
	$port = 1083; //调试的时候,可以多换端口来测试程序!
	/**
	 * 创建一个SOCKET 
	 * AF_INET=是ipv4 如果用ipv6,则参数为 AF_INET6
	 * SOCK_STREAM为socket的tcp类型,如果是UDP则使用SOCK_DGRAM
	*/
	$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("socket_create() 失败的原因是:" . convertToUtf8( socket_strerror(socket_last_error()) ) . "/n");
	//阻塞模式
	socket_set_block($sock) or die("socket_set_block() 失败的原因是:" .convertToUtf8( socket_strerror(socket_last_error()) ) . "/n");
	//绑定到socket端口
	$result = socket_bind($sock, $address, $port) or die("socket_bind() 失败的原因是:" . convertToUtf8( socket_strerror(socket_last_error()) )  . "/n");
	//开始监听
	$result = socket_listen($sock, 4) or die("socket_listen() 失败的原因是:" . convertToUtf8( socket_strerror(socket_last_error()) ) . "/n");
	echo "OK\nBinding the socket on $address:$port ... ";
	echo "OK\nNow ready to accept connections.\nListening on the socket ... \n";
	do { // never stop the daemon
	 //它接收连接请求并调用一个子连接Socket来处理客户端和服务器间的信息
	 $msgsock = socket_accept($sock) or die("socket_accept() failed: reason: " . convertToUtf8( socket_strerror(socket_last_error()) ) . "/n");
	  
	 //读取客户端数据
	 echo "Read client data \n";
	 //socket_read函数会一直读取客户端数据,直到遇见\n,\t或者\0字符.PHP脚本把这写字符看做是输入的结束符.
	 $buf = socket_read($msgsock, 8192);
	 echo "Received msg: $buf \n";
	  
	 //数据传送 向客户端写入返回结果
	 $msg = "welcome 服务器\n ";
	 socket_write($msgsock, $msg, strlen($msg)) or die("socket_write() failed: reason: " . convertToUtf8( socket_strerror(socket_last_error()) ) ."/n");
	 //一旦输出被返回到客户端,父/子socket都应通过socket_close($msgsock)函数来终止
	 socket_close($msgsock);
	} while (true);
	socket_close($sock);
	
	
	function convertToUtf8($str) {
		$encode = mb_detect_encoding($str, array("ASCII",'UTF-8',"GB2312","GBK",'BIG5')); #"EUC-CN" 属于GB2312中的一种 https://blog.csdn.net/qq_37788558/article/details/78241748
		if ($encode != 'UTF-8') {
			$str = mb_convert_encoding($str, 'UTF-8', $encode);
		}
		return $str;
	}

1.2 客户端代码

	<?php
	error_reporting(E_ALL);
	set_time_limit(0);
	echo "<h2>TCP/IP Connection</h2>\n";
	
	$port = 1083;
	$ip = "127.0.0.1";
	
	/*
	 +-------------------------------
	 *    @socket连接整个过程
	 +-------------------------------
	 *    @socket_create
	 *    @socket_connect
	 *    @socket_write
	 *    @socket_read
	 *    @socket_close
	 +--------------------------------
	 */
	
	$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
	if ($socket < 0) {
	    echo "client:socket_create() failed: reason: " . socket_strerror($socket) . "\n";
	}else {
	    echo "OK.\n";
	}
	
	echo "<br>client:试图连接 '$ip' 端口 '$port'...\n";
	$result = socket_connect($socket, $ip, $port);
	if ($result < 0) {
	    echo "<br>client:socket_connect() failed.\nReason: ($result) " . socket_strerror($result) . "\n";
	}else {
	    echo "<br>client:连接OK\n";
	}
	
	$in = "Ho\r\n";
	$in .= "first blood\r\n";
	$out = '';
	
	if(!socket_write($socket, $in, strlen($in))) {
	    echo "<br>client:socket_write() failed: reason: " . socket_strerror($socket) . "\n";
	}else {
	    echo "<br>client:发送到服务器信息成功!\n";
	    echo "<br>client:发送的内容为:<font color='red'>$in</font> <br>";
	}
	
	while($out = socket_read($socket, 8192)) {
	    echo "<br>client:接收服务器回传信息成功!\n";
	    echo "<br>client:接受的内容为:",$out;
	}
	echo "<br>client:关闭SOCKET...\n";
	socket_close($socket);
	echo "<br>client:关闭OK\n";
	?>

1.3 socket通信流程 | tcp握手

大佬地址:Nginx backlog配置概述
参考文章:百度百科
在这里插入图片描述

1.3.1 nginx 配置

1.3.2 php-fpm配置

  • 根据php-fpm的QPS来决定backlog的大小。计算方式最好为QPS=backlog。

1.4 如何查看accept queue溢出

  • netstat –s | grep LISTEN返回*** SYNS to LISTEN sockets ignored

第二章 RPC

RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。

2.1 RPC作用

  • 屏蔽远程调用跟本地调用的区别,让我们感觉就是调用项目内的方法;
    隐藏底层网络通信的复杂性,让我们更专注于业务逻辑。
  • 利用 RPC 我们不仅可以很方便地将应用架构从“单体”演进成“微服务化”,而且还能解决实际开发过程中的效率低下、系统耦合等问题,这样可以使得我们的系统架构整体清晰、健壮,应用可运维度增强。

2.2 应用场景

  • 当然 RPC 不仅可以用来解决通信问题,它还被用在了很多其他场景,比如:发 MQ、分布式缓存、数据库等。下图是我之前开发的一个应用架构图:
    在这里插入图片描述

2.3 调用过程

  • 调用方持续地把请求参数序列化成二进制后,经过 TCP 传输给了服务提供方。服务提供方从 TCP 通道里面收到二进制数据。
  • 所以 RPC 请求在发送到网络中之前,他需要把方法调用的请求参数转成二进制;转成二进制后,写入本地 Socket 中,然后被网卡发送到网络设备中。

2.4 协议

我们把数据格式的约定内容叫做“协议”,大多数的协议会分成两部分,分别是数据头和消息体。数据头一般用于身份识别,包括协议标识、数据大小、请求类型、序列化类型等信息;消息体主要是请求的业务参数信息和扩展属性等。
在这里插入图片描述

2.4.1 如何设计协议

初级版本
在这里插入图片描述

升级版本,可拓展性好在这里插入图片描述
选用序列化格式,
但用 JSON 进行序列化有这样两个问题,你需要格外注意:

  • JSON 进行序列化的额外空间开销比较大,对于大数据量服务这意味着需要巨大的内存和磁盘开销;
  • JSON 没有类型,但像 Java 这种强类型语言,需要通过反射统一解决。
  • 所以性能不会太好。所以如果 RPC 框架选用 JSON 序列化,服务提供者与服务调用者之间传输的数据量要相对较小,否则将严重影响性能。

2.4.2 性能考虑优先级

在这里插入图片描述

2.5 RPC 框架在使用时要注意哪些问题

序列化时,对象不要过于复杂、庞大、不要有复杂的继承关系

  • 对象要尽量简单,没有太多的依赖关系,属性不要太多,尽量高内聚;
  • 入参对象与返回值对象体积不要太大,更不要传太大的集合;
  • 尽量使用简单的、常用的、开发语言原生的对象,尤其是集合类;
  • 对象不要有复杂的继承关系,最好不要有父子类的情况。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值