好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

使用Spring Boot和Docker构建微服务

译者 | 涂承烨

审校 | 孙淑娟

在本教程中,我将向你展示如何使用Spring Boot及其不同组件构建微服务。在最后一节中,我将向你展示如何使用Docker容器部署微服务 。

我们将学习:

1、 实现微服务的不同组件

2、 通过容器化部署服务

微服务架构组件

1.配置服务器

为了使属性文件集中并被所有微服务共享,我们将创建一个本身就是微服务的配置服务器,并管理所有微服务属性文件,这些文件是版本控制的;属性中的任何更改都将自动发布到所有微服务,而不需要重新启动这些服务。需要记住的一件事是,每个微服务都要与配置服务器通信以获取属性值,因此配置服务器必须是一个高可用的组件;如果它宕机了,那么所有的微服务都会宕机,因为它不能确定属性的值!因此,我们应该考虑这个场景-配置服务器不应该是SPF(单点故障),所以我们将为配置服务器启动多个实例容器,用于应对这样的场景。

2.Eureka发现服务

微服务的主要目标是构建基于业务特性去中心化的不同组件,这样每个组件(也就是微服务)可以根据需要扩展,因此对于一个特定的微服务,有多个实例,我们可以根据需要添加和删除实例,因此单体式负载均衡的方式在微服务范例中是不适用的。

因为容器是动态生成的,所以容器有动态IP地址,要跟踪微服务的所有实例,就需要一个管理微服务的服务。当容器生成时,它将自己注册到此服务中,管理服务跟踪实例;如果删除了微服务,则管理服务将其从服务注册表中删除。如果其他微服务需要相互通信,它会通过服务发现以获得另一个服务的实例。同样,这是一个高可用性组件;如果服务发现宕机,微服务就不能相互通信,因此服务发现必须有多个实例。

3.组件,也称为服务

组件是微服务体系结构中的关键组成部分。我所说的组件是指可以独立管理或更新的实用工具或业务特性。它有一个预定义的边界,它公开了一个API,其他组件可以通过这个API与该服务通信。

微服务的理念是将一个完整的业务功能分解为几个独立的小功能,这些功能将相互通信以实现整个业务功能。将来,如果功能的任何部分发生了变化,我们可以更新或删除该组件,并向架构中添加一个新组件。因此,微服务架构通过适当的封装和适当定义的边界形成了适当的模块化架构。

4.网关服务

