国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

在 Docker 上運行一個 RESTful 風格的微服務

NotFound / 2405人閱讀

摘要:在這里,這個提供了一個風格的接口訪問。準備剛剛我們已經成功地在中運行了我們的微服務。對外暴露的端口需要跟服務的端口是一致的。運行是發布一個容器的端口到運行的主機上。

tags: Microservice Restful Docker

Author: Andy Ai
Weibo: NinetyH
GitHub: https://github.com/aiyanbo/do...


實現構思

使用 Maven 進行項目構建

使用 Jersey 實現一個 RESTful 風格的微服務

在 Docker 里面執行 mvn package 對項目打包

在 Docker 容器里運行這個微服務

實現一個 RESTful 風格的微服務

如果你對 RESTful 風格的 API 設計有疑惑,可以參考我的文章 RESTful Best Practices。

場景 & 需求

在 Maven 倉庫里面有許多的組件,我們現在暫且稱之為 Stack。在我們模擬的系統里面有下面2個需求:

列出倉庫里的所有 Stack

根據 StackID 找到某一個組件,如果沒有找到則返回 Not Found

現在,我們就根據這個需求一起踏入 Jersey 打造微服務的奇幻之旅。

Step0. 準備

使用 mvn 命令創建一個簡單工程

mvn archetype:generate -DgroupId=org.jmotor -DartifactId=docker-restful-demo -DinteractiveMode=false

pom.xml 加入 Jersey 等依賴


    UTF-8
    UTF-8
    4.12
    2.18
    3.1.0


    
        junit
        junit
        ${junit.version}
        test
    
    
        org.glassfish.jersey.containers
        jersey-container-grizzly2-http
        ${jersey.version}
    
    
        org.glassfish.jersey.media
        jersey-media-json-jackson
        ${jersey.version}
    
Step1. 構建 Model

Stack 包含了以下幾個屬性: id, groupId, artifactId, version。同時,Stack 類里面包含了一個 Builder 用來比較方便地創建一個 Stack 對象。這些都可以使用 IDE 自動生成,無需手動編寫。

package org.jmotor.model;

/**
 * Component:
 * Description:
 * Date: 2015/6/18
 *
 * @author Andy Ai
 */
public class Stack {
    private Integer id;
    private String groupId;
    private String artifactId;
    private String version;

    ...getter and setter...

    public static class Builder {
        private Integer id;
        private String groupId;
        private String artifactId;
        private String version;

        public Builder id(Integer id) {
            this.id = id;
            return this;
        }

        ...

        public Stack build() {
            Stack stack = new Stack();
            stack.setId(id);
            ...
            return stack;
        }

        public static Builder newBuilder() {
            return new Builder();
        }
    }
}
Step2 創建一個 Restlet

剛剛我們已經把 Model 做好了,現在我們就開始使用 Jersey 實現一個 Service,在 JAX-RS 中這樣的一個服務稱為 Resource。在這里,這個 Service(Resource) 提供了一個 RESTful 風格的接口訪問。所以我們稱之為 restlet。restlet 在 JAX-RS 或 Jersey 中并沒有這個概念,這是我們附加上去的用法。

import javax.ws.rs.Path;

@Path("/v1/stacks")
public class StacksRestlet {}

我們需要使用 javax.ws.rs.Path 這個注解來申明 Restlet 的根路徑是什么。在上面的代碼中, Restlet 的跟路徑是 /v1/stacks

Step3. 實現服務接口

在 Jersey 里實現一個服務接口非常簡單,你只需要創建一個 public 的方法就可以了。

接口1:

@GET
@Produces("application/json")
public List stacks() {
    return Arrays.asList(
            Stack.Builder.newBuilder().id(1).groupId("javax.servlet").artifactId("javax.servlet-api").version("3.1.0").build(),
            Stack.Builder.newBuilder().id(2).groupId("com.google.guava").artifactId("guava").version("18.0").build()
    );
}

我們使用 javax.ws.rs.GET 這個注解來申明接口接受的是 HTTP 請求的 GET 方法。javax.ws.rs.Produces("application/json") 用來表示我們這個接口返回的是 application/json 類型的數據。

接口2:

@GET
@Path("{id}")
@Produces("application/json")
public Stack filterByArtifactId(@NotNull @PathParam("id") Integer id) {
    switch (id) {
        case 1:
            return Stack.Builder.newBuilder().id(1).groupId("javax.servlet").artifactId("javax.servlet-api").version("3.1.0").build();
        case 2:
            return Stack.Builder.newBuilder().id(2).groupId("com.google.guava").artifactId("guava").version("18.0").build();
        default:
            throw new WebApplicationException("Stack not found, id: " + id, 404);
    }
}

在上面的示例中:

@Path("{id}") 表示 id 是一個 url 上的動態參數,因為 id 是變化的,所以我們要做成一個 url 變量。然后在方法里面使用 @PathParam("id") 來獲得這個參數。JAX-RS 可以有許多類型的參數,例如:QueryParam 用來獲取 url 問號? 后面的查詢參數。你可以在 javax.ws.rs 這個包中找到其他的參數!

使用 WebApplicationException 拋一個任何狀態的異常,例如: 404 或 500。

Step4. 運行微服務

這里,我們使用 Jersey 的內置的 Grizzly 容器運行。

final URI uri = UriBuilder.fromUri("http://localhost/").port(9998).build();
final ResourceConfig config = new ResourceConfig();
config.packages("org.jmotor.restlet");
final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(uri, config);
Runtime.getRuntime().addShutdownHook(new Thread() {
    @Override
    public void run() {
        server.shutdown();
    }
});
try {
    server.start();
} catch (IOException e) {
    e.printStackTrace();
    System.exit(1);
}
Step5. 測試

獲取 Stacks 列表

