基于docker部署的微服務(wù)架構(gòu)(二): 服務(wù)提供者和調(diào)用者

前言

前一篇 基于docker部署的微服務(wù)架構(gòu)(一):服務(wù)注冊(cè)中心 已經(jīng)成功創(chuàng)建了一個(gè)服務(wù)注冊(cè)中心冰评,現(xiàn)在我們創(chuàng)建一個(gè)簡(jiǎn)單的微服務(wù)映胁,讓這個(gè)服務(wù)在服務(wù)注冊(cè)中心注冊(cè)。然后再創(chuàng)建一個(gè)調(diào)用者甲雅,調(diào)用此前創(chuàng)建的微服務(wù)解孙。

創(chuàng)建微服務(wù)

新建一個(gè)maven工程,修改pom.xml引入 spring cloud 依賴:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.2.RELEASE</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Camden.SR2</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

resources 目錄中創(chuàng)建 application.yml 配置文件抛人,在配置文件內(nèi)容:

spring:
  application:
    name: @project.artifactId@

server:
  port: 8100

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8000/eureka/

這里eureka的注冊(cè)地址為上一篇中設(shè)置的defaultZone弛姜。
java 目錄中創(chuàng)建一個(gè)包 demo ,在包中創(chuàng)建啟動(dòng)入口 AddServiceApplication.java

@EnableDiscoveryClient
@SpringBootApplication
public class AddServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(AddServiceApplication.class, args);
    }
}

在demo包下新建一個(gè)子包c(diǎn)ontroller妖枚,在controller子包下創(chuàng)建一個(gè)controller對(duì)外提供接口廷臼。

@RestController
public class AddController {
    @RequestMapping(value = "/add", method = RequestMethod.GET)
    public Map<String, Object> add(Integer a, Integer b) {
        System.out.println("端口為8100的實(shí)例被調(diào)用");
        Map<String, Object> returnMap = new HashMap<>();
        returnMap.put("code", 200);
        returnMap.put("msg", "操作成功");
        returnMap.put("result", a + b);
        return returnMap;
    }
}

在服務(wù)注冊(cè)中心已經(jīng)運(yùn)行的情況下,運(yùn)行 AddServiceApplication.java 中的 main 方法绝页,啟動(dòng)微服務(wù)荠商。
訪問服務(wù)注冊(cè)中心頁面 http://localhost:8000, 可以看到已經(jīng)成功注冊(cè)了 ADD-SERVICE-DEMO 服務(wù)续誉。

服務(wù)注冊(cè)中心
服務(wù)注冊(cè)中心

啟動(dòng)第二個(gè)實(shí)例莱没,修改端口為 8101 酷鸦,修改 AddController.java 中的輸出信息為

System.out.println("端口為8101的實(shí)例被調(diào)用");

再次運(yùn)行 AddServiceApplication.java 中的 main 方法。
訪問服務(wù)注冊(cè)中心頁面 http://localhost:8000嘹裂, 可以看到已經(jīng)成功注冊(cè)了兩個(gè) ADD-SERVICE-DEMO 服務(wù)摔握,端口分別為 81008101

服務(wù)注冊(cè)中心2
服務(wù)注冊(cè)中心2

demo源碼 spring-cloud-1.0/add-service-demo

ribbon方式調(diào)用服務(wù)

新建一個(gè)maven工程泊愧,修改pom.xml引入 spring cloud 依賴:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.2.RELEASE</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-ribbon</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Camden.SR2</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

resources 目錄中創(chuàng)建 application.yml 配置文件,在配置文件內(nèi)容:

spring:
  application:
    name: @project.artifactId@

server:
  port: 8200

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8000/eureka/

java 目錄中創(chuàng)建一個(gè)包 demo 奢浑,在包中創(chuàng)建啟動(dòng)入口 RibbonClientApplication.java

@EnableDiscoveryClient
@SpringBootApplication
public class RibbonClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(RibbonClientApplication.class, args);
    }

    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

這里配置了一個(gè)可以從服務(wù)注冊(cè)中心讀取服務(wù)列表腋腮,并且實(shí)現(xiàn)了負(fù)載均衡的 restTemplate