微服务是一组独立服务的集合,它们共同组成一个业务功能。每个微服务都会发布一个API,通常是一个REST API,因此作为一个客户端,管理这么多要通信的端点URL是很麻烦的。另外,请从另一个角度考虑:如果某个应用程序希望构建身份验证框架或安全检查,它们必须在多个服务中各自实现,这将违反DRY的设计原则(DRY:Don't Repeat Yourself )。如果我们有一个面向互联网的网关服务,客户端将只调用一个端点,它将调用委托给一个实际的微服务,所有的身份验证或安全检查都将在网关服务中完成。

现在我们已经基本了解了微服务的不同部分是如何一起工作的。在本教程中,我将创建一个返回员工信息的员工搜索服务、一个调用搜索服务并显示结果的EmployeeDashBoard服务、一个Eureka服务(便于这些服务可以注册)以及一个网关服务(便于从外部连接到这些服务)。然后,我们将在Docker容器中部署我们的服务,并使用DockerCompose来生成Docker容器。在本教程中,我将使用Spring Boot。

让我们开始构建我们的微服务项目,必须创建五个单独的微服务:

配置服务器 Eureka服务器(注册中心) 员工服务 员工Dashboard服务 Zuul代理(网关服务)

最好从 Spring Initializr 网站开始,购买所需的模块,然后点击[generate project]。

对于本教程,我们将使用Spring Boot 1.5.4。

创建配置服务器

要创建配置服务器,首先我们需要检查starting .spring.io中的配置服务器模块,也检查actuator的endpoints。然后,下载zip文件并在Eclipse中打开它。

pom文件类似这样:

 <  ?  xml   version  =  "1.0"   encoding  =  "UTF-8"  ?  >   <  project   xmlns  =  "http://maven.apache.org/POM/4.0.0"   xmlns : xsi  =  "http://HdhCmsTestw3.org/2001/XMLSchema-instance"   xsi : schemaLocation  =  "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"  >   <  modelVersion  >  4.0  .0  <  /modelVersion>   <  groupId  >  com . example  <  /groupId>   <  artifactId  >  MicroserviceConfigServer  <  /artifactId>   <  version  >  0.0  .1  -  SNAPSHOT  <  /version>   <  packaging  >  jar  <  /packaging>   <  name  >  MicroserviceConfigServer  <  /name>   <  description  >  Demo   project   for   Spring   Boot  <  /description>   <  parent  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  starter  -  parent  <  /artifactId>   <  version  >  1.5  .4 . RELEASE  <  /version>   <  relativePath   /  >       <  /parent>   <  properties  >   <  project . build . sourceEncoding  >  UTF  -  8  <  /project.build.sourceEncoding>   <  project . reporting . outputEncoding  >  UTF  -  8  <  /project.reporting.outputEncoding>   <  java . version  >  1.8  <  /java.version>   <  spring  -  cloud . version  >  Dalston . SR1  <  /spring-cloud.version>   <  /properties>   <  dependencies  >   <  dependency  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  starter  -  actuator  <  /artifactId>   <  /dependency>   <  dependency  >   <  groupId  >  org . springframework . cloud  <  /groupId>   <  artifactId  >  spring  -  cloud  -  config  -  server  <  /artifactId>   <  /dependency>   <  dependency  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  starter  -  test  <  /artifactId>   <  scope  >  test  <  /scope>   <  /dependency>   <  /dependencies>   <  dependencyManagement  >   <  dependencies  >   <  dependency  >   <  groupId  >  org . springframework . cloud  <  /groupId>   <  artifactId  >  spring  -  cloud  -  dependencies  <  /artifactId>   <  version  >  $ { spring  -  cloud . version } <  /version>   <  type  >  pom  <  /type>   <  scope  >  import  <  /scope>   <  /dependency>   <  /dependencies>   <  /dependencyManagement>   <  build  >   <  plugins  >   <  plugin  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  maven  -  plugin  <  /artifactId>   <  /plugin>   <  /plugins>   <  /build>   <  /project> 

 

 

它将会下载spring-cloud-config-server构件。

 

下一步,我们会创建一个bootstrap.properties文件,在该文件中提到配置服务器从哪里读取相关属性。在生产模式下,它应该是Git仓库的URL,但是由于这是一个演示,所以我将使用我的本地磁盘。所有属性文件都将放在那里,配置服务器将读取这些属性文件。

让我们来看看bootstrap.properties文件的内容:

 server . port  =  9090   spring . cloud . config . server . native . searchLocations  =  file : //${user.home}/MicroService/centralProperties/   SPRING_PROFILES_ACTIVE  =  native 

 

 

在这里,我们引导Spring Boot设置系统的访问端口为9090,并使用一个centralProperties文件夹作为搜索所有属性文件的文件夹。注意,在我们的Docker容器中,你必须创建一个centralProperties文件夹,并将所有属性文件放在那里。

 

现在让我们看看Java部分:

 package   com . example . MicroserviceConfigServer ;  import   org . springframework . boot . SpringApplication ;  import   org . springframework . boot . autoconfigure . SpringBootApplication ;  import   org . springframework . cloud . config . server . EnableConfigServer ;  @  EnableConfigServer   @  SpringBootApplication   public   class   ConfigServer  {  public   static   void   main ( String []  args ) {  SpringApplication . run ( ConfigServer . class ,  args );
 }
}

 

 

在这里,我们使用了@EnableConfigserver注释,我们引导Spring Boot将此服务视为配置服务器应用程序。

 

现在,在centralProperties文件夹中放置一些测试属性文件。

现在,我们已经为配置服务器设置好了。如果我们运行这个服务并在浏览器输入URL http://localhost:9090/config/default,我们会看到以下响应:

{  "name" :  "config" ,  "profiles" : [  "default"  ],  "label" :  null ,  "version" :  null ,  "state" :  null ,  "propertySources" : [
      {  "name" :  "file:///home/shamik/MicroService/centralProperties/config.properties" ,  "source" : {  "application.message" :  "Hello Shamik"  }
      },
      {  "name" :  "file:///home/shamik/MicroService/centralProperties/application.properties" ,  "source" : {  "welcome.message" :  "Hello Spring Cloud"  }
      }
   ]
}

 

 

它显示了我放置在centralProperties文件夹中的所有文件名、键和值。

 

实现服务发现

下一步是创建用于服务发现的Eureka服务器。我们将使用Netflix的Eureka服务器进行服务发现。为此,我从start.spring.io中选择Eureka服务器模块,并下载项目。

pom文件类似这样:

 <  ?  xml   version  =  "1.0"   encoding  =  "UTF-8"  ?  >   <  project   xmlns  =  "http://maven.apache.org/POM/4.0.0"   xmlns : xsi  =  "http://HdhCmsTestw3.org/2001/XMLSchema-instance"   xsi : schemaLocation  =  "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"  >   <  modelVersion  >  4.0  .0  <  /modelVersion>   <  groupId  >  com . example  <  /groupId>   <  artifactId  >  EmployeeEurekaServer  <  /artifactId>   <  version  >  0.0  .1  -  SNAPSHOT  <  /version>   <  packaging  >  jar  <  /packaging>   <  name  >  EmployeeEurekaServer  <  /name>   <  description  >  Demo   project   for   Spring   Boot  <  /description>   <  parent  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  starter  -  parent  <  /artifactId>   <  version  >  1.5  .4 . RELEASE  <  /version>   <  relativePath   /  >       <  /parent>   <  properties  >   <  project . build . sourceEncoding  >  UTF  -  8  <  /project.build.sourceEncoding>   <  project . reporting . outputEncoding  >  UTF  -  8  <  /project.reporting.outputEncoding>   <  java . version  >  1.8  <  /java.version>   <  spring  -  cloud . version  >  Dalston . SR1  <  /spring-cloud.version>   <  /properties>   <  dependencies  >   <  dependency  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  starter  -  actuator  <  /artifactId>   <  /dependency>   <  dependency  >   <  groupId  >  org . springframework . cloud  <  /groupId>   <  artifactId  >  spring  -  cloud  -  starter  -  config  <  /artifactId>   <  /dependency>   <  dependency  >   <  groupId  >  org . springframework . cloud  <  /groupId>   <  artifactId  >  spring  -  cloud  -  starter  -  eureka  -  server  <  /artifactId>   <  /dependency>   <  dependency  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  starter  -  test  <  /artifactId>   <  scope  >  test  <  /scope>   <  /dependency>   <  /dependencies>   <  dependencyManagement  >   <  dependencies  >   <  dependency  >   <  groupId  >  org . springframework . cloud  <  /groupId>   <  artifactId  >  spring  -  cloud  -  dependencies  <  /artifactId>   <  version  >  $ { spring  -  cloud . version } <  /version>   <  type  >  pom  <  /type>   <  scope  >  import  <  /scope>   <  /dependency>   <  /dependencies>   <  /dependencyManagement>   <  build  >   <  plugins  >   <  plugin  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  maven  -  plugin  <  /artifactId>   <  /plugin>   <  /plugins>   <  /build>   <  /project> 

现在创建bootstrap.properties:

 spring . application . name  =  EmployeeEurekaServer   eureka . client . serviceUrl . defaultZone : http : //localhost:9091/   server . port  =  9091   eureka . client . register  -  with  -  eureka  =  false   eureka . client . fetch  -  registry  =  false 

在这里,我为这个应用程序的逻辑名称起名为EmployeeEurekaServer, Eureka服务器的URL是http://localhost:9091,将在端口9091上启动。请注意,Eureka服务器本身可以是一个Eureka客户端;因为可能有多个Eureka服务器的实例,它需要与其他服务器同步。通过eureka.client.register-with-eureka=false,我们明确告知Spring Boot不要把Eureka服务器当作客户端,因为我只创建了一个Eureka服务器,所以它不需要把自己注册为客户端。

现在我将创建Java文件:

 package   com . example . EmployeeEurekaServer ;  import   org . springframework . boot . SpringApplication ;  import   org . springframework . boot . autoconfigure . SpringBootApplication ;  import   org . springframework . cloud . netflix . eureka . server . EnableEurekaServer ;  @  EnableEurekaServer   @  SpringBootApplication   public   class   EmployeeEurekaServerApplication  {  public   static   void   main ( String []  args ) {  SpringApplication . run ( EmployeeEurekaServerApplication . class ,  args );
 }
}

 

 

通过@EnableEurekaServer注释,Spring Boot将该服务生成为Eureka服务器。如果我运行服务,并在浏览器中输入http://localhost:9091/,我们将看到以下页面:

 

创建员工搜索服务

现在,我们将创建一个微服务,它根据传递的ID实际返回Employee信息。此外,它还可以返回所有Employee信息。我将发布一个REST API,并在Eureka服务器上注册这个微服务,以便其他微服务可以发现它。

我们从start.spring.io中选择eurekclient。

让我们看看这个的pomm .xml:

 <  ?  xml   version  =  "1.0"   encoding  =  "UTF-8"  ?  >   <  project   xmlns  =  "http://maven.apache.org/POM/4.0.0"   xmlns : xsi  =  "http://HdhCmsTestw3.org/2001/XMLSchema-instance"   xsi : schemaLocation  =  "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"  >   <  modelVersion  >  4.0  .0  <  /modelVersion>   <  groupId  >  com . example  <  /groupId>   <  artifactId  >  EmployeeSearchService  <  /artifactId>   <  version  >  0.0  .1  -  SNAPSHOT  <  /version>   <  packaging  >  jar  <  /packaging>   <  name  >  EmployeeSearchService  <  /name>   <  description  >  Demo   project   for   Spring   Boot  <  /description>   <  parent  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  starter  -  parent  <  /artifactId>   <  version  >  1.5  .4 . RELEASE  <  /version>   <  relativePath   /  >       <  /parent>   <  properties  >   <  project . build . sourceEncoding  >  UTF  -  8  <  /project.build.sourceEncoding>   <  project . reporting . outputEncoding  >  UTF  -  8  <  /project.reporting.outputEncoding>   <  java . version  >  1.8  <  /java.version>   <  spring  -  cloud . version  >  Dalston . SR1  <  /spring-cloud.version>   <  /properties>   <  dependencies  >   <  dependency  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  starter  -  actuator  <  /artifactId>   <  /dependency>   <  dependency  >   <  groupId  >  org . springframework . cloud  <  /groupId>   <  artifactId  >  spring  -  cloud  -  starter  -  config  <  /artifactId>   <  /dependency>   <  dependency  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  starter  -  jersey  <  /artifactId>   <  /dependency>   <  dependency  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  starter  -  web  <  /artifactId>   <  /dependency>   <  dependency  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  starter  -  test  <  /artifactId>   <  scope  >  test  <  /scope>   <  /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  >  $ { spring  -  cloud . version } <  /version>   <  type  >  pom  <  /type>   <  scope  >  import  <  /scope>   <  /dependency>   <  /dependencies>   <  /dependencyManagement>   <  build  >   <  plugins  >   <  plugin  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  maven  -  plugin  <  /artifactId>   <  /plugin>   <  /plugins>   <  /build>   <  /project> 

让我们看看这个的bootstrap.properties:

 spring . application . name  =  EmployeeSearch   spring . cloud . config . uri  =  http : //localhost:9090   eureka . client . serviceUrl . defaultZone : http : //localhost:9091/eureka   server . port  =  8080   security . basic . enable :  false   management . security . enabled :  false 

在这里,我们给服务的逻辑名称起名为EmployeeSearch,该服务的所有实例在Eureka服务器中都以这个名称注册。这是所有EmployeeSerach服务实例的通用逻辑名称。另外,我给出了配置服务器的URL(请注意,当我们在Docker中部署它时,我们应该更改localhost为配置服务器的Docker容器IP,以便找到配置服务器)。

另外也提到了Eureka服务器的URL(请注意,当我们在Docker中部署它时,我们应该将localhost更改为Eureka的Docker容器IP,以便找到Eureka服务器)。

现在我们来创建controller和service文件。

 package   com . example . EmployeeSearchService . service ;  import   java . util . Collection ;  import   java . util . HashMap ;  import   java . util . Map ;  import   java . util . stream . Collectors ;  import   java . util . stream . Stream ;  import   org . springframework . stereotype . Service ;  import   com . example . EmployeeSearchService . domain . model . Employee ;  @  Service   public   class   EmployeeSearchService  {  private   static   Map   <   Long ,  Employee   >   EmployeeRepsitory   =   null ;  static  {  Stream   <   String   >   employeeStream   =   Stream . of ( "1,Shamik  Mitra,Java,Architect" ,  "2,Samir  Mitra,C++,Manager" ,  "3,Swastika  Mitra,AI,Sr.Architect" );  EmployeeRepsitory   =   employeeStream . map ( employeeStr   -  >  {  String []  info   =   employeeStr . split ( "," );  return   createEmployee ( new   Long ( info [ 0 ]),  info [ 1 ],  info [ 2 ],  info [ 3 ]);
  }). collect ( Collectors . toMap ( Employee :: getEmployeeId ,  emp   -  >   emp ));

 }  private   static   Employee   createEmployee ( Long   id ,  String   name ,  String   practiceArea ,  String   designation ) {  Employee   emp   =   new   Employee ();  emp . setEmployeeId ( id );  emp . setName ( name );  emp . setPracticeArea ( practiceArea );  emp . setDesignation ( designation );  emp . setCompanyInfo ( "Cognizant" );  return   emp ;
 }  public   Employee   findById ( Long   id ) {  return   EmployeeRepsitory . get ( id );
 }  public   Collection   <   Employee   >   findAll () {  return   EmployeeRepsitory . values ();
 }

}

Controller文件:

 package   com . example . EmployeeSearchService . controller ;  import   java . util . Collection ;  import   org . springframework . beans . factory . annotation . Autowired ;  import   org . springframework . cloud . context . config . annotation . RefreshScope ;  import   org . springframework . web . bind . annotation . PathVariable ;  import   org . springframework . web . bind . annotation . RequestMapping ;  import   org . springframework . web . bind . annotation . RestController ;  import   com . example . EmployeeSearchService . domain . model . Employee ;  import   com . example . EmployeeSearchService . service . EmployeeSearchService ;  @  RefreshScope   @  RestController   public   class   EmployeeSearchController  {  @  Autowired   EmployeeSearchService   employeeSearchService ;  @  RequestMapping ( "/employee/find/{id}" )  public   Employee   findById ( @  PathVariable   Long   id ) {  return   employeeSearchService . findById ( id );
 }  @  RequestMapping ( "/employee/findall" )  public   Collection   <   Employee   >   findAll () {  return   employeeSearchService . findAll ();
 }
}  package   com . example . EmployeeSearchService . domain . model ;  public   class   Employee  {  private   Long   employeeId ;  private   String   name ;  private   String   practiceArea ;  private   String   designation ;  private   String   companyInfo ;  public   Long   getEmployeeId () {  return   employeeId ;
 }  public   void   setEmployeeId ( Long   employeeId ) {  this . employeeId   =   employeeId ;
 }  public   String   getName () {  return   name ;
 }  public   void   setName ( String   name ) {  this . name   =   name ;
 }  public   String   getPracticeArea () {  return   practiceArea ;
 }  public   void   setPracticeArea ( String   practiceArea ) {  this . practiceArea   =   practiceArea ;
 }  public   String   getDesignation () {  return   designation ;
 }  public   void   setDesignation ( String   designation ) {  this . designation   =   designation ;
 }  public   String   getCompanyInfo () {  return   companyInfo ;
 }  public   void   setCompanyInfo ( String   companyInfo ) {  this . companyInfo   =   companyInfo ;
 }  @  Override   public   String   toString () {  return   "Employee [employeeId="   +   employeeId   +   ", name="   +   name   +   ", practiceArea="   +   practiceArea   +   ", designation="   +   designation   +   ", companyInfo="   +   companyInfo   +   "]" ;
 }




}

 

 

这里没有什么特别的;我只创建了几个employee,并将它们映射到Rest URL。

 

现在让我们看看Spring Boot文件:

 package   com . example . EmployeeSearchService ;  import   org . springframework . boot . SpringApplication ;  import   org . springframework . boot . autoconfigure . SpringBootApplication ;  import   org . springframework . cloud . client . discovery . EnableDiscoveryClient ;  import   org . springframework . cloud . netflix . eureka . EnableEurekaClient ;  @  EnableDiscoveryClient   @  SpringBootApplication   public   class   EmployeeSearchServiceApplication  {  public   static   void   main ( String []  args ) {  SpringApplication . run ( EmployeeSearchServiceApplication . class ,  args );
 }
}

在这里,我们使用@EnableDiscoveryClient注释将该服务注册为Eureka客户机。

现在 ,如果我们在浏览器中输入http://localhost:8080/employee/find/1,可以看到以下输出:

{  "employeeId" : 1 ,  "name" : "Shamik  Mitra" ,  "practiceArea" : "Java" ,  "designation" : "Architect" ,  "companyInfo" : "Cognizant"  }

创建员工大屏服务

现在,我将创建另一个服务,它使用Employee Search 服务来获取Employee信息,以便与Employee Search服务通信。我会使用Feign客户端,也会使用Hystrix作为断路器,所以如果Employee搜索服务宕机,它可以返回默认数据。

pom.xml:

 <  ?  xml   version  =  "1.0"   encoding  =  "UTF-8"  ?  >   <  project   xmlns  =  "http://maven.apache.org/POM/4.0.0"   xmlns : xsi  =  "http://HdhCmsTestw3.org/2001/XMLSchema-instance"   xsi : schemaLocation  =  "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"  >   <  modelVersion  >  4.0  .0  <  /modelVersion>   <  groupId  >  com . example  <  /groupId>   <  artifactId  >  EmployeeDashBoardService  <  /artifactId>   <  version  >  0.0  .1  -  SNAPSHOT  <  /version>   <  packaging  >  jar  <  /packaging>   <  name  >  EmployeeDashBoardService  <  /name>   <  description  >  Demo   project   for   Spring   Boot  <  /description>   <  parent  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  starter  -  parent  <  /artifactId>   <  version  >  1.5  .4 . RELEASE  <  /version>   <  relativePath   /  >       <  /parent>   <  properties  >   <  project . build . sourceEncoding  >  UTF  -  8  <  /project.build.sourceEncoding>   <  project . reporting . outputEncoding  >  UTF  -  8  <  /project.reporting.outputEncoding>   <  java . version  >  1.8  <  /java.version>   <  spring  -  cloud . version  >  Dalston . SR1  <  /spring-cloud.version>   <  /properties>   <  dependencies  >   <  dependency  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  starter  -  actuator  <  /artifactId>   <  /dependency>   <  dependency  >   <  groupId  >  org . springframework . cloud  <  /groupId>   <  artifactId  >  spring  -  cloud  -  starter  -  config  <  /artifactId>   <  /dependency>   <  dependency  >   <  groupId  >  org . springframework . cloud  <  /groupId>   <  artifactId  >  spring  -  cloud  -  starter  -  eureka  <  /artifactId>   <  /dependency>   <  dependency  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  starter  -  jersey  <  /artifactId>   <  /dependency>   <  dependency  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  starter  -  web  <  /artifactId>   <  /dependency>   <  dependency  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  starter  -  test  <  /artifactId>   <  scope  >  test  <  /scope>   <  /dependency>   <  dependency  >   <  groupId  >  org . springframework . cloud  <  /groupId>   <  artifactId  >  spring  -  cloud  -  starter  -  feign  <  /artifactId>   <  /dependency>   <  dependency  >   <  groupId  >  org . springframework . cloud  <  /groupId>   <  artifactId  >  spring  -  cloud  -  starter  -  ribbon  <  /artifactId>   <  /dependency>   <  dependency  >   <  groupId  >  org . springframework . cloud  <  /groupId>   <  artifactId  >  spring  -  cloud  -  starter  -  hystrix  <  /artifactId>   <  /dependency>   <  /dependencies>   <  dependencyManagement  >   <  dependencies  >   <  dependency  >   <  groupId  >  org . springframework . cloud  <  /groupId>   <  artifactId  >  spring  -  cloud  -  dependencies  <  /artifactId>   <  version  >  $ { spring  -  cloud . version } <  /version>   <  type  >  pom  <  /type>   <  scope  >  import  <  /scope>   <  /dependency>   <  /dependencies>   <  /dependencyManagement>   <  build  >   <  plugins  >   <  plugin  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  maven  -  plugin  <  /artifactId>   <  /plugin>   <  /plugins>   <  /build>   <  /project> 

 

 

bootstrap.properties:

 

 spring . application . name  =  EmployeeDashBoard   spring . cloud . config . uri  =  http : //localhost:9090   eureka . client . serviceUrl . defaultZone : http : //localhost:9091/eureka   server . port  =  8081   security . basic . enable :  false   management . security . enabled :  false  

 

 

 

 

Feign client:

 package   com . example . EmployeeDashBoardService . controller ;  import   java . util . Collection ;  import   org . springframework . cloud . netflix . feign . FeignClient ;  import   org . springframework . cloud . netflix . ribbon . RibbonClient ;  import   org . springframework . web . bind . annotation . PathVariable ;  import   org . springframework . web . bind . annotation . RequestMapping ;  import   com . example . EmployeeDashBoardService . domain . model . EmployeeInfo ;  @  FeignClient ( name   =   "EmployeeSearch" )  @  RibbonClient ( name   =   "EmployeeSearch" )  public   interface   EmployeeServiceProxy  {  @  RequestMapping ( "/employee/find/{id}" )  public   EmployeeInfo   findById ( @  PathVariable ( value   =   "id" )  Long   id );  @  RequestMapping ( "/employee/findall" )  public   Collection   <   EmployeeInfo   >   findAll ();

}

 

 

Controller:

 

 package   com . example . EmployeeDashBoardService . controller ;  import   java . util . Collection ;  import   org . springframework . beans . factory . annotation . Autowired ;  import   org . springframework . cloud . context . config . annotation . RefreshScope ;  import   org . springframework . web . bind . annotation . PathVariable ;  import   org . springframework . web . bind . annotation . RequestMapping ;  import   org . springframework . web . bind . annotation . RestController ;  import   com . example . EmployeeDashBoardService . domain . model . EmployeeInfo ;  @  RefreshScope   @  RestController   public   class   FeignEmployeeInfoController  {  @  Autowired   EmployeeServiceProxy   proxyService ;  @  RequestMapping ( "/dashboard/feign/{myself}" )  public   EmployeeInfo   findme ( @  PathVariable   Long   myself ) {  return   proxyService . findById ( myself );

 }  @  RequestMapping ( "/dashboard/feign/peers" )  public   Collection   <   EmployeeInfo   >   findPeers () {  return   proxyService . findAll ();
 }

}

 

 

Spring boot启动service:

 

 package   com . example . EmployeeDashBoardService ;  import   org . springframework . boot . SpringApplication ;  import   org . springframework . boot . autoconfigure . SpringBootApplication ;  import   org . springframework . boot . web . client . RestTemplateBuilder ;  import   org . springframework . cloud . client . circuitbreaker . EnableCircuitBreaker ;  import   org . springframework . cloud . client . discovery . EnableDiscoveryClient ;  import   org . springframework . cloud . netflix . feign . EnableFeignClients ;  import   org . springframework . context . annotation . Bean ;  import   org . springframework . web . client . RestTemplate ;  @  EnableDiscoveryClient   @  EnableFeignClients   @  SpringBootApplication   public   class   EmployeeDashBoardService  {  public   static   void   main ( String []  args ) {  SpringApplication . run ( EmployeeDashBoardService . class ,  args );
 }  @  Bean   public   RestTemplate   restTemplate ( RestTemplateBuilder   builder ) {  return   builder . build ();
 }
}

一切就绪!我们现在准备好了。如果我们在浏览器中输入url http://localhost:8081/dashboard/feign/1,将看到以下输出:

{  "employeeId" : 1 ,  "name" : "Shamik  Mitra" ,  "practiceArea" : "Java" ,  "designation" : "Architect" ,  "companyInfo" : "Cognizant"  }

创建网关服务

pom.xml:

 <  ?  xml   version  =  "1.0"   encoding  =  "UTF-8"  ?  >   <  project   xmlns  =  "http://maven.apache.org/POM/4.0.0"   xmlns : xsi  =  "http://HdhCmsTestw3.org/2001/XMLSchema-instance"   xsi : schemaLocation  =  "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"  >   <  modelVersion  >  4.0  .0  <  /modelVersion>   <  parent  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  dependencies  <  /artifactId>   <  version  >  1.5  .6 . RELEASE  <  /version>   <  relativePath  > .. / .. /  spring  -  boot  -  dependencies  <  /relativePath>   <  /parent>   <  artifactId  >  spring  -  boot  -  starter  -  parent  <  /artifactId>   <  packaging  >  pom  <  /packaging>   <  name  >  Spring   Boot   Starter   Parent  <  /name>   <  description  >  Parent   pom   providing   dependency   and   plugin   management   for   applications   built   with   Maven  <  /description>   <  url  >  http : //projects.spring.io/spring-boot/   <  organization  >   <  name  >  Pivotal   Software ,  Inc . <  /name>   <  url  >  http : //HdhCmsTestspring.io   <  /organization>   <  properties  >   <  java . version  >  1.6  <  /java.version>   <  resource . delimiter  >  @  <  /resource.delimiter>       <  project . build . sourceEncoding  >  UTF  -  8  <  /project.build.sourceEncoding>   <  project . reporting . outputEncoding  >  UTF  -  8  <  /project.reporting.outputEncoding>   <  maven . compiler . source  >  $ { java . version } <  /maven测试数据piler.source>   <  maven . compiler . target  >  $ { java . version } <  /maven测试数据piler.target>   <  /properties>   <  dependencyManagement  >   <  dependencies  >   <  dependency  >   <  groupId  >  org . springframework  <  /groupId>   <  artifactId  >  spring  -  core  <  /artifactId>   <  version  >  $ { spring . version } <  /version>   <  exclusions  >   <  exclusion  >   <  groupId  >  commons  -  logging  <  /groupId>   <  artifactId  >  commons  -  logging  <  /artifactId>   <  /exclusion>   <  /exclusions>   <  /dependency>   <  /dependencies>   <  /dependencyManagement>   <  build  >   {C}    <  resources  >   <  resource  >   <  directory  >  $ { basedir } /src/  main  /  resources  <  /directory>   <  filtering  >  true  <  /filtering>   <  includes  >   <  include  >  **  /application*.yml  include  >   <  include  >  **  /application*.yaml  include  >   <  include  >  **  /application*.properties  include  >   <  /includes>   <  /resource>   <  resource  >   <  directory  >  $ { basedir } /src/  main  /  resources  <  /directory>   <  excludes  >   <  exclude  >  **  /application*.yml  exclude  >   <  exclude  >  **  /application*.yaml  exclude  >   <  exclude  >  **  /application*.properties  exclude  >   <  /excludes>   <  /resource>   <  /resources>   <  pluginManagement  >   <  plugins  >   {C}    <  plugin  >   <  groupId  >  org . apache . maven . plugins  <  /groupId>   <  artifactId  >  maven  -  failsafe  -  plugin  <  /artifactId>   <  executions  >   <  execution  >   <  goals  >   <  goal  >  integration  -  test  <  /goal>   <  goal  >  verify  <  /goal>   <  /goals>   <  /execution>   <  /executions>   <  /plugin>   <  plugin  >   <  groupId  >  org . apache . maven . plugins  <  /groupId>   <  artifactId  >  maven  -  jar  -  plugin  <  /artifactId>   <  configuration  >   <  archive  >   <  manifest  >   <  mainClass  >  $ { start  -  class } <  /mainClass>   <  addDefaultImplementationEntries  >  true  <  /addDefaultImplementationEntries>   <  /manifest>   <  /archive>   <  /configuration>   <  /plugin>   <  plugin  >   <  groupId  >  org . apache . maven . plugins  <  /groupId>   <  artifactId  >  maven  -  surefire  -  plugin  <  /artifactId>   <  configuration  >   <  includes  >   <  include  >  **  /*Tests.java     **/   *  Test . java  <  /include>   <  /includes>   <  excludes  >   <  exclude  >  **  /Abstract*.java  exclude  >   <  /excludes>   <  /configuration>   <  /plugin>   <  plugin  >   <  groupId  >  org . apache . maven . plugins  <  /groupId>   <  artifactId  >  maven  -  war  -  plugin  <  /artifactId>   <  configuration  >   <  failOnMissingWebXml  >  false  <  /failOnMissingWebXml>   <  archive  >   <  manifest  >   <  mainClass  >  $ { start  -  class } <  /mainClass>   <  addDefaultImplementationEntries  >  true  <  /addDefaultImplementationEntries>   <  /manifest>   <  /archive>   <  /configuration>   <  /plugin>   <  plugin  >   <  groupId  >  org . codehaus . mojo  <  /groupId>   <  artifactId  >  exec  -  maven  -  plugin  <  /artifactId>   <  configuration  >   <  mainClass  >  $ { start  -  class } <  /mainClass>   <  /configuration>   <  /plugin>   <  plugin  >   <  groupId  >  org . apache . maven . plugins  <  /groupId>   <  artifactId  >  maven  -  resources  -  plugin  <  /artifactId>   <  version  >  2.6  <  /version>   <  configuration  >   <  delimiters  >   <  delimiter  >  $ { resource . delimiter } <  /delimiter>   <  /delimiters>   <  useDefaultDelimiters  >  false  <  /useDefaultDelimiters>   <  /configuration>   <  /plugin>   <  plugin  >   <  groupId  >  pl . project13 . maven  <  /groupId>   <  artifactId  >  git  -  commit  -  id  -  plugin  <  /artifactId>   <  executions  >   <  execution  >   <  goals  >   <  goal  >  revision  <  /goal>   <  /goals>   <  /execution>   <  /executions>   <  configuration  >   <  verbose  >  true  <  /verbose>   <  dateFormat  >  yyyy  -  MM  -  dd  'T'  HH : mm : ssZ  <  /dateFormat>   <  generateGitPropertiesFile  >  true  <  /generateGitPropertiesFile>   <  generateGitPropertiesFilename  >  $ { project . build . outputDirectory } /git.properties  generateGitPropertiesFilename  >   <  /configuration>   <  /plugin>       <  plugin  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  maven  -  plugin  <  /artifactId>   <  executions  >   <  execution  >   <  goals  >   <  goal  >  repackage  <  /goal>   <  /goals>   <  /execution>   <  /executions>   <  configuration  >   <  mainClass  >  $ { start  -  class } <  /mainClass>   <  /configuration>   <  /plugin>       <  plugin  >   <  groupId  >  org . apache . maven . plugins  <  /groupId>   <  artifactId  >  maven  -  shade  -  plugin  <  /artifactId>   <  dependencies  >   <  dependency  >   <  groupId  >  org . springframework . boot  <  /groupId>   <  artifactId  >  spring  -  boot  -  maven  -  plugin  <  /artifactId>   <  version  >  1.5  .6 . RELEASE  <  /version>   <  /dependency>   <  /dependencies>   <  configuration  >   <  keepDependenciesWithProvidedScope  >  true  <  /keepDependenciesWithProvidedScope>   <  createDependencyReducedPom  >  true  <  /createDependencyReducedPom>   <  filters  >   <  filter  >   <  artifact  >  * : *  <  /artifact>   <  excludes  >   <  exclude  >  META  -  INF  /*.SF     META-INF/*.DSA      META-INF/*.RSA                                  package            shade                            META-INF/spring.handlers                META-INF/spring.factories                META-INF/spring.schemas                      ${start-class}                                         bootstrap.properties:   spring.application.name=EmployeeAPIGateway   eureka.client.serviceUrl.defaultZone:http://localhost:9091/eureka   server.port=8084   security.basic.enable: false    management.security.enabled: false    zuul.routes.employeeUI.serviceId=EmployeeDashBoard   zuul.host.socket-timeout-millis=30000         

在这里,请注意属性zuul.routes.employeeUI.serviceId=EmployeeDashBoard。有了这个,我们指示Zuul,任何包含employeeUI的URL都会重定向到EmployeeDashboard服务。

Spring Boot file:

 package   com . example . EmployeeZuulService ;  import   org . springframework . boot . SpringApplication ;  import   org . springframework . boot . autoconfigure . SpringBootApplication ;  import   org . springframework . cloud . client . discovery . EnableDiscoveryClient ;  import   org . springframework . cloud . netflix . zuul . EnableZuulProxy ;  @  EnableZuulProxy   @  EnableDiscoveryClient   @  SpringBootApplication   public   class   EmployeeZuulServiceApplication  {  public   static   void   main ( String []  args ) {  SpringApplication . run ( EmployeeZuulServiceApplication . class ,  args );
 }
}

 

 

现在,如果我运行服务并在浏览器中输入

 

http://localhost:8084/employeeUI/dashboard/feign/1,将看到以下输出 :

{  "employeeId" : 1 ,  "name" : "Shamik  Mitra" ,  "practiceArea" : "Java" ,  "designation" : "Architect" ,  "companyInfo" : "Cognizant"  }

在Docker容器中部署

现在代码已写完。让我们看看应用程序是如何运行的。到目前为止,我们所有的服务都在本地机器上完美地运行。但是,我们不希望我们的代码最终只在本地环境中运行。相反,我们希望看到它在生产环境中出色地运行。(我们爱我们的代码就像爱我们的孩子,我们希望看到它一直成功)。但当我们送孩子上学或引导他们就是为了他们能走上正确的成功之路,同样我们也需要引导我们的应用走上成功之路。因此,让我们进入DevOps的世界,并尝试为我们的源代码在生产环境中提供正确的路径。

● 欢迎来到Docker世界

Docker就不用介绍了。如果你觉得你还需要一个指南,看看 这里 。。

接下来,我将假设你的电脑上安装了Docker CE。我们将在这里使用以下部署概念:

1、Dockerfile:这是一个文本文档,包含了构建Docker映像所需的所有指令。使用Dockerfile的指令集,我们可以编写复制文件、进行安装等步骤。如需更多参考,请 访问此链接 。

2、Docker Compose:这是一个可以创建和生成多个容器的工具。它有助于使用一个命令构建所需的环境。

3、如微服务架构图所示,我们将为每个微服务创建一个单独的容器。下面是我们示例中的容器列表:

配置服务器(Config Server) 员工微服务(EmployeeService) 员工搜索微服务(Employee Search Service) 员工大屏微服务(Employee Dashboard Service) 网关微服务(Gateway Service)

● 配置服务器的Docker配置

容器应该包含配置服务器jar文件,我们将从本地电脑中选择jar文件上传到容器中。在真实的场景中,我们应该将jar文件推送到一个Artifact Repository Manager系统,比如Nexus或Artifactory,容器应该从repo manager下载该文件。

根据bootstrap.properties,配置服务器应该在端口8888上可用。

如上所述,我们将让配置服务器从文件读取配置,因此我们将确保即使容器宕机,这些属性文件也能被检索到。

创建一个名为config-repo的文件夹,其中将包含所需的属性文件。我们将确保对Config Server容器执行以下操作。

#  mkdir   config  -  repo  #  cd   config  -  repo  #  echo   "service.employyesearch.serviceId=EmployeeSearch"   >   EmployeeDashBoard . properties  #  echo   "user.role=Dev"   >   EmployeeSearch . properties 

回到上一级文件夹,创建一个名为Dockerfile的Docker文件。这个Dockerfile将创建我们的基础镜像,其中包含Java。

#  cd  .. /  #  vi   Dockerfile 

 

 

放置以下内容:

 

 FROM   alpine : edge   MAINTAINER   javaonfly   RUN   apk   add   --  no  -  cache   openjdk8 

 

 

FROM: 这个关键字告诉Docker使用给定的图像及其标签作为构建基础。

 

MAINTAINER: 映像的作者。

RUN: 该命令将在系统中安装openjdk8。

执行下面的命令来创建基本的Docker镜像:

 docker   build   --  tag  =  alpine  -  jdk : base   --  rm  =  true  

在成功构建基础映像之后,就该为Config Server创建Docker映像了。

创建一个名为files的文件夹,并将配置服务器jar文件放在该目录中。然后,创建一个名为Dockerfile-configserver的文件,内容如下:

 FROM   alpine  -  jdk : base   MAINTAINER   javaonfly   COPY   files  /  MicroserviceConfigServer . jar   /  opt  /  lib  /   RUN   mkdir   /  var  /  lib  /  config  -  repo   COPY   config  -  repo   /  var  /  lib  /  config  -  repo   ENTRYPOINT  [ "/usr/bin/java" ]  CMD  [ "-jar" ,  "/opt/lib/MicroserviceConfigServer.jar" ]  VOLUME   /  var  /  lib  /  config  -  repo   EXPOSE   9090 

在这里,我们提到了从前面创建的alpine-jdk映像构建映像。我们将把名为employeeconfigserver.jar的jar文件复制到/opt/lib位置,并将config-repo复制到/root目录。当容器启动时,我们希望配置服务器开始运行,因此将ENTRYPOINT和CMD设置为运行Java命令。我们需要挂载一个卷来从容器外部共享配置文件;VOLUME命令可以帮助我们实现这一点。外部应该可以通过端口9090访问配置服务器;这就是为什么我们有公开端口 9090。

现在让我们构建Docker镜像,并将其标记为config-server:

#  docker   build   --  file  =  Dockerfile  -  configserver   --  tag  =  config  -  server : latest   --  rm  =  true  .

现在让我们创建一个Docker卷:

#  docker   volume   create   --  name  =  config  -  repo  #  docker   run   --  name  =  config  -  server   --  publish  =  9090 : 9090   --  volume  =  config  -  repo : /var/  lib  /  config  -  repo   config  -  server : latest 

 

 

一旦我们运行上面的命令,我们应该能够看到一个Docker容器启动并运行。如果我们打开浏览器输入URL http://localhost:9090/config/default/,我们也应该能够访问这些属性。

 

● EurekaServer

类似地,我们需要为EurekaServer创建Docker文件,它将运行在9091端口上。Eureka服务器的Dockerfile应该如下所示:

 FROM   alpine  -  jdk : base   MAINTAINER   javaonfly   COPY   files  /  MicroserviceEurekaServer . jar   /  opt  /  lib  /   ENTRYPOINT  [ "/usr/bin/java" ]  CMD  [ "-jar" ,  "/opt/lib/MicroserviceEurekaServer.jar" ]  EXPOSE   9091 

要构建映像,使用以下命令:

 docker   build   --  file  =  Dockerfile  -  EurekaServer   --  tag  =  eureka  -  server : latest   --  rm  =  true  .  docker   run   --  name  =  eureka  -  server   --  publish  =  9091 : 9091   eureka  -  server : latest 

微服务

现在是时候部署我们真正的微服务了。步骤应该是类似的;我们唯一需要记住的是我们的微服务是依赖于ConfigServer和EurekaServer的,所以我们总是需要确保在我们启动微服务之前,上面两个服务是启动并运行的。容器之间存在依赖关系,所以是时候研究Docker Compose了。这是确保容器生成保持一定秩序的一种很好的方式。

为此,我们应该为其他容器编写一个Dockerfile。下面是Dockerfile的内容:

 Dockerfile  -  EmployeeSearch .  ===  ===  ===  ===  ===  ===  ===  ===  ===  ===  ==   FROM   alpine  -  jdk : base   MAINTAINER   javaonfly   RUN   apk   --  no  -  cache   add   netcat  -  openbsd   COPY   files  /  EmployeeSearchService . jar   /  opt  /  lib  /   COPY   EmployeeSearch  -  entrypoint . sh   /  opt  /  bin  /  EmployeeSearch  -  entrypoint . sh   RUN   chmod   755   /  opt  /  bin  /  EmployeeSearch  -  entrypoint . sh   EXPOSE   8080   Dockerfile  -  EmployeeDashboard   ===  ===  ===  ===  ===  ===  ===  ===  ===  ===  ===  ===   FROM   alpine  -  jdk : base   MAINTAINER   javaonfly   RUN   apk   --  no  -  cache   add   netcat  -  openbsd   COPY   files  /  EmployeeDashBoardService . jar   /  opt  /  lib  /   COPY   EmployeeDashBoard  -  entrypoint . sh   /  opt  /  bin  /  EmployeeDashBoard  -  entrypoint . sh   RUN   chmod   755   /  opt  /  bin  /  EmployeeDashBoard  -  entrypoint . sh   EXPOSE   8080   Dockerfile  -  ZuulServer   ===  ===  ===  ===  ===  ===  ===  ===  ===  ===  ===  ===  ===  ==   FROM   alpine  -  jdk : base   MAINTAINER   javaonfly   COPY   files  /  EmployeeZuulService . jar   /  opt  /  lib  /   ENTRYPOINT  [ "/usr/bin/java" ]  CMD  [ "-jar" ,  "/opt/lib/EmployeeZuulService.jar" ]  EXPOSE   8084 

 

 

这里需要注意的是,我为Employee和Employee Dashboard服务创建了两个shell脚本。它指示Dockercompose在Config服务器和Eureka服务器启动之前不要启动Employee和Employee Dashboard服务。

 

 Employee   dashBoard   Script   ===  ===  ===  ===  ===  ===  ===  ===  ===  ===  ===  =   #!/bin/sh   while   !   nc   -  z   config  -  server   9090  ;  do   echo   "Waiting for the Config Server"   sleep   3   done   while   !   nc   -  z   eureka  -  server   9091  ;  do   echo   "Waiting for the Eureka Server"   sleep   3   done   java   -  jar   /  opt  /  lib  /  EmployeeDashBoardService . jar   ===  ===  ===  ===  ===  ===  ===  ===  ===  ===  ===  =   Employee   service   Script   ===  ===  ===  ===  ===  ===  ===  ===  ===  ===  ===  =   #!/bin/sh   while   !   nc   -  z   config  -  server   9090  ;  do   echo   "Waiting for the Config Server"   sleep   3   done   while   !   nc   -  z   eureka  -  server   9091  ;  do   echo   "Waiting for the Eureka Server"   sleep   3   done   java   -  jar   /  opt  /  lib  /  EmployeeSearchService . jar 

现在让我们创建一个名为docker-compose.yml的文件。它将使用所有这些Dockerfiles来生成我们所需的环境。它还将确保生成所需的容器保持正确的顺序,并且它们是相互连接的。

 version :  '2.2'   services :  config  -  server :  container_name :  config  -  server   build :  context : .  dockerfile :  Dockerfile  -  configserver   image :  config  -  server : latest   expose :  -   9090   ports :  -   9090 : 9090   networks :  -   emp  -  network   volumes :  -   config  -  repo : /var/  lib  /  config  -  repo   eureka  -  server :  container_name :  eureka  -  server   build :  context : .  dockerfile :  Dockerfile  -  EurekaServer   image :  eureka  -  server : latest   expose :  -   9091   ports :  -   9091 : 9091   networks :  -   emp  -  network   EmployeeSearchService :  container_name :  EmployeeSearch   build :  context : .  dockerfile :  Dockerfile  -  EmployeeSearch   image :  employeesearch : latest   environment :  SPRING_APPLICATION_JSON :  '{"spring": {"cloud": {"config": {"uri": "http://config-server:9090"}}}}'   entrypoint :  /opt/  bin  /  EmployeeSearch  -  entrypoint . sh   expose :  -   8080   ports :  -   8080 : 8080   networks :  -   emp  -  network   links :  -   config  -  server : config  -  server   -   eureka  -  server : eureka  -  server   depends_on :  -   config  -  server   -   eureka  -  server   logging :  driver :  json  -  file   EmployeeDashboardService :  container_name :  EmployeeDashboard   build :  context : .  dockerfile :  Dockerfile  -  EmployeeDashboard   image :  employeedashboard : latest   environment :  SPRING_APPLICATION_JSON :  '{"spring": {"cloud": {"config": {"uri": "http://config-server:9090"}}}}'   entrypoint :  /opt/  bin  /  EmployeeDashBoard  -  entrypoint . sh   expose :  -   8081   ports :  -   8081 : 8081   networks :  -   emp  -  network   links :  -   config  -  server : config  -  server   -   eureka  -  server : eureka  -  server   depends_on :  -   config  -  server   -   eureka  -  server   logging :  driver :  json  -  file   ZuulServer :  container_name :  ZuulServer   build :  context : .  dockerfile :  Dockerfile  -  ZuulServer   image :  zuulserver : latest   expose :  -   8084   ports :  -   8084 : 8084   networks :  -   emp  -  network   links :  -   eureka  -  server : eureka  -  server   depends_on :  -   eureka  -  server   logging :  driver :  json  -  file   networks :  emp  -  network :  driver :  bridge   volumes :  config  -  repo :  external :  true  

下面是Docker compose文件中的几个重要属性:

1、version:一个必填字段,我们需要在这里维护Docker Compose格式的版本。

2、服务:每个属性都定义了我们需要生成的容器。

● build:如果提到了,那么Docker Compose应该从给定的Dockerfile构建一个映像。

● image:将要创建的镜像的名称。

● network:使用的网络名称,这个名称应该出现在网络部分。

● links:这将在服务和上述服务之间创建一个内部链接。这里,EmployeeSearch服务需要访问Config和Eureka服务器。

● depends:这是维持顺序所必需的属性。EmployeeSearch容器依赖于Eureka和Config Server。因此,Docker确保在派生EmployeeSearch容器之前派生Eureka和Config Server容器。

在创建文件之后,我们 构建镜像 ,创建所需的容器,并从下面这个命令开始:

 docker  -  compose   up   --  build 

要停止整个环境,我们可以使用这个命令:

  docker  -  compose   down  

在这个 链接 中可以找到Docker Compose的完整文档。

总之,编写Dockerfile和Docker Compose文件是一个一次性的活动,但它允许你在任何时候根据需要生成一个完整的环境。

结论

这是关于如何在微服务中构建不同组件并在Docker中部署它们的完整指南。在生产环境中,应该会涉及到CI/CD,所以你不需要知道所有用于构建映像的Docker命令,但作为一个全栈开发人员,学习如何在Docker中创建和构建映像是很重要的。

译者介绍

涂承烨,51CTO社区编辑,信息系统项目管理师、信息系统监理师、PMP,某省综合性评标专家,拥有15年的开发经验。对项目管理、前后端开发、微服务、架构设计、物联网、大数据等较为关注。

原文标题: Building Microservices Using Spring Boot and Docker ,作者:Shamik Mitra

原文地址:https://HdhCmsTest51cto测试数据/article/720302.html

查看更多关于使用Spring Boot和Docker构建微服务的详细内容...

  阅读:26次