在阿里云容器服务上开发基于Docker的Spring Cloud微服务应用(三)

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 本文介绍了如何通过Eureka进行服务注册和发现,如何镜像化等内容。最后简单介绍了如何构建示例代码中的所有服务镜像。

服务发现

本文为阿里云容器服务Spring Cloud应用开发系列文章的第三篇。

一、在阿里云容器服务上开发Spring Cloud微服务应用

二、部署Spring Cloud应用示例

三、服务发现(本文)

四、服务间通信与集成

五、服务智能路由

六、集中配置管理

七、高可用和容错

八、监控和日志

九、服务的部署和发布策略

传统应用由于服务数目相对固定,服务所在的节点也相对固定,动态发现的需求不强烈。服务发现的通常做法是通过DNS域名解析,或IP地址找到相关服务。云环境中,服务的数目可能随时变化,服务所在的节点和侦听的端口也无法预先知道,所以在云应用的微服务架构中,服务发现是必须具备的一项能力。

通常我们可以采用zookeeper、etcd或consul等开源产品来实现服务的注册与发现。Spring Cloud中提供了两种方式:一是Consul,另外一个是Netflix的Eureka。本文讨论了如何采用Eureka进行服务发现,以及如何将Eureka及相关服务容器化。

Eureka服务发现和镜像构建

Eureka Server可以通过在程序中annotation声明的方式生成,详细步骤见下文。如果想直接用构建好的镜像,可以使用本文提供的示例:

docker pull registry.aliyuncs.com/jingshanlb/discovery-server

构建Eureka Server镜像

如果使用已有的镜像可以忽略本步。

引入对Eureka的依赖

首先,我们需要在在build.gradle中引入Java项目对Eureka的依赖。

...
dependencies {
    compile('org.springframework.cloud:spring-cloud-starter-eureka-server')
    ...
}
...

通过注解方式声明Eureka Server

Eureka Server可以通过在程序中加入annotation完成,其中@SpringBootApplication将本应用声明为springboot应用,@EnableEurekaServer将Eureka Server的能力带入应用。@EnableDiscoveryClient表明本应用同时也是DiscoveryClient,用于连接Eureka Server。