在demo包下新建一個(gè)子包c(diǎn)ontroller徊哑,在controller子包下創(chuàng)建一個(gè)controller對(duì)外提供接口聪富。

@RestController
public class RibbonController {

    @Autowired
    RestTemplate restTemplate;

    @RequestMapping(value = "/add", method = RequestMethod.GET)
    public String add(Integer a, Integer b) {
        return restTemplate.getForEntity("http://ADD-SERVICE-DEMO/add?a="+a+"&b=" + b, String.class).getBody();
    }
    
}

可以看到這里的請(qǐng)求url用了服務(wù)注冊(cè)中心對(duì)應(yīng)的 Application

運(yùn)行 RibbonClientApplication.java 中的 main 方法梢莽,啟動(dòng)項(xiàng)目奸披。
在瀏覽器中訪問 http://localhost:8200/add?a=1&b=2 ,得到返回結(jié)果:

{
    msg: "操作成功",
    result: 3,
    code: 200
}

多次訪問阵面,查看 AddServiceApplication 的控制臺(tái),可以看到兩個(gè) ADD-SERVICE-DEMO 被負(fù)載均衡的調(diào)用仑扑。
demo源碼 spring-cloud-1.0/ribbon-client-demo

feign方式調(diào)用服務(wù)

新建一個(gè)maven工程置鼻,修改pom.xml引入 spring cloud 依賴:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.2.RELEASE</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-feign</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Camden.SR2</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

resources 目錄中創(chuàng)建 application.yml 配置文件沃疮,在配置文件內(nèi)容:

spring:
  application:
    name: @project.artifactId@

server:
  port: 8300

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8000/eureka/

java 目錄中創(chuàng)建一個(gè)包 demo 梅肤,在包中創(chuàng)建啟動(dòng)入口 FeignClientApplication.java

@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
public class FeignClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(FeignClientApplication.class, args);
    }

}

在demo包下新建一個(gè)子包service,在service子包下創(chuàng)建一個(gè)接口 AddService.java 調(diào)用之前創(chuàng)建的微服務(wù) ADD-SERVICE-DEMO俊啼。

@FeignClient("ADD-SERVICE-DEMO")
public interface AddService {
    @RequestMapping(method = RequestMethod.GET, value = "/add")
    String add(@RequestParam(value = "a") Integer a, @RequestParam(value = "b") Integer b);
}

這里 @FeignClient 注解中的參數(shù)為服務(wù)注冊(cè)中心對(duì)應(yīng)的 Application左医。

在demo包下再新建一個(gè)子包c(diǎn)ontroller同木,在controller子包下創(chuàng)建一個(gè) FeignController.java 對(duì)外提供接口跛十。

@RestController
public class FeignController {

    @Autowired
    private AddService addService;

    @RequestMapping(value = "/add", method = RequestMethod.GET)
    public String add(Integer a, Integer b) {
        return addService.add(a, b);
    }

}

FeignController 里注入了剛才創(chuàng)建的 AddService 接口。

運(yùn)行 FeignClientApplication.java 中的 main 方法洲尊,啟動(dòng)項(xiàng)目奈偏。
在瀏覽器中訪問 http://localhost:8300/add?a=1&b=2 ,得到返回結(jié)果:

{
    msg: "操作成功",
    result: 3,
    code: 200
}

多次訪問惊来,查看 AddServiceApplication 的控制臺(tái),可以看到兩個(gè) ADD-SERVICE-DEMO 被負(fù)載均衡的調(diào)用矢渊。
demo源碼 spring-cloud-1.0/feign-client-demo

使用docker-maven-plugin打包并生成docker鏡像

add-service-demo 為例枉证,
復(fù)制 application.yml,重命名為 application-docker.yml昂灵,修改 defaultZone為:

eureka:
  client:
    serviceUrl:
      defaultZone: http://service-registry:8000/eureka/

這里修改了 defaultZone 的訪問url,如何修改取決于部署docker容器時(shí)的 --link 參數(shù)眨补, --link 可以讓兩個(gè)容器之間互相通信倒脓。

修改 application.yml 中的 spring 節(jié)點(diǎn)為:

spring:
  application:
    name: @project.artifactId@
  profiles:
    active: @activatedProperties@

這里增加了 profiles 的配置,在maven打包時(shí)選擇不同的profile甘晤,加載不同的配置文件饲做。