$ curl http://localhost:9998/v1/stacks
[{"id":1,"groupId":"javax.servlet","artifactId":"javax.servlet-api","version":"3.1.0"},{"id":2,"groupId":"com.google.gua
va","artifactId":"guava","version":"18.0"}]

根據 ID 獲取 Stack

$ curl http://localhost:9998/v1/stacks/1
{"id":1,"groupId":"javax.servlet","artifactId":"javax.servlet-api","version":"3.1.0"}

找不到的 Stack

$ curl -I http://localhost:9998/v1/stacks/5
HTTP/1.1 404 Not Found
Content-Length: 0
Date: Tue, 23 Jun 2015 06:04:19 GMT
在 Docker 中運行

首先,我們需要安裝一個 Docker 環境,你可以從 Docker Docs 上找到如何安裝它。

安裝完成后,我們需要把我們的微服務打包成一個 Docker Image。下面,我們就使用 Dockerfile 來構建我們的 Docker Image。

Step0. 準備

剛剛我們已經成功地在 IDE 中運行了我們的微服務。但是如果需要讓它能獨立運行,我們需要把我們的工程通過 mvn 做成一個可以運行的包。但是因為我們在 Docker 中運行,所以我們只需要把相關的依賴復制到一個特地的地方就可以了。在下面的代碼中,我們把依賴放到了 ${project.build.directory}/lib 下。

pom.xml 加入下面的代碼:


    
        
            org.apache.maven.plugins
            maven-dependency-plugin
            
                
                    copy-dependencies
                    package
                    
                        copy-dependencies
                    
                    
                        provided
                        ${project.build.directory}/lib
                    
                
            
        
        
            org.apache.maven.plugins
            maven-compiler-plugin
            
                1.7
                1.7
            
        
    
Step1. Dockerfile
FROM jamesdbloom/docker-java8-maven

MAINTAINER Andy Ai "yanbo.ai@gmail.com"

WORKDIR /code

ADD pom.xml /code/pom.xml
ADD src /code/src
ADD settings.xml /root/.m2/settings.xml

RUN ["mvn", "package"]

CMD ["java", "-cp", "target/lib/*:target/docker-restful-demo-1.0-SNAPSHOT.jar", "org.jmotor.StackMicroServices"]

EXPOSE 9998

Tips

ADD settings.xml /root/.m2/settings.xml,這是加入了本地的 maven settings。在這個文件里面你可能會使用到一些特定的配置,例如:maven 倉庫的代理鏡像。代理鏡像可以加快你的 Docker Build。

EXPOSE 9998 Docker 對外暴露的端口需要跟服務的端口是一致的。

Step2. Build Image
cd docker-restful-demo
docker build -t docker-restful-demo .

上面代碼中,-t 是在 Docker Build 的時候指定 Image Tag。

Step3. 運行 Image
docker run -d -p 9998:9998 docker-restful-demo

Tips
-p 是發布一個 Docker 容器的端口到 Docker 運行的主機上。

Step4. Docker 容器測試

檢查 Docker 容器是否在運行

$ docker ps
CONTAINER ID        IMAGE                       COMMAND                CREATED             STATUS              PORTS
                NAMES
bdda2408484a        docker-restful-demo:latest   "java -cp target/lib   31 seconds ago      Up 29 seconds       0.0.0.0:9
998->9998/tcp   fervent_swartz

檢查 Docker 容器內的服務是否已經啟動:

登錄到 Docker 容器:

docker exec -i -t bdda2408484a bash

查看服務端口信息

$ ss -a
Netid  State      Recv-Q Send-Q                       Local Address:Port                           Peer Address:Port
nl     UNCONN     0      0                                     rtnl:kernel                                     *
nl     UNCONN     4352   0                                  tcpdiag:ss/92                                      *
nl     UNCONN     768    0                                  tcpdiag:kernel                                     *
nl     UNCONN     0      0                                        6:kernel                                     *
nl     UNCONN     0      0                                       10:kernel                                     *
nl     UNCONN     0      0                                       12:kernel                                     *
nl     UNCONN     0      0                                       15:kernel                                     *
nl     UNCONN     0      0                                       16:kernel                                     *
u_str  ESTAB      0      0                                        * 9590                                      * 0
tcp    LISTEN     0      128                       ::ffff:127.0.0.1:9998                                     :::*

測試接口

$ curl -i http://localhost:9998/v1/stacks
HTTP/1.1 200 OK
Content-Type: application/json
Date: Tue, 23 Jun 2015 07:51:15 GMT
Content-Length: 163

[{"id":1,"groupId":"javax.servlet","artifactId":"javax.servlet-api","version":"3.1.0"},{"id":2,"groupId":"com.google.gua
va","artifactId":"guava","version":"18.0"}]

退出 Docker 容器

exit
Step5. 遠程調用測試

如果你使用的是 boot2docker, 需要拿到 boot2docker 虛擬機的IP

$ boot2docker ip
192.168.59.103

調用遠程接口

$ curl http://192.168.59.103:9998/v1/stacks
curl: (7) Failed to connect to 192.168.59.103 port 9998: Connection refused

如果遇到上面的錯誤,我們可以通過2種方式去解決它:
方法1: 將程序綁定全零IP的端口

檢查 Docker 容器綁定的端口:

$ docker port bdda2408484a
9998/tcp -> 0.0.0.0:9998

我們看到的是 9998 這個端口綁定在 0.0.0.0 上,這時需要把 Jersey 容器的 URI 改成 0.0.0.0 就可以,像這樣:

final URI uri = UriBuilder.fromUri("http://localhost/").port(9998).build();

--->

final URI uri = UriBuilder.fromUri("http://0.0.0.0/").port(9998).build();

方法2: 將程序綁定到非回路的IP端口上

查看 Docker 容器 IP 地址的方法:

boot2docker ssh

docker inspect --format "{{.NetworkSettings.IPAddress}}" $container_id

使用 Java 接口獲取本機的非回路IP地址:

final URI uri = UriBuilder.fromUri("http://localhost/").port(9998).build();

--->

InetAddress inetAddress = localInet4Address();
String host = "0.0.0.0";
if (inetAddress != null) {
    host = inetAddress.getHostAddress();
}
final URI uri = UriBuilder.fromUri("http://" + host + "/").port(9998).build();
        
private static InetAddress localInet4Address() throws SocketException {
    Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces();
    while (networkInterfaces.hasMoreElements()) {
        NetworkInterface networkInterface = networkInterfaces.nextElement();
        Enumeration inetAddresses = networkInterface.getInetAddresses();
        while (inetAddresses.hasMoreElements()) {
            InetAddress inetAddress = inetAddresses.nextElement();
            if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
                return inetAddress;
            }
        }
    }
    return null;
}

使用上面的任何一種方法,服務都能正常調用:

$ curl -i http://192.168.59.103:9998/v1/stacks
HTTP/1.1 200 OK
Content-Type: application/json
Date: Tue, 23 Jun 2015 07:53:24 GMT
Content-Length: 163

[{"id":1,"groupId":"javax.servlet","artifactId":"javax.servlet-api","version":"3.1.0"},{"id":2,"groupId":"com.google.gua
va","artifactId":"guava","version":"18.0"}]
加速器

在撰寫此文的時候,我使用的是 DaoColud 的鏡像在做加速。 具體步驟請查看 DaoColud Mirror 文檔。

如果你在 Windows 上使用 Boot2Docker, 可以按照下列步驟設置你的 Docker 鏡像倉庫:

boot2docker ssh

sudo su
echo "EXTRA_ARGS="--registry-mirror=http://98bc3dca.m.daocloud.io"" >> /var/lib/boot2docker/profile
exit

boot2docker restart

參考資料

https://dashboard.daocloud.io...
http://martinfowler.com/artic...
https://jersey.java.net/docum...
https://blog.giantswarm.io/ge...

未經同意不可轉載, 轉載需保留原文鏈接與作者署名。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/26422.html

相關文章

  • 運行 Docker 的微服務 - 服務發現與注冊

    摘要:運行在上的微服務服務發現與注冊在上一節中,我們學習了如何在上構建一個風格的微服務。接下來,我們將學習如何把運行在上的微服務暴露在服務中心上,以便客戶端的調用。資源服務在關閉時需要將服務實例在服務中心進行注銷操作。響應用戶的終止。 運行在 Docker 上的微服務 - 服務發現與注冊 tags: Docker Microservice RESTful etcd Author: And...

    陳偉 評論0 收藏0
  • 服務指南走北(四):你不愿意做微服務架構的十個理由

    摘要:微服務架構模式使得每個微服務獨立部署,且每個服務獨立擴展,開發者不再需要協調其它服務部署對本服務的影響。微服務架構模式使得持續化部署成為可能。所以使用微服務不是必須的,而是在適當的實際,架構適應應用場景的一種改變。 近段時間離職,跟同事們講解我之前所做的微服務相關產品,對于同事們提出的問題,做了如下整理出來,加上自己的理解,分享出來跟大家一起探討下: 問題預覽 我為什么要換微服務?能...

    Seay 評論0 收藏0
  • SegmentFault 技術周刊 Vol.5 - Docker丨Build, Ship, Run,

    摘要:此刻的后手指依舊飛速地敲打鍵盤,絲毫沒有要停不下來意思。閱讀本期技術周刊,你不光能弄明白什么是,使用的意義何在,還將被傳授秘籍,以達的境界。周刊篩選的每篇內容,是作者的獨到見解,踩坑總結和經驗分享。 showImg(https://segmentfault.com/img/bVC5qJ?w=900&h=385); 啪嗒啪嗒,啪嗒啪嗒,聽到后排動感十足的清脆鍵盤響,我就能猜到公司程序員定...

    Panda 評論0 收藏0
  • 服務橫行的今天, 你的文檔跟節奏了么?

    摘要:納尼隔壁少林派表示自家金剛技壓群雄在座各位都是。。。納尼你覺得寫太繁瑣了你不喜歡我們還有或者等等一大堆工具呢。納尼沒有你還是覺得無法接受好吧那么筆者推薦類似這類更友好的工具你可以導入導出其他格式也可以使用其來撰寫。 說起微服務, 想必現在的技術圈內人士個個都能談笑風云, 娓娓道來。的確, 技術變革日新月異, 各種工具框架雨后春筍般涌現, 現在我們可以輕巧便捷地根據自己的業務需求, 構建...

    liaoyg8023 評論0 收藏0
  • 2021 年最新基于 Spring Cloud 的微服務架構分析

    摘要:是一個相對比較新的微服務框架,年才推出的版本雖然時間最短但是相比等框架提供的全套的分布式系統解決方案。提供線程池不同的服務走不同的線程池,實現了不同服務調用的隔離,避免了服務器雪崩的問題。通過互相注冊的方式來進行消息同步和保證高可用。 Spring Cloud 是一個相對比較新的微服務框架,...

    cikenerd 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<