unicorn与nginx通讯--[ruby unix socket]
【龍昌博客】 http://www.xefan.com/archives/84146.html
unicorn是如何与nginx通讯的——介绍ruby中的unix socket
Ruby 应用服务典型地是与一个 web 服务一同使用的,如 nginx。当用户请求你的 Rails 应用中的页面时,nginx 将请求指派给应用服务。
然而这个过程是如何完成的呢?nginx 与 unicorn 是如何通讯的呢?
最有效的一种选择是使用 unix 套接字(sockets)。让我们来看看它们是如何工作的!
在这篇文章中我们将从一个基本的套接字(sockets)开始,最后将创建一个使用 nginx 代理的简单应用服务。
socket
套接字(sockets)允许进程之间通过对一个文件读或者写进行相互通讯。
在这个例子中 Unicorn 创建 socket 并监听它的连接。然后 Nginx 就可以连接到这个 socket 并与 Unicorn 通讯了。
什么是 unix socket?
Unix socket 使得一个进程通过类似文件的方式与另一个进程进行通讯。它是 IPC(Interprocess Communication) 的一种。
要使得可以通过 socket 访问进程,首先需要创建一个 socket 并作为一个文件保存在磁盘中。
然后监听这个 socket 的连入连接。当接收到一个连接时,就可以使用标准 IO 方法进行读写数据。
Ruby 通过以下一组类提供了 unix socket 所需的所有内容:
- UNIXServer - 创建 socket 并保存到磁盘中,并且让你可以监听新连接。
- UNIXSocket - 打开已存在的套接字(sockets)。
注意:还存在着其它类型的 socket,最突出的是 TCP socket。不过这篇文章只处理 unix socket。那么它们之间的区别是什么呢?unix socket 具有文件名。
最简单的 Socket
我们接下来看两个小程序。
第一个是服务端,它创建一个 UnixServer
实例,然后使用 server.accept
等待连接。当收到连接后则相互问候。
需要说明一下,accept
和 readline
方法都会阻塞程序的执行,直到收到内容。
require "socket" server = UNIXServer.new('/tmp/simple.sock') puts "==== Waiting for connection"
socket = server.accept puts "==== Got Request:"
puts socket.readline puts "==== Sending Response"
socket.write("I read you loud and clear, good buddy!") socket.close
在下面这个例子中,我们打开由服务端创建的 socket,然后使用普通的 IO 方法进行发送和接收问候。这里我们有了服务端,现在还需要客户端。
require "socket" socket = UNIXSocket.new('/tmp/simple.sock') puts "==== Sending"
socket.write("Hello server, can you hear me?\n") puts "==== Getting Response"
puts socket.readline socket.close
simple_ruby_socket_example演示一下程序,先运行服务端,然后再运行客户端。你可以看到以下结果:
简单的 Unix socket 服务端/客户端交互的例子。左边是客户端,右边是服务端。
与 nginx 接合
现在我们知道如何创建一个 unix socket 的服务端了,我们可以很容易地与 nginx 接合。
不相信我?让我们来做一个快速的概念验证吧。我修改上面的代码使其输出从 socket 接收到的所有内容。
require "socket" # Create the socket and "save it" to the file system
server = UNIXServer.new('/tmp/socktest.sock') # Wait until for a connection (by nginx)
socket = server.accept # Read everything from the socket
while line = socket.readline
puts line.inspect
end socket.close
当我发起一个 web 请求时,nginx 将如下数据发送到我的服务端上:现在如果我修改 nginx 配置,将请求转发到 /tmp/socktest.sock
socket 上。
我就能看到 nginx 发送来的数据了。(别担心,我们稍后会讨论它的配置的)
request_http
太酷了!这就是一个包含了额外头信息的 HTTP 请求。现在我们准备来构建一个真正的应用服务。
但是,首先让我们讨论一个 nginx 的配置吧。
安装配置 Nginx
如果你还没有安装 nginx 的话,请先安装。对于 OSX 可以 homebrew 简单完成:
brew install nginx
你可以将其保存至 /tmp/nginx.conf
并通过命令 nginx -c /tmp/nginx.conf
运行 nginx。现在我们配置 nginx 将 localhost:2048 的请求通过名为 /tmp/socktest.sock
的 socket 转发到上游服务端。
名字可以是任意的,它仅需要与我们 web 服务的 socket 名字匹配即可。
# Run nginx as a normal console program, not as a daemon
daemon off; # Log errors to stdout
error_log /dev/s tdout info; events {} # Boilerplate http { # Print the access log to stdout
access_log /dev/s tdout; # Tell nginx that there's an external server called @app living at our socket
upstream app {
server unix: /tmp/so cktest.sock fail_timeout = 0;
} server { # Accept connections on localhost:2048
listen 2048;
server_name localhost; # Application root
root /tmp; # If a path doesn't exist on disk, forward the request to @app
try_files $uri/in dex.html $uri @app; # Set some configuration options on requests forwarded to @app
location @app {
proxy_set_header X - Forwarded - For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http: // app;
} }
}
nginx_non_daemon以非后台模式运行 nginx。当你运行 nginx 时它应该看起来像如下这样:
Nginx 以非后台模式运行
自定义应用服务
既然我们已经知道了如何将 nginx 与我们程序进行连接,那么我们就来构建一个简单的应用服务。
当 nginx 将请求转发到我们的 socket 时,它是一个标准的 HTTP 请求。
经过一些处理后我可以决定 socket 是否会返回一个有效的 HTTP 响应,它会在浏览器中显示。
下面这个应用接受任何请求并显示时间戳。
require "socket" # Connection creates the socket and accepts new connections
class Connection attr_accessor :path def initialize(path:)
@path = path
File.unlink(path) if File.exists?(path)
end def server
@server ||= UNIXServer.new(@path)
end def on_request
socket = server.accept
yield(socket)
socket.close
end
end # AppServer logs incoming requests and renders a view in response
class AppServer attr_reader :connection
attr_reader :view def initialize(connection:, view:)
@connection = connection
@view = view
end def run
while true
connection.on_request do |socket|
while (line = socket.readline) != "\r\n"
puts line
end
socket.write(view.render)
end
end
end end # TimeView simply provides the HTTP response
class TimeView
def render
%[HTTP/1.1 200 OK The current timestamp is: #{ Time.now.to_i } ]
end
end AppServer.new(connection: Connection.new(path: '/tmp/socktest.sock'), view: TimeView.new).run
appserver现在运行 nginx 和脚本,然后访问 localhost:2048。请求会发送到我的应用上,然后响应被浏览器渲染。太酷了!
HTTP 请求信息由我们的应用服务输出到 STDOUT
以下就是我们的劳动成果。
timestamp 浏览器中显示服务端返回的时间戳
原文地址: http://blog.honeybadger.io/how-unicorn-talks-to-nginx-an-introduction-to-unix-sockets-in-ruby/
unicorn与nginx通讯--[ruby unix socket]的更多相关文章
- nginx php 使用unix socket 还是tcp?
两种通信方式的分析和总结 从原理上来说,unix socket方式肯定要比tcp的方式快而且消耗资源少,因为socket之间在nginx和php-fpm的进程之间通信,而tcp需要经过本地回环驱动,还 ...
- 转:用unix socket加速php-fpm、mysql、redis的连接
图虫的服务器长期是单机运行.估计除了mysql之外,php-fpm和redis还可以在单机上共存很长时间.(多说服务器早就达成了单机每日2000万+动态请求,所以我对单机搞定图虫的大流量非常乐观) 如 ...
- Nginx 中 fastcgi_pass 监听端口 unix socket和tcp socket差
Nginx 中 fastcgi_pass 监听端口 unix socket和tcp socket差别 Nginx连接fastcgi的方式有2种:unix domain socket和TCP,Uni ...
- nginx和php-fpm通信的两种方式 unix socket和TCP
nginx和fastcgi的通信方式有两种,一种是TCP 一种是unix socket TCP使用的是 127.0.0.1:9000端口,将fastcgi_pass参数修改为127.0.0.1:900 ...
- 【转】nginx 和 php-fpm 通信使用unix socket还是TCP,及其配置
原文: http://blog.csdn.net/pcyph/article/details/46513521 -------------------------------------------- ...
- nginx和php-fpm 是使用 tcp socket 还是 unix socket ?
转自 http://blog.csdn.net/qq624202120/article/details/60957634 从上面的图片可以看,unix socket减少了不必要的tcp开销,而tcp需 ...
- Another MySQL daemon already running with the same unix socket的解决
问题出现: 每周一需要备份一次数据库,即从服务器MySQL导出sql文件,再导入到我机器上虚拟机的MySQL里.但是今天早上连不上,我进入控制台用#service mysqld start强行启动,报 ...
- Unable to start MySQL service. Another MySQL daemon is already running with the same UNIX socket
Unable to start MySQL service. Another MySQL daemon is already running with the same UNIX socket 特征 ...
- 启动Mysql报错:Another MySQL daemon already running with the same unix socket.
启动Mysql报错: Another MySQL daemon already running with the same unix socket. 删除如下文件即可解决 /var/lib/mysql ...
随机推荐
- Spark MLlib KMeans 聚类算法
一.简介 KMeans 算法的基本思想是初始随机给定K个簇中心,按照最邻近原则把分类样本点分到各个簇.然后按平均法重新计算各个簇的质心,从而确定新的簇心.一直迭代,直到簇心的移动距离小于某个给定的值. ...
- sql 上舍下舍運用
[四舍五入取整截取] select round(54.56,0) [向下取整截取] SELECT FLOOR(54.56) [向上取整截取] SELECT CEILING(13.15) --MS ...
- Kali Linux入坑之基本配置(2018.1)
我在?天前就决心如Kali的坑,然而安装kali呀vm tools呀更新呀弄了好几天.期间出现的各种问题在此汇总一下. 1.Kali的安装版本选择 在官网上看到的这么多Kali版本应该怎么选呢,在网上 ...
- C语言面试基础知识整理
一.预处理 1.什么是预编译?何时需要预编译? (1)预编译又称预处理,是做些代码文本的替换工作,即程序执行前的一些预处理工作.主要处理#开头的指令,如拷贝#include包含的文件代码.替换#def ...
- Exception in thread "main" org.I0Itec.zkclient.exception.ZkAuthFailedException: Authentication failure is thrown while creating kafka topic
Exception in thread "main" org.I0Itec.zkclient.exception.ZkAuthFailedException: Authentica ...
- sql优化个人总结(全)
sql优化总结--博客 第一次自己写博客,以后要坚持每掌握一个技能点,就要写一篇博客出来,做一个不满足于一个只会写if...else的程序员. 最近三个月入职了一家新的公司,做的是CRM系统,将公司多 ...
- 移动端和PC端弹出遮罩层后,页面禁止滚动的解决方法及探究
PC端解决方案 pc端的解决思路就是在弹出遮罩层的时候取消已经存在的滚动条,达到无法滚动的效果. 也就是说给body添加overflow:hidden属性即可,IE6.7下不会生效,需要给html增加 ...
- Spire.XLS,生成Excel文件、加载Excel文件
一.组件介绍 Spire.XLS是E-iceblue开发的一套基于企业级的专业Office文档处理的组件之一,全称Spire.Office for .NET.旗下有Spire.Doc,Spire XL ...
- open-vm-tools与VMware Tools
安装VMware Tools经常会出现兼容性不好,系统之间复制文件失灵,并且安装时提示建议使用open-vm-tools,于是放弃vmware-tools的安装,尝试使用open-vm-tools o ...
- 工具(4): Git自助手册
目录: ** 0x01 基础教程/0x02 分支流程/0x03 提交日志/0x04 变化比较/0x05 团队协作/0x06 高级用法/0x07 常见问题(FAQ)/0x08 掌握Git的秘诀 0x01 ...