在pom.xml文件中增加:

<properties>
    <java.version>1.8</java.version> <!-- 指定java版本 -->
    <!-- 鏡像前綴,推送鏡像到遠(yuǎn)程庫(kù)時(shí)需要盆均,這里配置了一個(gè)阿里云的私有庫(kù) -->
    <docker.image.prefix>
        registry.cn-hangzhou.aliyuncs.com/ztecs
    </docker.image.prefix>
    <!-- docker鏡像的tag -->
    <docker.tag>demo</docker.tag>

    <!-- 激活的profile -->
    <activatedProperties></activatedProperties>
</properties>

<profiles>
    <!-- docker環(huán)境 -->
    <profile>
        <id>docker</id>

        <properties>
            <activatedProperties>docker</activatedProperties>
            <docker.tag>docker-demo-${project.version}</docker.tag>
        </properties>
    </profile>
</profiles>

<build>
    <defaultGoal>install</defaultGoal>
    <finalName>${project.artifactId}</finalName>

    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>

    <plugins>
        <!-- 配置spring boot maven插件,把項(xiàng)目打包成可運(yùn)行的jar包 -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <executable>true</executable>
            </configuration>
        </plugin>

        <!-- 打包時(shí)跳過單元測(cè)試 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <skipTests>true</skipTests>
            </configuration>
        </plugin>

        <!-- 配置docker maven插件饰抒,綁定install生命周期诀黍,在運(yùn)行maven install時(shí)生成docker鏡像 -->
        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>docker-maven-plugin</artifactId>
            <version>0.4.13</version>
            <executions>
                <execution>
                    <phase>install</phase>
                    <goals>
                        <goal>build</goal>
                        <goal>tag</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <!-- 修改這里的docker節(jié)點(diǎn)ip,需要打開docker節(jié)點(diǎn)的遠(yuǎn)程管理端口2375眯勾,
                具體如何配置可以參照之前的docker安裝和配置的文章 -->
                <dockerHost>http://docker節(jié)點(diǎn)ip:2375</dockerHost>
                <imageName>${docker.image.prefix}/${project.build.finalName}</imageName>
                <baseImage>java</baseImage>
                <!-- 這里的entryPoint定義了容器啟動(dòng)時(shí)的運(yùn)行命令咒精,容器啟動(dòng)時(shí)運(yùn)行
                java -jar 包名 , -Djava.security.egd這個(gè)配置解決tomcat8啟動(dòng)時(shí),
因?yàn)樾枰占h(huán)境噪聲來生成安全隨機(jī)數(shù)導(dǎo)致啟動(dòng)過慢的問題-->
                <entryPoint>
                    ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/${project.build.finalName}.jar"]
                </entryPoint>
                <resources>
                    <resource>
                        <targetPath>/</targetPath>
                        <directory>${project.build.directory}</directory>
                        <include>${project.build.finalName}.jar</include>
                    </resource>
                </resources>
                <image>${docker.image.prefix}/${project.build.finalName}</image>
                <newName>${docker.image.prefix}/${project.build.finalName}:${docker.tag}</newName>
                <forceTags>true</forceTags>
                <!-- 如果需要在生成鏡像時(shí)推送到遠(yuǎn)程庫(kù)歇拆,pushImage設(shè)為true -->
                <pushImage>false</pushImage>
            </configuration>
        </plugin>
    </plugins>
</build>

選擇 docker profile故觅,運(yùn)行 mvn install -P docker 渠啊,打包項(xiàng)目并生成docker鏡像输吏,注意docker-maven-plugin中的 <entryPoint> 標(biāo)簽里的內(nèi)容不能換行贯溅,否則在生成docker鏡像的時(shí)候會(huì)報(bào)錯(cuò)躲查。
運(yùn)行成功后,登錄docker節(jié)點(diǎn)镣煮,運(yùn)行 docker images 應(yīng)該可以看到剛才打包生成的鏡像了。

啟動(dòng)docker容器并注冊(cè)服務(wù)

在前一篇中镊折,已經(jīng)創(chuàng)建了一個(gè) service-registry-demo 的docker鏡像介衔,這里先把這個(gè)鏡像運(yùn)行起來。

