C编程语言用于分布式系统?当然的事情。
#编程 #distributedsystems #c #vely

什么是分布式计算

分布式计算是两个或多个用于共同用途的服务器。通常,某些任务在许多计算机之间进行了分配,并且它们都可以共同努力完成。请注意,“单独的服务器”可能意味着物理分开的计算机。这也可能意味着虚拟服务器,例如虚拟私人服务器(VPS)或容器,它们可能共享相同的物理硬件,尽管它们在网络上显示为单独的计算机。

您可能需要这种设置的原因有很多。完成任务所需的资源可能并非全部在一台计算机上。例如,您的应用程序可能依赖于多个数据库,每个数据库都位于其他计算机上。或者,您可能需要将请求分发给您的应用程序,因为一台计算机不足以同时处理它们。在其他情况下,您使用的是远程服务(例如基于REST API),而本质上的服务则位于其他地方。

在任何情况下,包括您的分布式系统组成的计算机可能位于本地网络上,或者它们可能是在全球范围内或某种组合的计算机。吞吐量(每秒可以通过网络交换多少个字节)和延迟(数据包通过网络旅行需要多长时间)显然会有所不同:对于本地网络,您将具有较高的吞吐量和较低的延迟,以及对于互联网服务器将恰恰相反。根据您期望的服务质量进行相应的计划。

服务器如何通信

根据您的网络设置,要求各种通信。如果两个服务器驻留在本地网络上,那么他们通常会使用最快的通信方法。本地网络通常意味着一个安全的网络,因为除了您之外,没有其他人可以访问它。因此,您将不需要TSL/SSL或任何其他类型的安全协议,因为这会放慢速度。

,如果两个服务器在Internet上,则必须使用安全协议(例如TSL/SSL或其他其他协议),因为您的通信可能会被监视。

本地网络分布式计算

大多数时候,您的分布式系统将在本地网络上。从物理意义上讲,这种网络可能是独立的和私人的,也可以(更常见的是)虚拟含义,在云提供商为您建立某种私有云网络的情况下。很可能通过专门的硬件(例如路由器和防火墙)和安全的协议来强制分离,以使属于不同客户的网络分开。这样,即使上面的计算机是一个与众不同的,也可以建立一个“本地”网络,尽管通常它们是较大的本地网络的一部分。

无论哪种方式,就您的应用程序而言,您正在查看本地网络。因此,这里的示例将是这种情况,因为它很可能是您所拥有的。本地网络意味着驻留在不同服务器上的应用程序的不同部分将使用基于TCP/IP的某些有效协议。一个这样的协议是FastCGI,这是一种用于服务器,客户端和各种一般程序之间通信的高性能二进制协议,这就是这里使用的。因此,原则上,设置看起来像这样(稍后会有更多细节):
Vely image

先决条件

install Vely(最小版17.3)开头,将用于创建应用程序服务器。请注意,您可以使用类似的代码来调用远程PHP FPM服务,因为它也使用FastCGI协议!

接下来,从理论上讲,您应该有两个服务器,但是在此示例中,这两个服务器都将在同一局部主机上(即“ 127.0.0.1”)。这只是为了简单。如果您在本地网络上有两个不同的服务器,则该代码完全相同 - 只需为“远程”服务器而不是本地“ 127.0.0.0.1”,只需使用另一个IP(例如“ 192.168.0.15”)。这两个服务器甚至不一定需要在物理上是两台不同的计算机。您可以在计算机上启动虚拟机(VM),并在那里托管另一台虚拟计算机。流行的免费软件(例如VirtualBox或KVM管理程序)可以帮助您做到这一点。

无论如何,在此示例中,您将启动两个简单的应用程序服务器;他们将彼此交流。第一个将称为“本地”,另一台“远程”服务器。本地应用程序服务器将向遥控器提出请求。

本地服务器

在本地服务器上,为您的本地应用程序服务器源代码创建一个新目录:

mkdir local_server
cd local_server

然后创建一个新文件“ status.vely”,以下内容:

#include "vely.h"

void status() {
    silent-header
    out-header default
    // input parameter: the IP address of remote server
    input-param server
    // input parameter: number of days to ask the status for
    input-param days

    // Create URL payload for remote server
    // such as "/days/18" to get status for 18 days
    pf-out "/days/%s", days to define payload
    // Create a string describing the remote server
    // so if "server" is "192.168.0.15", then it would
    // be 192.168.0.15:3800, meaning it runs on TCP port 3800
    pf-out "%s:3800", server to define srv_location

    // Create a remote server connection
    new-server define srv location srv_location \
        method "GET" app-path "/server" \
        request-path "/remote_status" \
        url-payload payload \
        timeout 30

    // Call the remote server
    call-server srv
    // Get the results from remote server
    read-server srv data define dt
    // Print out the results
    @Output is: [<<p-out dt>>]
}