@SpringBootApplication
@EnableEurekaServer
@EnableDiscoveryClient
public class DiscoveryServerApplication {

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

配置Eureka Server

在application.yml配置Eureka的参数。内容如下:

server:
  port: 8761

eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

---
spring:
  profiles: cloud

server:
  port: 8761

eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/,${ADDITIONAL_EUREKA_SERVER_LIST}

在测试环境中(profile没有指定),Eureka侦听8761端口,serviceUrl.defaultZone中只有一个Eureka服务实例。

在随后的cloud profile中,serviceUrl.defaultZone除了有本机的Eureka Server,还通过ADDITIONAL_EUREKA_SERVER_LIST环境变量指明其他Eureka Server节点信息。Eureka server之间的内容互相同步,Eureka client只需注册到其中任意一个节点即可。

启动Eureka Server

运行Eureka服务有两种方式,一种是通过Docker命令行执行,另外一种是在docker-compose文件中声明,并执行docker-compose启动。

命令行方式可以是从gradle中执行

gradle bootRun

通过Java命令启动单独一个Eureka Server,效果和上面的Gradle命令一样

java -jar build/libs/discovery-server-0.0.1-SNAPSHOT.jar

通过Java命令启动,profile为cloud,并通过环境变量指定了Eureka集群中其他的节点地址。

ADDITIONAL_EUREKA_SERVER_LIST=http://discovery2:8761/eureka/ SPRING_PROFILES_ACTIVE=cloud java -jar build/libs/discovery-server-0.0.1-SNAPSHOT.jar

由于在开发实际的应用过程中往往需要启动多个容器,所以通过脚本的方式启动服务非常不方便,所以建议通过在docker-compose文件中声明启动容器时的环境变量配置Eureka启动时的行为:

services:
  discovery1:
    container_name: discovery1
    image: registry.aliyuncs.com/jingshanlb/discovery-server
    ... ...
    environment:
      - ADDITIONAL_EUREKA_SERVER_LIST=http://discovery2:8761/eureka/
      - SPRING_PROFILES_ACTIVE=cloud

如果有多个Eureka Server需要在ADDITIONAL_EUREKA_SERVER_LIST环境变量中指明,每个Eureka 的URL之间用逗号分隔即可。

构建Eureka Server镜像

Springboot应用编译生成的Jar包包含了所有依赖包以及app server,这种包也叫“超级JAR包“,英文 Uber Jar。编译好的Jar包在dockercompose文件中指明,即可由docker引擎生成容器镜像。

如何编译Uber Jar就不详细介绍了,我们只要记住执行如下命令即可:

gradle build

编译生成的Jar包在build/libs目录:

$ tree build/libs/
build/libs/
├── discovery-server-0.0.1-SNAPSHOT.jar
└── discovery-server-0.0.1-SNAPSHOT.jar.original

0 directories, 2 files

最后,写一个Dockerfile,定义如何生成一个Eureka Server镜像:

FROM java:8-jre-alpine
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/' /etc/apk/repositories
VOLUME /tmp
ADD build/libs/*.jar app.jar
RUN sh -c 'touch /app.jar'
RUN echo $(date) > /image_built_at
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar","--spring.profiles.active=${SPRING_PROFILES_ACTIVE}"]

其中ADD build/libs/*.jar app.jar表示把构建好的Jar包复制到镜像中。由于build/libs目录下只有一个jar包,所以这行命令实际上是将jar包复制到镜像的根目录下,并命名为app.jar。这个Dockerfile可以用户所有springboot编译出来的应用。

RUN echo $(date) > /image_built_at表示把构建镜像的日期打入镜像以利于未来的运维,读者可以根据自己的需求修改或删除这一行。

运行如下命令生成镜像,并上传到你自己的镜像仓库账号下:

#Java构建
gradle build

#创建镜像
export REGPREFIX=registry.aliyuncs.com/<username>/ docker tag $(docker build -t ${REGPREFIX}discovery-server -q .) ${REGPREFIX}discovery-server:$(date -ju "+%Y%m%d-%H%M%S")

运行上述命令生成的Eureka Server镜像有两个tag:latest和创建时间,例如20160627-092112。你可以根据自己的实际需求定义tag。

登录到镜像仓库并上传镜像的命令如下:

#登录到镜像仓库,*** 用户名, *** 密码
docker login -u *** -p *** registry.aliyuncs.com

#将创建好的镜像上传到镜像仓库,<username>替换为你的username
export REGPREFIX=registry.aliyuncs.com/<username>/ docker push {REGPREFIX}discovery-server

注意,如果你是第一次上传镜像,需要首先在阿里云开发者平台 创建一个镜像仓库,否则上传镜像会失败。

进入创建容器仓库界面,输入仓库名,并选择本地仓库
create_repo01

创建成功后就可以随时上传镜像了。

Eureka Client进行服务注册和发现

除Eureka Server之外所有需要注册到Eureka的应用都要通过Eureka Client注册到Eureka Server和获取其他应用的访问信息。

注解

引入Eureka Client也是通过annotation的机制完成。

@SpringBootApplication
@EnableDiscoveryClient
public class BarApplication {

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

其中@EnableDiscoveryClient和前面Eureka Server的注解功能一样,注意,client不能声明EnableEurekaServer。

在bootstrap.yml中为应用命名,该名字用于向Eureka注册,所有用同样名字注册的应用都视为同一个应用(或服务)的不同实例,所以一定要注意应用名在一个Eureka集群的上下文中是唯一的。

spring:
  application:
    name: bar

Eureka Client所属应用也是通过build.gradle文件引入Eureka依赖,application.yml配置Eureka,程序的编译、运行和构建容器镜像和Eureka Server类似,这里就不再重复了。

服务发现和服务调用

通过在bootstrap.yml中声明spring.application.name,应用启动时会自动完成向Eureka Server的注册。那么,如何进行服务发现呢,我们在foobar的代码中看一下。

...
    @Autowired
    @LoadBalanced
    private RestTemplate restTemplate;

...
    private BarMessage getMessageFromBarService(){
        BarMessage bar = restTemplate.getForObject("http://bar/message", BarMessage.class);
        log.debug("From bar service : {}.", bar);
        return bar;
    }
...

RestTemplate的声明需要加上@Autowired@LoadBalanced两个注解。在随后对restTemplate.getForObject的调用传入服务的URL。

http://bar/message

其中bar服务名,/message为希望调用的URL Path。 restTemplate.getForObject从Eureka中获得bar服务的所有实例,并根据内置的负载均衡算法选择一个实例调用并返回结果。

从这里可以看出,利用RestTemplate可以完成服务发现和服务调用。Spring Cloud还提供了其它的方法,比如Feign,这里就不再介绍了。

示例代码

本系列文章的示例可以从这里找到:https://code.aliyun.com/libin.libin/aliyuncs-springcloud-demo

aliyuncs-springcloud-demo目录下可以看到如下内容:

aliyuncs-springcloud-demo$ tree -L 2
.
├── build-all.sh
├── clean-all-images.sh
├── common
│   ├── discovery-server
│   └── gateway
├── docker-compose.acs.yml
├── docker-compose.yml
├── push-all-images.sh
└── services
    ├── bar
    ├── foo
    └── foobar

common目录下是公用服务,包括服务发现的Discovery Server(Eureka),和智能路由Gateway(Zuul)。

services目录下是所有应用的业务逻辑所在的服务,它们都注册到Discovery Server,服务的发现也通过Discovery Server。

注册和发现的机制在前面已经描述过了,所有应用(包括Discovery Server和Gatewa也)的Docker镜像构建都非常类似,在各自的目录下都可以找到相应的文件。

编译所有服务并上传镜像

手工进入每个目录并执行编译和上传的命令非常繁琐,也容易出错,所以在示例中提供了脚本来构建和上传所有服务的镜像。

编译、打包所有服务,并创建容器镜像(不上传镜像)的命令:

#运行命令前将jingshanlb替换为实际用户名
./build-all.sh

上传所有镜像,注意,如果还没创建镜像仓库,首先去创建,步骤见Eureka Server一节。

#运行命令前将jingshanlb替换为实际用户名
./push-all-images.sh

小节

本文介绍了如何通过Eureka进行服务注册和发现,如何镜像化等内容。最后简单介绍了如何构建示例代码中的所有服务镜像。

后续的文章我们会一起来看Spring Cloud和阿里云容器服务的其它特性。

相关实践学习
使用ACS算力快速搭建生成式会话应用
阿里云容器计算服务 ACS(Container Compute Service)以Kubernetes为使用界面,采用Serverless形态提供弹性的算力资源,使您轻松高效运行容器应用。本文将指导您如何通过ACS控制台及ACS集群证书在ACS集群中快速部署并公开一个容器化生成式AI会话应用,并监控应用的运行情况。
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
16天前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1316 5
|
2月前
|
存储 持续交付 Docker
Docker:颠覆传统开发的轻量级容器革命
Docker:颠覆传统开发的轻量级容器革命
|
7月前
|
存储 开发工具 开发者
揭秘 Microsoft.Docker.SDK:让容器开发更轻松的强大工具揭秘
随着云计算和容器技术的快速发展,`Docker` 已经成为容器化技术的事实标准。`Microsoft` 作为 `Docker` 的主要支持者和参与者,推出了 `Microsoft.Docker.SDK`,旨在帮助开发者更轻松地进行容器开发。本文将深入揭秘 Microsoft.Docker.SDK 的功能、使用方法以及它在容器开发中的应用。
184 12
|
7月前
|
安全 持续交付 云计算
课时5:阿里云容器服务:最原生的集成Docker和云服务
阿里云容器服务以服务化形式构建容器基础设施,大幅提升开发效率,简化应用部署流程。通过Docker容器和DevOps工具(如Jenkins),实现自动化部署与迭代,优化企业内部复杂部署问题。该服务支持GPU调度、混合云架构无缝迁移,并与阿里云产品体系无缝集成,提供安全防护、网络负载均衡等多重功能支持。凭借微服务架构,帮助企业突破业务瓶颈,提高资源利用率,轻松应对海量流量。
242 0
课时5:阿里云容器服务:最原生的集成Docker和云服务
|
7月前
|
安全 开发者 Docker
Docker技术背景与应用:解决现代开发中的关键问题
Docker作为一种革命性的容器化技术,极大地改变了现代软件开发的方式。通过解决环境一致性、依赖管理、部署复杂性和资源利用率等问题,Docker为开发者提供了高效、灵活的开发和部署环境。尽管面临着一些挑战,但随着技术的发展和完善,Docker将继续在现代软件开发中发挥重要作用。作为全栈工程师,掌握并善用Docker技术,将为我们的开发工作带来更多便利和可能性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
8月前
|
弹性计算 监控 持续交付
面对热点事件,阿里云如何通过云上弹性与容器服务帮助客户应对流量洪峰
面对热点事件,阿里云如何通过云上弹性与容器服务帮助客户应对流量洪峰
177 0
|
8月前
|
监控 Cloud Native Java
基于阿里云容器服务(ACK)的微服务架构设计与实践
本文介绍如何利用阿里云容器服务Kubernetes版(ACK)构建高可用、可扩展的微服务架构。通过电商平台案例,展示基于Java(Spring Boot)、Docker、Nacos等技术的开发、容器化、部署流程,涵盖服务注册、API网关、监控日志及性能优化实践,帮助企业实现云原生转型。
|
11月前
|
设计模式 Java API
微服务架构演变与架构设计深度解析
【11月更文挑战第14天】在当今的IT行业中,微服务架构已经成为构建大型、复杂系统的重要范式。本文将从微服务架构的背景、业务场景、功能点、底层原理、实战、设计模式等多个方面进行深度解析,并结合京东电商的案例,探讨微服务架构在实际应用中的实施与效果。
546 6
|
11月前
|
设计模式 Java API
微服务架构演变与架构设计深度解析
【11月更文挑战第14天】在当今的IT行业中,微服务架构已经成为构建大型、复杂系统的重要范式。本文将从微服务架构的背景、业务场景、功能点、底层原理、实战、设计模式等多个方面进行深度解析,并结合京东电商的案例,探讨微服务架构在实际应用中的实施与效果。
253 1
|
10月前
|
Java 开发者 微服务
从单体到微服务:如何借助 Spring Cloud 实现架构转型
**Spring Cloud** 是一套基于 Spring 框架的**微服务架构解决方案**,它提供了一系列的工具和组件,帮助开发者快速构建分布式系统,尤其是微服务架构。
786 70
从单体到微服务:如何借助 Spring Cloud 实现架构转型

相关产品

  • 容器计算服务
  • 容器服务Kubernetes版