小编ska*_*tek的帖子

使用OTP/Erlang作为Web应用程序的基于组件的体系结构的一部分

我有一个Erlang/OTP应用程序,它执行一些业务逻辑.它是用Erlang编写的,主要用于容错,因为我可以轻松地重启系统中一个崩溃的组件(高正常运行时间是最重要的要求).它的每个组件都进行某种特定的"并行"计算.

作为一个工作周期的结果,应用程序生成一个值列表.让我们称这个Erlang/OTP应用程序为"后端".

此Erlang/OTP应用程序还将使用PostgreSQL服务器将结果存储在持久存储中,并存储其计算所需的其他元信息(尚未实现).

接下来我需要为这个Erlang/OTP应用程序添加一个前端 - 一个简单的基于Web的解决方案,可以为Web用户提供服务:接受来自他/她的计算请求,要求后端进行计算和从后端向用户返回结果.

没有可扩展性要求,我认为每天最大用户数不能超过1000.

所以我现在的任务是为我的后端Erlang/OTP应用程序实现一个通用的前端(常见的意思是我有一个典型的用例:访问该站点,注册,登录,使用该应用程序,获取结果一个漂亮的ajax'y看网页,退出).

一方面,我知道代码重用可以节省我很多时间:例如使用Ruby on Rails,我可以免费获得用户身份验证,密码存储,ajax接口和许多其他东西.

另一方面,我对设计一个包含Erlang/OTP + PostgreSQL数据库服务器后端和Web框架(RoR,Django等)作为前端的应用程序一无所知.

我想到了很多问题:Erlang/OTP和Web框架是否应该使用相同的PostgreSQL数据库来共享结果?将计算请求从Web框架发送到Erlang/OTP应用程序并将其取回的最佳方法是什么?我如何监督PostgreSQL服务器 - 它不受OTP容错的保护?

一般来说,我有一些异构软件组件,我想从它们构建一个工作系统('主要'组件是Erlang/OTP应用程序).


我应该从哪里开始这个任务?你能给我任何建议或提示要阅读的资源吗?

PS我试图阅读这个并按照链接,但不太了解.

UPD:我知道芝加哥Boss和其他Erlang网络框架确实存在,但我怀疑它们中的任何一个都有如此成熟的环境,充满活力的社区以及不同插件和库的巨大差异,例如Ruby on Rails,Django或任何PHP基于MVC框架.对?

UPD2:也许我必须更深入地阐述这一点:我还需要前端尽可能保持可维护性.在Erlang中执行它意味着我可能在找到合适的开发人员维护它时遇到问题; 在RoR,Django等中进行操作意味着我可以轻松找到维持前端并增长前端的工作人员.

architecture erlang frontend backend erlang-otp

8
推荐指数
1
解决办法
1613
查看次数

Erlang/OTP架构:用于SOAish服务的RESTful协议

让我们想象一下,我们有一个披萨店的订单处理系统来设计和建造.

要求是:

R1.系统应该是客户端和用例不可知的,这意味着客户可以访问系统,在初始设计期间不考虑该系统.例如,如果披萨店决定其许多客户以后使用三星Bada智能手机,为Bada OS编写客户端将不需要重写系统的API和系统本身; 或者,例如,如果事实证明使用iPad而不是Android设备在某种程度上更适合送货司机,那么创建iPad客户端将很容易,并且不会以任何方式影响系统的API;

R2.可重用性,这意味着如果业务流程发生变化,可以轻松地重新配置系统,而无需重写大量代码.例如,如果稍后披萨店将开始接受在线支付以及接收交付司机的现金(在接受订单VS接受付款时接受付款),那么将系统调整到新的业务流程将很容易;

R3.高可用性和容错性,这意味着系统应该在线并且应该全天候接受订单.

因此,为了满足R3,我们可以使用Erlang/OTP并具有以下架构: 纯Erlang/OTP架构,带有一个RESTful API入口点

这里的问题是这种架构中有很多"硬编码"功能.例如,如果披萨店在订单发出前从接受现金支付转为接受在线支付,则需要花费大量时间和精力来重写整个系统并修改系统的API.

此外,如果披萨店需要对其CRM客户端进行一些增强,那么我们将不得不重写API,客户端和系统本身.

因此,以下架构旨在解决这些问题,从而帮助满足R1,R2和R3: 面向服务的体系结构,具有多个RESTful API入口点

系统中的每个"服务"都是带有RESTful API的Webmachine Web服务器.这种方法具有以下好处:

  • Erlang/OTP的所有优点,因为每个Webmachine都是一个Erlang应用程序,可以监督并可以放入Erlang版本中;
  • 面向服务的体系结构,具有SOA的所有优点 ;
  • 易于适应业务流程的变化 ;
  • 易于向客户端添加新客户端和新功能(例如,向CRM客户端),因为客户端可以使用系统中所有服务的RESTful API,而不是一个"中央"API(就SOA而言的服务可组合性).

因此,基本上,第二张图中提出的系统体系结构是面向服务的体系结构,其中每个服务都有一个RESTful API而不是WSDL协定,每个服务都是一个Erlang/OTP应用程序.

以下是我的问题:

  1. 图2:我想在这里重新发明轮子吗?我应该坚持使用纯Erlang/OTP架构吗?("纯Erlang"表示Erlang应用程序打包到一个版本中,通过gen_server相互通信:call和gen_server:cast函数调用);
  2. 你能说出建议方法中的任何缺点吗?(图2)
  3. 您是否认为维护和增长(R1和R2)这样的系统(图2)比真正的Erlang/OTP更容易?
  4. 这样一个系统的安全性(图2)可能是一个问题,因为有许多入口点对Web开放(所有服务的RESTful API)而不是一个入口点(图1),是不是这样?
  5. 在这样的系统中有几个"编排模块"还是可以存在一些更好的实践?(图2中的"接受订单","CRM"和"调度订单"服务);
  6. 纯粹的Erlang/OTP(图1)在消息传递和协议限制方面是否优于这种方法(图2)?(在我之前的类似问题中部分讨论过,gen_server:调用VS HTTP RESTful调用)

architecture rest erlang soa erlang-otp

8
推荐指数
1
解决办法
1512
查看次数

图表数据库更适合最短路径算法吗?

我的目标是为道路网络编写最短路径算法.

目前我的架构是这样的:我将所有数据存储在启用PostGIS的PostgreSQL数据库中.我做了一个SELECT * FROM ways,在一个有100,000个边缘(方式)的表上花了不到3秒钟,然后我将(Java,Ruby或任何基于任何东西的)最短路径算法应用于已经驻留在内存中的图形.在具有100,000个边缘的图形上,第二个操作可能需要大约1.5秒.

所以,它需要:

  • 2-3秒将数据库中的所有路径加载到内存中并创建图形(节点以方式(边缘)存储在一个表中);
  • 1-1.5秒计算已经在内存中的图形上的最短路径.

这与pgRouting非常相似(根据我的知识,它使用C Boost将图形存储在内存中),除了pgRouting总计大约需要2秒来计算同一数据集上的最短路径(是的,它很快,但是对我来说这是一个黑盒子,所以我需要自己的).

但最近我发现了Graph数据库和Neo4j.在他们的网站上,他们声称"仍然能够在数百万道路和航路点的图表上以亚秒速度进行这些计算,这使得在许多情况下放弃使用K/V存储预先计算索引的正常方法并且能够将路由放入关键路径,可以适应现场条件,建立高度个性化和动态的空间服务."

所以问题是:对于我的特定问题,图表数据库会更快吗?

该问题具有以下属性:

  • 数据库由一个表(方式)组成;
  • 对数据库的唯一查询是获取进入内存的所有方法(构建图形);
  • 我不需要可伸缩性,即图形可能不会增长.

database graph shortest-path neo4j graph-databases

7
推荐指数
1
解决办法
4091
查看次数

Erlang中的并行深度优先搜索比其顺序对应慢

我试图在Erlang中实现一个修改后的并行深度优先搜索算法(我们称之为*dfs_mod*).

我想要得到的只是所有'死胡同路径',这些路径基本上是当*dfs_mod*访问没有邻居的顶点或带有邻居的顶点时返回的路径.我保存每个路径ets_table1,如果我的自定义函数fun1(Path)返回true以及ets_table2如果fun1(Path)回报false(我需要一些客户过滤器来过滤所产生的"死胡同"路径).

我已经实现了这个算法的顺序版本,并且由于一些奇怪的原因,它比并行版本表现更好.

并行实现背后的想法很简单:

  • 参观Vertex[Vertex|Other_vertices] = Unvisited_neighbours,
  • 将其添加Vertex到当前路径;
  • 发送{self(), wait}到'收集'流程;
  • 运行*dfs_mod*为Unvisited_neighbours当前的Vertex一个新的进程 ;
  • 继续运行*dfs_mod*与其余提供的顶点(Other_vertices);
  • 当没有更多顶点要访问时 - 发送{self(), done}到收集器进程并终止;

所以,基本上每当我访问一个带有未访问邻居的顶点时,我会产生一个新的深度优先搜索过程,然后继续其他顶点.

在产生第一个*dfs_mod*进程后,我开始收集所有{Pid, wait}{Pid, done}消息(wait消息是让收集器等待所有done消息).在等待收集器函数返回后的N毫秒内ok.


出于某种原因,这个并行实现的运行时间为8到160秒,而顺序版本仅运行4秒(测试是在具有Intel i5处理器的机器上具有5个顶点的完全连接的有向图上完成的).

以下是我对这种糟糕表现的看法:

  • 我将有向图传递Graph给每个运行*dfs_mod*的新进程.也许digraph:out_neighbours(Graph)从多个进程中反对一个有向图会导致这种缓慢?
  • 我在列表中累积当前路径并将其传递给每个新生成的*dfs_mod*进程,也许传递这么多列表是问题?
  • 每次访问新顶点并将其添加到路径时,我都会使用ETS表来保存路径.ETS属性是([bag, public,{write_concurrency, true}),但也许我做错了什么?
  • 每次我访问一个新的顶点并将其添加到路径时,我检查一个带有自定义函数的路径fun1()(它基本上检查路径是否在带有"m"的顶点之前出现标有字母"n"的顶点,并true/false根据结果返回).也许这fun1() …

parallel-processing erlang depth-first-search

7
推荐指数
1
解决办法
604
查看次数

生成集合中的所有"唯一"子集(不是powerset)

假设我们有一个S包含几个子集的Set :

- [a,b,c]
- [a,b]
- [c]
- [d,e,f]
- [d,f]
- [e]
Run Code Online (Sandbox Code Playgroud)

我们还要说S包含六个独特的元素:a, b, c, d, ef.

我们怎样才能找到S包含每一个独特元素的所有可能子集S

函数/方法的结果应该是这样的:

  1. [[a,b,c], [d,e,f]];
  2. [[a,b,c], [d,f], [e]];
  3. [[a,b], [c], [d,e,f]];
  4. [[a,b], [c], [d,f], [e]].

有没有最佳实践或任何标准方法来实现这一目标?

我将非常感谢伪代码,Ruby或Erlang示例.

ruby erlang set subset powerset

7
推荐指数
1
解决办法
2639
查看次数

EUnit从测试模块输出调试信息

我们说我有一个名为的模块 example.erl

在本单元中,我使用以下构造进行调试:

%%% Switch debugging output on/off:
%-define(DBG(Str, Args), ok).
-define(DBG(Str, Args), io:format(Str, Args)).
Run Code Online (Sandbox Code Playgroud)

它帮助我将各种调试信息输出到Erlang shell:

?DBG("Function fun1 starting... ~n", [])
Run Code Online (Sandbox Code Playgroud)

但是,如果我打电话example.erlexample_tests使用example:test(),这个输出信息不会出现.

如何在EUnit测试期间将其显示出来?

UPD:我找到了一些相关信息,但我仍然不知道如何解决这个问题.

erlang dbg eunit

7
推荐指数
1
解决办法
4453
查看次数

Erlang状态和C/C++集成?

如果我们查看官方文档,我们可以找到各种方法来连接Erlang和C/C++.2009年在这里提出了类似的问题,我想知道自那时以来情况发生了怎样的变化.

是否有任何成熟的稳定库可以完成在Erlang和C之间实现二进制协议的所有肮脏工作?它是eierl_interface,是什么区别它们之间?

我的意思是这似乎是一个非常普遍的问题,我希望有人已经成功地解决了它,并且不再需要编写自己的Erlang端口驱动程序,因为大多数都是通用代码.

PS我也找到了这个库:EPAPI.

c c++ erlang erlang-ports

7
推荐指数
1
解决办法
1046
查看次数

使用Erlang/OTP构建容错的软实时Web应用程序

我想为比萨饼送货店建立一个容错的软实时网络应用程序.它应该有助于披萨店接受来自客户的电话,将它们作为订单放入系统(通过CRM网络客户端),并帮助调度员将订单分配给送货司机.

这些目标并不罕见,但我希望每周7天每天24小时提供服务,即使其具有容错能力.此外,我希望它能够非常快速地工作并且非常敏感.

下面是这种应用程序的一个非常简单的架构视图.

比萨饼送货店订单系统

问题是我不知道如何使用所有Erlang/OTP优点来使应用程序具有响应性和容错性.

这是我的问题:

  1. 应该复制哪些系统元素以提供容错,我应该如何做?我知道我可以在复制的Mnesia数据库中存储每辆车的状态(坐标,分配的订单等).这是一个正确的方法吗?
  2. 哪些数据存储服务应该是传统的基于SQL的(例如基于boss_db),哪些应该在Mnesia上完成以提供非常快速的响应?是否可以使用传统的SQL数据库将客户记录和历史记录存储在这样的容错和响应速度快的应用程序中?
  3. 我是否应该尝试将所有服务(客户,车辆状态等)的所有数据存储在RAM中,以使应用程序具有高响应性?
  4. 我应该将持久性车辆数据(id,容量等)存储在传统的SQL数据库中,并将实时数据(坐标,分配的订单,主干中的订单等)存储在Mnesia数据库中,以使应用程序更多实时响应?

architecture erlang fault-tolerance real-time erlang-otp

7
推荐指数
1
解决办法
2533
查看次数

Erlang YAWS:如何测试简单的REST Web服务?

在一个简单的基于Erlang YAWS的RESTful应用程序中,我希望有一组测试将HTTP请求发送到RESTful API,从服务器获取响应,然后测试这些响应.

如果每个"send-request-get-request-test"测试都可以在EUnit中运行(可以使用测试生成器),那就太好了.

我也希望能够用rebar(make test)运行这组测试.

最近,我 ibrowse在另一个应用程序(受Mochiweb),但我发现它安静的使用麻烦.

是否还有其他选项可以编写可以将HTTP请求发送到YAWS RESTful应用程序的Erlang/OTP测试?最常见的方法是什么?

rest erlang yaws erlang-otp eunit

7
推荐指数
2
解决办法
2332
查看次数

CouchDB作为Erlang版本的一部分

我想构建和部署一个应用程序,其中Django作为前端,YAWS(appmods)或Mochiweb/Webmachine作为后端,CouchDB作为数据存储.此外,我计划广泛使用CouchDB的复制能力,以便为整个应用程序提供高容错能力.

我倾向于认为,为了实现这一点,我必须创建一个单独的OTP版本,它将YAWS和CouchDB作为Erlang/OTP应用程序.

这种方法似乎是正确的吗?如何在OTP应用程序方面组织YAWS和CouchDB以创建可靠的生产设置?这样做有什么最佳做法吗?

erlang couchdb release erlang-otp mochiweb

7
推荐指数
1
解决办法
528
查看次数