docker run -d --name service-registry-demo --publish 8000:8000 \
 --volume /etc/localtime:/etc/localtime \
 registry.cn-hangzhou.aliyuncs.com/ztecs/service-registry-demo:docker-demo-1.0

對(duì)這條命令做個(gè)簡(jiǎn)單說明夜牡, -d 指定當(dāng)前容器運(yùn)行在后臺(tái), --name 指定容器名稱塘装, --publish 指定端口映射到宿主機(jī), --volume 這個(gè)掛載是為了解決容器內(nèi)的時(shí)區(qū)和宿主機(jī)不一致的問題僚碎,讓容器使用宿主機(jī)設(shè)置的時(shí)區(qū)阴幌,最后指定使用的docker鏡像,鏡像名稱和標(biāo)簽需要根據(jù)自己的情況做修改矛双。
運(yùn)行這條命令之后,service-registry-demo 的容器就啟動(dòng)了懒闷。訪問 http://宿主機(jī)IP:8000,打開注冊(cè)中心的頁面愤估。
下邊啟動(dòng) add-service-demo 容器速址,

docker run -d --name add-service-demo --link service-registry-demo:service-registry --publish 8100:8100 \
 --volume /etc/localtime:/etc/localtime \
 registry.cn-hangzhou.aliyuncs.com/ztecs/add-service-demo:docker-demo-1.0

這條命令和上一條差不多,只是增加了一個(gè) --link 參數(shù)昔园,--link 指定容器間的連接并炮,命令格式 --link 容器名:別名,這里連接了之前創(chuàng)建的名為 service-registry-demo 的容器羡棵,這里的別名和 application-docker.yml 文件中配置的 defaultZone 一致。其實(shí)就是通過別名找到了對(duì)應(yīng)的容器IP皂冰,進(jìn)到容器里查看 hosts 文件就明白了养篓,其實(shí)就是加了條hosts映射。
add-service-demo 容器啟動(dòng)成功之后舶胀,刷新配置中心的頁面,發(fā)現(xiàn)已經(jīng)注冊(cè)到配置中心了嚣伐。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市放典,隨后出現(xiàn)的幾起案子基茵,更是在濱河造成了極大的恐慌,老刑警劉巖弥臼,帶你破解...
    沈念sama閱讀 222,946評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件醋火,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡芥驳,警方通過查閱死者的電腦和手機(jī)茬高,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丽猬,“玉大人熏瞄,你說我怎么就攤上這事∮勺溃” “怎么了?”我有些...
    開封第一講書人閱讀 169,716評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵行您,是天一觀的道長(zhǎng)剪廉。 經(jīng)常有香客問我,道長(zhǎng)捌斧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,222評(píng)論 1 300
  • 正文 為了忘掉前任妇押,我火速辦了婚禮,結(jié)果婚禮上洞难,老公的妹妹穿的比我還像新娘舆吮。我一直安慰自己揭朝,他們只是感情好队贱,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,223評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著潭袱,像睡著了一般柱嫌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上屯换,一...
    開封第一講書人閱讀 52,807評(píng)論 1 314
  • 那天编丘,我揣著相機(jī)與錄音,去河邊找鬼彤悔。 笑死嘉抓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的晕窑。 我是一名探鬼主播抑片,決...
    沈念sama閱讀 41,235評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼杨赤!你這毒婦竟也來了敞斋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,189評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤植捎,失蹤者是張志新(化名)和其女友劉穎焰枢,沒想到半個(gè)月后医咨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,712評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡很泊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,775評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了枫虏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片隶债。...
    茶點(diǎn)故事閱讀 40,926評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡曲梗,死狀恐怖虏两,靈堂內(nèi)的尸體忽然破棺而出笤虫,到底是詐尸還是另有隱情耕皮,我是刑警寧澤,帶...
    沈念sama閱讀 36,580評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站赐俗,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏叔扼。R本人自食惡果不足惜瓜富,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,259評(píng)論 3 336
  • 文/蒙蒙 一谤辜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧渠欺,春花似錦椎眯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,750評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至庙睡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間啡邑,已是汗流浹背募寨。 一陣腳步聲響...
    開封第一講書人閱讀 33,867評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工贵涵, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瓷马,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,368評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親焚鹊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,930評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容