v店添加商品doto单人 flow内部服务错误提示

当前访客身份:游客 [
ZeroMQ 替换 HTTP 作为内部服务
英文原文:
Performing requests
Here's how I perform a request to list all the users in my system:
(defn do-rpc
([sock method path] (do-rpc sock method path nil))
([sock method path body]
(let [msg (cheshire.core/generate-smile
{:method method :path path :body body})]
(.send sock msg 0)
(let [res (.recv sock 0)]
(cheshire.core/parse-smile res true)))))
(with-req-sock connection
(fn [sock]
(println (do-rpc sock &GET& &/users&)))) This sends a request with a &json& map that contains the keys method, path and body. If we do this now, we'll just get a weird response back since our server still just echoes the requsest. So let's get our hands dirty and implement an actual RPC request handler!
下面是我如何执行一个请求来列出我系统中所有的用户的:
(defn do-rpc
([sock method path] (do-rpc sock method path nil))
([sock method path body]
(let [msg (cheshire.core/generate-smile
{:method method :path path :body body})]
(.send sock msg 0)
(let [res (.recv sock 0)]
(cheshire.core/parse-smile res true)))))
(with-req-sock connection
(fn [sock]
(println (do-rpc sock &GET& &/users&)))) 这个以“json”地图形式(包含:键、方法、路径和数据体)发送了一个请求。如果我们现在这样做了,我们就只会得到一个奇怪的返回,因为我们的服务器还只是对请求作简单的默认回应。所以让我们动动手来实施一个实际的RPC请求处理程序吧!
Responding to requests
Since we're very HTTP like, implementing a rudimentary request handler only takes a few small steps.
We're going to re-implement themy-response-handlerfrom above into something that reads in the SMILE encoded requests and responds with SMILE encoded responses.
(defn respond
(if (and (= (get req :method) &GET&) (= (get req :path) &/users&))
{:status 200 :body [{:id 1 :name &August&}]}))
;; This function used to echo. We now parse and generate SMILE.
(defn my-response-handler
(let [req (cheshire.core/parse-smile raw-req true)]
(if-let [response (respond req)]
(cheshire.core/generate-smile response)
(cheshire.core/generate-smile {:status 404})))
(catch Exception e
(cheshire.core/generate-smile {:status 500})))) If respond returns non-nil, assume it's a valid response and SMILE encode it. If respond returns nil, return status 404. Just like HTTP, because why not! If any of this throws an exception, we'll respond with status 500. Again, just like HTTP.
While this is slightly more interesting than an echo server, we don't want to manually do RPC routing with if tests. We want to utilize some kind of library to be able to set up different request handlers with as little repetition as possible.
Take a deep breath. Sit down. Are you comfortable? This is going to be awesome.
由于我们非常类似于HTTP,所以只简单的几步就实现基本的请求处理器了。
我们将把上面的响应处理器实现为读取以SMILE编码的请求而且用以SMILE编码的响应应答的东西。
(defn respond
(if (and (= (get req :method) &GET&) (= (get req :path) &/users&))
{:status 200 :body [{:id 1 :name &August&}]}))
;; 这个函数常常用来回显的。现在我们解析并生成SMILE。
(defn my-response-handler
(let [req (cheshire.core/parse-smile raw-req true)]
(if-let [response (respond req)]
(cheshire.core/generate-smile response)
(cheshire.core/generate-smile {:status 404})))
(catch Exception e
(cheshire.core/generate-smile {:status 500}))))
如果响应返回非空,那么就显示它是一个有效地响应并且使用SMILE编码这个响应。如果响应返回的是空,那么返回状态404。就像HTTP那样,因为为什么不那样呢!如果其中任何一个抛出例外,那么我们将响应状态500。再说明一下,就如同HTTP那样。
虽然这个比回显服务器稍稍让人感兴趣一点,但是如果测试的话,我们就不想手工进行RPC路由。我们想应用某种库来建立各自不同且尽可能少的重复请求处理器。
深呼吸。请坐下来。你感觉到舒畅吗?这是多么精彩啊。
Using existing HTTP routing libraries
Our requests are very HTTP-like, with a method and a path, which is really all we need in order to do traditional HTTP routing on, well, method and path.
So let's just use an existing HTTP routing library for that!
We'll be using Compojure, which handles Ring request. Ring is the most commonly used HTTP stack for Clojure. Ring has a very simple API. You give Ring a function. This function takes one argument, the request, represented as an immutable map. This function should return a map, representing the response. That's it!
The only thing we need to do, is to turn our ZeroMQ based map into something that Compojure understands. On Ring, it's called:request-methodinstead of just:method, for example.
(defroutes app
(GET &/users& []
{:status 200 :body [{:id 1 :name &August&}]})
(GET &/users/:user-id& [user-id]
(if (= 1 user-id)
{:status 200 :body {:id 1 :name &August&}})))
(defn respond
(app {:request-method (keyword (.toLowerCase (get req :method)))
:uri (get req :path)
:body (get req :body)})) Words cannot describe how awesome this is.With just a couple of lines of code, we're invoking a HTTP stack from something that isn't HTTP at all.
其它翻译版本:1(点击译者名切换)
使用已有的HTTP路由库
我们的请求非常类似于HTTP,有方法和路径,这就是我们为了通过方法和路径来路由传统的HTTP而确实需要的东西。
因此,为了实现这个目的,我们只使用已有的HTTP 路由库!
我们将使用处理Ring请求的Compojure(译者注:Clojure的MVC框架)。Ring是Clojure中最常用的HTTP栈。Ring有非常简单的API。你在Ring上编写一个函数。这个函数把一个参数,请求,应答当作不可更改的map。这个函数应当返回一个表示应答的map。就这些。
我们需要做的唯一的事情就是转换基于map的ZeroMQ为Compojure可以理解的东西。在Ring上,它被称为:request-method而不仅仅是:method,例如:
(defroutes app
(GET &/users& []
{:status 200 :body [{:id 1 :name &August&}]})
(GET &/users/:user-id& [user-id]
(if (= 1 user-id)
{:status 200 :body {:id 1 :name &August&}})))
(defn respond
(app {:request-method (keyword (.toLowerCase (get req :method)))
:uri (get req :path)
:body (get req :body)})) 语言无法表达这是多么的精彩。仅仅只需几行代码,我们就从根本不是HTTP的东西里调用了HTTP栈。
We're done!
Wow, you made it this far! Or perhaps you just skimmed and got to this part. I'm proud of you either way.
We now have a solid way of doing RPC calls over just one TCP connection, with no manual connection management, and with queuing of requests if the server is down. We have a sane way of implementing our server to respond to different procedures. This is all we really wanted, so let's celebrate and perform remote procedure calls without having to deal with boring details such as connection management.
And I think this post demonstrates the powers of one datastructure and a hundred functions. Just by creating a data structure that looks identical to the ones the Ring stack create, we can re-use an entire suite of HTTP tools already available to us.
Good luck!
我们已经实现了!
哇,到现在为止你已经实现了RPC了!或者也许你只是大概浏览一下就直接到达这一部分。无论哪种方式,我都为你而骄傲。
现在我们拥有了一个仅在一个TCP连接上进行多个RPC调用的可靠的方法,并且不需要手工管理连接,而且在服务器关闭的情况下可以对请求排队。我们用一种完善的方式实现了响应各种过程的服务器。这就是我们真正需要的,因此让我们庆祝一下,然后在不需要处理哪些诸如连接管理等令人讨厌的细节的情况下执行远程过程调用。
还有,我认为这篇文章显示了一个数据结构和一百个函数的强大。只是通过创建一个看起来和Ring栈创建的相同的数据结构,我们就能重用已经对我们来说可用的整套HTTP工具。
祝你幸运!
Multiple servers
I've never actually done this myself, so I won't show you the code for it. I'll leave the implementation details as an exercise for the reader. The concepts are clear, though. Since we've seen that it's really easy to compose REQ/REP and DEALER/ROUTER, all it should take is another node that sits between the REQ clients and the REP servers and routes and deals requests to multiple servers. Alternatively, just bind the DEALER we already have on the server and connect a bunch of REP sockets directly to it. But be aware, that would result in one TCP connection per REP socket.
事实上我自己没有这样做过,所以我不会给你展示它的代码。我会把实现细节作为练习留给读者们。毕竟,概念很清楚。既然我们已经看到组装REQ/REP 和DEALER/ROUTER是很容易的,所有需要处理的只是介于REQ客户端和REP服务器之间的一个节点和路由,以及处理对多服务器的请求。或者,只需要把我们已经有的DEALER 绑定到服务器上,然后开一堆REP socket直接连接到它上面。但要注意,那会导致为每一个REP socket打开一个TCP连接。
Authentication
I've only used ZeroMQ for internal services that are behind firewalls, so I haven't needed to add any form of auth. My advice for authentication would be to mimic HTTP. I would allow full access to the service itself, but in the routing, have a precondition that checks if an auth token of some sort is present in the request. If the request fails to authenticate, respond with status 403 or something along those lines.
Work is underway in ZeroMQ 3 for providing encrypted transports, too, so you don't have to manually encrypt your messages to be MITM safe if you're dispatching messages across a network you don't trust.
我只是使用ZeroMQ来作为位于防火墙之后的内部服务,所以我并不需要添加任何形式的认证。 我对于认证的建议将是:模仿HTTP。我将会完全允许对服务本身的访问,但是在路由上设置一个前提条件,来检查是否在请求中提供了某种类型的认证令牌。如果请求没有通过认证,就响应一个403状态码或者相关的信息。
在 ZeroMQ 3中提供加密传输的工作也正在进行中,所以如果你在通过一个你不信任的网络传播消息,你不必手动加密你的消息来满足MITM安全性。
Some notes on the Clojure code
I have this crazy idea that I should make the code as readable as possible to people that are unfamiliar with Clojure in general. So I do some non-ideomatic stuff. All I probably achieved with this was to alienate the people that actually read the article - Clojure programmers. Oh well.
We're doing a lot of Java interop, and in my code I like to use the(doto)macro. Instead of this:
(let [ctx (ZMQ/context 1)
router-socket (.socket ctx ZMQ/ROUTER)
dealer-socket (.socket ctx ZMQ/DEALER)]
(.bind router-socket &tcp://127.0.0.1:1337&)
(.bind dealer-socket &inproc://responders&)
) We could have written this:
(let [ctx (ZMQ/context 1)
router-socket (doto (.socket ctx ZMQ/ROUTER) (.bind &tcp://127.0.0.1:1337&))
dealer-socket (doto (.socket ctx ZMQ/DEALER) (.bind &inproc://responders&))]
) Which means we could have created a whole lot less names in that code, and created our ROUTER/DEALER pair and the queue like so:
(let [ctx (ZMQ/context 1)
queue (ZMQQueue.
(doto (.socket ctx ZMQ/ROUTER) (.bind &tcp://127.0.0.1:1337&))
(doto (.socket ctx ZMQ/DEALER) (.bind &inproc://responders&)))]
(.start (Thread. (fn [] (.run queue))))) Or even fewer names, and inlined the entire thing.
(let [ctx (ZMQ/context 1)]
(ZMQQueue.
(doto (.socket ctx ZMQ/ROUTER) (.bind &tcp://127.0.0.1:1337&))
(doto (.socket ctx ZMQ/DEALER) (.bind &inproc://responders&)))
(.run))))))
Clojure代码的一些说明
我有这样一个疯狂的想法:我应当让那些一般不熟悉Clojure的人们尽可能的读懂代码。因此我做了一些非习惯性东西。我可能获得这个想法的所有就是疏远那些真正读懂这篇文章的人-Clojure开发人员。喔,就这样。
我们在做许多Java混合的操作。在我代码里,我喜欢使用doto宏,而不是如下:
let [ctx (ZMQ/context 1)
router-socket (.socket ctx ZMQ/ROUTER)
dealer-socket (.socket ctx ZMQ/DEALER)]
(.bind router-socket &tcp://127.0.0.1:1337&)
(.bind dealer-socket &inproc://responders&)
) 我们应当书写成下面:
(let [ctx (ZMQ/context 1)
router-socket (doto (.socket ctx ZMQ/ROUTER) (.bind &tcp://127.0.0.1:1337&))
dealer-socket (doto (.socket ctx ZMQ/DEALER) (.bind &inproc://responders&))]
) 这意味着我们在这段代码里有很少的名字,而且还创建了ROUTER/DEALER对和队列,如下:
(let [ctx (ZMQ/context 1)
queue (ZMQQueue.
(doto (.socket ctx ZMQ/ROUTER) (.bind &tcp://127.0.0.1:1337&))
(doto (.socket ctx ZMQ/DEALER) (.bind &inproc://responders&)))]
(.start (Thread. (fn [] (.run queue))))) 或者有更少的名字,且内联化整个代码:
(let [ctx (ZMQ/context 1)]
(ZMQQueue.
(doto (.socket ctx ZMQ/ROUTER) (.bind &tcp://127.0.0.1:1337&))
(doto (.socket ctx ZMQ/DEALER) (.bind &inproc://responders&)))
(.run))))))
dototakes a Java object as the first argument, and all the other following arguments are assumed to be lists (in Clojure, a list is a function call) and inserts this instance as the 2nd element in the list, i.e. the first argument to the function. So while the code looks like we call bind on a string, it's actually called on the instance pased to the first argument - the socket instances created by the call to socket on the ctx. This is convenient for creating an instance of something, calling a bunch of methods with side effects on it, and return that instance, without having to create a named variable for the instance.
I've also chosen to use(getmy-map:a-key)instead of the more idiomatic(:a-keymy-map). It might be confusing for people unfamiliar with Clojure that keywords are also callable polymorphic functions, that does map lookups if the first argument is a map.
doto 把Java对象当作第一个参数,其他紧跟着的所有参数都被当作列表(在Clojure里,列表就是函数调用),接着把实例插入做为列表的第二个元素,也就是函数的第一个参数。因此虽然这段代码看起来像我们对一个字符串调用了bind ,实际上我们调用的是传递给第一个参数的实例-对ctx调用套接字所生成的套接字实例。这便于创建某对象的实例,调用实例的许多可以产生其他结果的方法,然后在不需要为这个实例创建命名变量的情况下返回实例。
我还选择使用(get my-map:a-key)而不是更符合语言习惯的(:a-key my-map) 。这使不熟悉Clojure的人迷惑:关键字还是可以调用的多态函数,如果第一个参数是map,那么这将执行map查找。一个男人同时和三个女人在同一张床上吮奶,并且做爱,xingjiaoshiin
友情链接:您所在位置: &
&nbsp&&nbsp&nbsp&&nbsp
基于医疗行业的服务情感价值研究.pdf262页
本文档一共被下载:
次 ,您可免费全文在线阅读后下载本文档
文档加载中...广告还剩秒
需要金币:300 &&
你可能关注的文档:
··········
··········
中图分类号:
学校代码:
博士学位论文
基于医疗行业的服务情感价值研究
ServiceEmotionalValue BasedonHealthcare
南开大学研究生院
二O一一年五月
南开大学学位论文原创性声明
本人郑重声明:所呈交的学位论文,是本人在导师指导下进行研究工作所取
得的研究成果。除文中已经注明引用的内容外,本学位论文的研究成果不包含任
何他人创作的、已公开发表或者没有公开发表的作品的内容。对本论文所涉及的
研究工作做出贡献的其他个人和集体,均己在文中以明确方式标明。本学位论文
原创性声明的法律责任由本人承担。
学位论文作者签名:
非公开学位论文标注说明
根据南开大学有关规定,非公开学位论文须经指导教师同意、作者本人申请
和相关部门批准方能标注。未经批准的均为公开学位论文,公开学位论文本说明
基于医疗行业的服务情感价值研究
口限制 ≤2年
口秘密 ≤10年
口机密 ≤20年
审批表编号
限制★2年 最长2年,可少于2年
秘密★10年 最长5年,可少于5年
机密★20年 最长10年,可少
正在加载中,请稍后...最好的洗衣机品牌,熟妇阴X?比较大
友情链接:插的呻,乱伦.淫液小姨
友情链接:

我要回帖

更多关于 rat doto best doto 的文章

 

随机推荐