【问题标题】:deploy compojure app that is also a CLI app部署同样是 CLI 应用程序的 compojure 应用程序
【发布时间】:2015-09-02 21:42:37
【问题描述】:

我有一个 Clojure 应用程序,既可以从命令行使用,也可以作为 Compojure 应用程序使用。 我通过在我的 leiningen project.clj 中放置一个环处理程序和一个主函数 (clojure.tools.cli) 来做到这一点。

{... :main my-app.core :ring {:handler my-app.handler/handler }}

handler 定义为 (defroutes handler ...)

现在,如果我想运行 CLI 应用程序,我可以运行 lein uberjar,然后运行 ​​java -jar arguments。 我还可以通过lein ring server PORT 运行 Compojure 应用程序。

现在,如何在生产服务器中将其部署为 Compojure 应用程序(而不是 CLI 应用程序)? (解释lein ring server 工作原理的奖励积分。)

注意:如果有帮助,我已经在使用 nginx,而且我对要使用的容器很灵活。

【问题讨论】:

  • github.com/boot-clj/boot 可以解决吗?还不确定它是做什么的......
  • 您在部署的哪个部分遇到问题,只是 lein/project.clj 语法? “作为一个复合应用程序”是什么意思? Compojure 只是一个路由库,所以即使你作为 CLI 运行,它仍然是 compojure,对吧? (我个人不喜欢 dev 或 prod 中的 lein ring server,因为它使依赖注入和 REPL 开发变得困难)。
  • @DaxFohl by CLI 我的意思是作为一个 jar,然后它转到使用 tools.cli 的 -main 入口点。 REST API 使用 CLI 应用程序用来做事的相同代码,我使用 lein ring server 8888 运行它,但它是相同的代码。我希望能够部署 jar 并在端口 8888 上运行它。

标签: clojure compojure


【解决方案1】:

这是我用于新项目的默认模板。它允许您对环形应用程序进行依赖注入,并从命令行将应用程序作为 uberjar 运行。你可以在这里阅读更多:http://www.sparxeng.com/blog/software/improved-clojure-workflow

; handler.clj    
(defn wrap-inject-deps
  "Ring middleware that injects the dependencies into each ring request map"
  [handler deps]
  (fn [req]
    (handler (assoc req :deps deps))))

(defn create-handler
  "Similar to the default ring 'handler', but with a parameter to let you inject dependencies"
  [deps]
  (-> (routes
        api-routes
        web-routes
        (route/resources "/"))
      (kwp/wrap-keyword-params)
      (params/wrap-params)
      (json/wrap-json-params)
      (json/wrap-json-response)
      (wrap-inject-deps deps))) ; this injects dependencies

(defn start-jetty
  "Launch the Jetty instance"
  [deps]
  (let [port (Integer. (or (-> system :env :port) 5000))
        handler (create-handler deps)]
    (jetty/run-jetty handler {:port port :join? false})))


; system.clj
(defn get-env
  "Initialize configuration vars"
  []
  {:aws-access-key-id     (System/getenv "AWS_ACCESS_KEY_ID")
   :aws-secret-access-key (System/getenv "AWS_SECRET_ACCESS_KEY")
   :mongo-url             (System/getenv "MONGO_URL"))

(defn start
  "Launch dependencies such as DB connection and Jetty. Return these as a map, for use in REPL"
  [& [env]]
  (let [env (or env (get-env))
        deps {:env     env
              :monger  (db/init env)}
        jetty (handler/start-jetty deps)]
    (assoc deps :jetty jetty)))


; program.clj
(defn -main [& [port]]
  "App entrypoint"
  (let [env (system/get-env) ; "env" is just a map of config variables, that can be hard-coded, read from file, or whatever you want.
        env (if port (assoc env :port port) env)]
    (system/start env)))

如果您需要从您的代码库创建多个具有不同入口点的应用程序,则可以使用 leiningen 配置文件。

【讨论】:

  • 好吧,我不确定我是否可以使用它,因为我的 CLI 应用程序使用了我的 -main 函数(解析输入参数......)并且不会启动网络服务器。
  • @nha 使用 leiningen 配置文件指定不同的入口点。
【解决方案2】:

lein ring server 启动 jetty 以服务于您构建的 Web 应用程序。它通过使用您在:ring 中指定的选项启动服务器来完成此操作。如果您在环境中指定LEIN_NO_DEV,服务器将以生产模式运行。码头是否适合您的制作需求,由您决定。

如果您想在不同的服务器上运行您的 Web 应用程序,有多种选择。其中之一在 Tomcat 上运行。再看一下lein ring 的文档,特别是关于战争文件的部分。基本上,您会调用lein warlein uberwar 来生成war 文件。然后你可以例如将war文件放到Tomcat的webapps目录下。

另一种选择是使用immutant,它有大量关于安装和运行应用程序的文档。

【讨论】:

  • 谢谢,有帮助。现在,如果我使用lein ring server 8888 启动我的服务器,我该如何让 tomcat/jetty 在端口 888 上为我的 compojure 应用程序提供服务?
  • 好吧,对于 Jetty via lein ring,你已经有了答案。对于 Tomcat,这更多是关于配置 Tomcat 的问题,所以我建议您提出一个新问题。但它基本上需要你在Tomcat的server.xml配置文件中设置port变量。
  • 顺便说一句,如果这是您正在寻找的信息,请随时投票/接受答案:-)
  • @nha 你在问什么,更具体地说?如果您希望码头在 888 端口上运行,那么您显然可以使用lein ring server 888。但是您的一系列问题似乎暗示您希望能够键入lein ring server 8888,然后让它在端口 888 上运行?嗯?
  • @DaxFohl 抱歉,这是此特定评论中的错字。我的意思是我希望码头在端口8888 上为我的应用程序提供服务。知道在我的配置/代码中我没有指定端口,只有在使用lein 时我才指定端口。但我的意思是没有 lein,在生产服务器上(而不是开发服务器。
猜你喜欢
  • 2010-11-07
  • 2018-06-12
  • 1970-01-01
  • 2019-06-12
  • 2014-10-11
  • 2017-11-16
  • 2016-09-11
  • 2021-06-21
  • 2019-03-08
相关资源
最近更新 更多