这里的代码非常简单。 new-server将在TCP端口3800上在IP地址“服务器”(并使用input-param)给出的IP地址上运行的远程服务器的新连接。在字符串变量“有效负载”中创建的URL有效负载传递给远程服务器。如果它在30秒内没有回复,则代码将超时。然后,您正在使用call-server实际上调用远程服务器(由应用程序“服务器”和请求处理程序“ emote_status.vely”提供),最后是read-server以从中获得答复。为简单起见,此处省略了错误处理,但是您可以轻松地检测超时,任何网络错误,远程服务器中的任何错误,包括错误代码和错误文本等。请参阅上述语句。

制作并启动本地服务器

接下来,创建一个本地应用程序:

sudo vf -i -u $(whoami) client

制作应用程序(即编译源代码并构建本机可执行文件):

vv -q

最后,启动本地应用程序服务器:

vf -w 2 client

这将启动2个本地应用程序服务器的服务器实例。

远程服务器

好吧,现在您拥有本地服务器。接下来,您将设置远程服务器。登录到您的远程服务器并为您的远程应用程序服务器创建一个新目录:

mkdir remote_server
cd remote_server

然后使用此代码创建文件“ remote_status.vely”:

#include "vely.h"

void remote_status() {
    silent-header
    out-header default
    input-param days

    pf-out "Status in the past %s days is okay", days
}

这很简单,它只是回答状态还可以。它接受检查状态并显示后面的天数。在实际服务中,您可以查询数据库以检查状态(请参阅run-query)。

制作并启动远程服务器

首先创建您的应用程序:

sudo vf -i -u $(whoami) server

然后制作您的程序:

vv -q

最后启动服务器:

vf -w 2 -p 3800 server

这将启动2个作为背景服务器运行的守护程序进程。他们将从您本地服务器提供请求。

请注意,如果您在不同的计算机上运行此示例,则某些Linux发行版带有防火墙,并且您可能需要使用ufwfirewall-cmd在此处使用端口3800。另外,如果您在此服务器上使用SELinux,则可能需要允许绑定到端口3800,或者使Selinux Persissive(使用“ sudo setenforce 0”)。

运行分布式呼叫

有多种方法可以调用您创建的远程服务。这些是您 local 服务器进行的调用,因此将目录更改为:

cd local_server

这是调用远程应用程序服务器的各种方式:

  • 在本地服务器上执行命令行计划,该程序调用远程应用程序服务器: Vely image 为此,请使用vv实用程序的“ -r”选项生成shell命令,可以用来调用您的程序:
vv -r --req "/status/days/18/server/127.0.0.1"

在这里,您要说的是,您想在本地服务器上提出请求“状态”(属于源文件中的状态。您还说,输入参数“天”的值应为“ 18”,并且输入参数“服务器”的值应为“ 127.0.0.0.1” - 参见上述文件中的input-param语句。如果您实际上具有不同的IP服务器,请使用它代替“ 127.0.0.1”。上述结果可能是:

export REQUEST_METHOD=GET
export SCRIPT_NAME="/client"
export PATH_INFO="/status/days/18/server/127.0.0.1"
export QUERY_STRING=""
/var/lib/vv/bld/client/client

执行此操作,结果将是:

Output is: [Status in the past 18 days is okay]

“ [..]”之间的零件来自远程服务器,而“输出为:”部分来自您执行的命令行Vely程序​​。

export SCRIPT_NAME="/server"
export PATH_INFO="/remote_status"
export QUERY_STRING="days=12"
cgi-fcgi -connect "127.0.0.1:3800" /server

结果是:

Status in the past 12 days is okay

在这种情况下,输出直接来自远程服务器,因此“输出为:”零件丢失。 “ CGI-FCGI”实用程序只需将远程服务的输出复制到标准输出。

  • 使用命令行实用程序联系本地应用程序服务器,然后拨打远程服务器,该服务器回复回到本地应用程序服务器,该服务器回复回到您的命令行实用程序: Vely image 您将使用FastCGI_command_line_client进行此操作:
export SCRIPT_NAME="/client"
export PATH_INFO="/status/server/127.0.0.1"
export QUERY_STRING="days=10"
cgi-fcgi -connect /var/lib/vv/client/sock/sock  /client

结果是:

Output is: [Status in the past 10 days is okay]

这就是您所期望的。请注意,在这种情况下,某些输入参数位于request_URL(“ path_info”中的“ server”)和Query String中的一些路径(“ query_string”中的“ days”)中。另外,在这种情况下,“ CGI-FCGI”实用程序首先将请求发送到您的本地应用程序服务器,该服务器将其发送到远程服务,因此有“输出为:”输出。

设计分布式系统时,您有不同的选项,本文显示了实施它们的容易。