在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):happyyangyuan/springcloud-quickstart开源软件地址(OpenSource Url):https://github.com/happyyangyuan/springcloud-quickstart开源编程语言(OpenSource Language):Java 99.1%开源软件介绍(OpenSource Introduction):springcloud-quickstart这是一个基于gradle构建工具的spring cloud微服务框架超级简单入门教程。
spring cloud为开发人员提供了快速搭建分布式系统的一整套解决方案,包括配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等等。它可以直接在PC上使用Java的main方法运行集群。
另外说明spring cloud是基于springboot的,所以需要开发中对springboot有一定的了解。 最近在推广我自己开源的生产级高性能响应式的微服务框架,学习成本相对springcloud低很多,有兴趣的可以关注一下 spring cloud依赖管理
## dependency versions.
springBootVersion=1.5.8.RELEASE
springCloudVersion=Edgware.RELEASE
### docker configuration
#gradle docker plugin version
transmodeGradleDockerVersion=1.2
#This configuration is for docker container environment to access the local machine host,in Chinese is "宿主机" ip.
hostMachineIp=10.40.20.54
buildscript {
repositories {
maven { url "https://repo.spring.io/libs-milestone/" }
jcenter()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
allprojects {
apply plugin: 'org.springframework.boot'
repositories {
maven { url "https://repo.spring.io/libs-milestone/" }
jcenter()
}
dependencyManagement {
imports {
//spring bom helps us to declare dependencies without specifying version numbers.
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
} 注意,上面imports的mavenBom非常重要,它帮我们管理了springCloud各种零散的jar包的版本。有了它,我们在对springCloud组件的依赖引入时,不需要指定具体的组件版本了,这简直是炒鸡方便啊。
服务注册中心/discovery/eureka-server
dependencies {
compile('org.springframework.cloud:spring-cloud-starter-eureka-server')
}
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ 另请注意一点:很多网上的教程以及spring官方的教程上将'service-url'写成'serviceUrl'这是错误的! @EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
} 启动这个main方法,然后访问 http://localhost:8761 dependencies {
compile "org.springframework.cloud:spring-cloud-starter-eureka"
} springboot入口main类:com.example.EurekaDemoClientApplication.java @SpringBootApplication
@EnableDiscoveryClient
@RestController
public class EurekaDemoClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaDemoClientApplication.class, args);
}
@Value("${server.port}")
private int port;
@RequestMapping("/hi")
public String hi() {
return "hi, my port=" + port;
}
} application.yml
执行main方法启动springboot后,可以访问http://localhost:8763/hi 查看springboot restApi效果。 访问http://localhost:8761 (eureka-server控制台)查看服务注册效果。 依次类推,再启动另外一个/discovery/eureka-demo-client0,请再次查看服务注册效果。 服务路由和负载均衡/routing以上/discovery/eureka-demo-client和/discovery/eureka-demo-client0我们可以把它看作是服务提供者service provider,这里开始定义服务消费者,即对服务提供者进行调用的的客户端。
当同一个微服务启动了多个副本节点后,我们对该服务的调用就需要一个负载均衡器来选择其中一个节点来进行调用,这就是springcloud-ribbon提供的功能。而feign则是对springcloud ribbon的一个封装,方便使用的。这里不深入介绍ribbon了,它本质就是一个借助服务注册发现实现的一个负载均衡器。
下面来分析feign源码: dependencies{
compile "org.springframework.cloud:spring-cloud-starter-feign"
compile "org.springframework.cloud:spring-cloud-starter-eureka"
} com.example.RoutingDemoFeignApplication.java @SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class RoutingDemoFeignApplication {
public static void main(String[] args) {
SpringApplication.run(RoutingDemoFeignApplication.class, args);
}
} com.example.CallHiService.java接口,指明service provider微服务名: eureka-demo-client @FeignClient(value = "eureka-demo-client")
public interface CallServiceHi {
@RequestMapping(value = "/hi", method = RequestMethod.GET)
String sayHiFromClientOne(@RequestParam(value = "name") String name);
} com.example.HiController.java 方便我们验证负载均衡结果: @RestController
public class HiController {
@Autowired
private CallServiceHi hiServiceCaller;
@RequestMapping("hi")
public String hi(@RequestParam String name) {
return hiServiceCaller.sayHiFromClientOne(name);
}
} application.yml需要指明服务注册中心的地址,从而可以获取到所有目标节点信息,从而实现负载的功能 eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
server:
port: 8765
spring:
application:
name: service-feign 运行main方法,启动springboot,然后请多次访问http://localhost:8765/hi?name=happyyangyuan 查看负载效果。 预期的输出结果轮流为:hi happyyangyuan, my port=8763 / hi happyyangyuan, my port=8762 调用链追踪/call-chain/call-chain内的demo展示的是使用Spring Cloud Sleuth实现的分布式系统的调用链追踪方案,它兼容支持了zipkin,只需要在build.gradle文件中引入相应的依赖即可。 /call-chain/zipkin-server顾名思义,就是springCloud Sleuth内置的zipkin-server集成,以来配置/call-chain/zipkin-server/build.gradle: dependencies {
compile "io.zipkin.java:zipkin-server"
compile "io.zipkin.java:zipkin-autoconfigure-ui"
} com.example.ZipkinServerApplication.java,注意加入@EnableZipkinServer注解: @SpringBootApplication
@EnableZipkinServer
public class ZipkinServerApplication {
public static void main(String[] args) {
SpringApplication.run(ZipkinServerApplication.class, args);
}
} application.properties指明zipkin端口
执行com.example.ZipkinServerApplication.java的main方法启动,然后访问http://localhost:9411 /call-chain/zipkin-clients调用链模拟这里模拟调用链: zipkin-client --调用--> zipkin-client0 --调用--> zipkin-client1 /call-chain/zipkin-clients/build.gradle指定三个zipkinClients的公共依赖配置:subprojects{
dependencies {
compile 'org.springframework.cloud:spring-cloud-starter-zipkin'
/*这两个依赖已经被传递依赖了,因此不需要申明
compile "org.springframework.cloud:spring-cloud-sleuth-zipkin-stream"
compile "org.springframework.cloud:spring-cloud-starter-sleuth"*/
compile "org.springframework.cloud:spring-cloud-starter-feign"
compile "org.springframework.cloud:spring-cloud-starter-eureka"
}
} 注意到,服务调用我们使用的的是feign客户端,并且引入了服务发现eureka客户端和zipkin客户端。 zipkin客户端配置配置文件依然是/call-chain/zipkin-clients/zipkin-client/src/main/resources/application.properties
上面的配置文件,注意一下三点
zipkin客户端ZipkinClientApplication代码逻辑com.example.ZipkinClientApplication.java使用feign实现了对zipkin-client0的调用: @SpringBootApplication
@RestController
@EnableDiscoveryClient
@EnableFeignClients
public class ZipkinClientApplication {
public static void main(String[] args) {
SpringApplication.run(ZipkinClientApplication.class, args);
}
@Autowired
private FeignServiceInterface feignService;
@RequestMapping(value = "/")
public String home() {
return feignService.callServiceFeign("no name");
}
@FeignClient(value = "zipkin-client0")
public interface FeignServiceInterface {
@RequestMapping(value = "/", method = RequestMethod.GET)
String callServiceFeign(@RequestParam(value = "name") String name);
}
} 不知道你注意到没有,zipkin客户端激活功能不需要什么鬼类似“@EnableXxx”之类的注解,满足以下两点就可以激活zipkin客户端了数据采集了:
验证调用链看效果启动zipkin-server、zipkin-client、zipkin-client0、zipkin-client1,启动方式你们都懂的。 然后访问http://localhost:8988 即可将调用链日志数据发送给zipkin-server,然后你再访问http://localhost:9411 查看调用链的展示。界面操作太简单,我就不贴图了。 集中配置管理/config在实际微服务实现的分布式应用中,微服务数量是比较多的,节点数就更多了,我们不可能去每个节点里面去修改和维护那些配置文件的。我们需要一个统一的地方去定义和管理这些配置,springCloud Config提供了这样一个功能,我们只需要使用VCS版本管理控制系统比如git来维护一份统一配置,然后由springCloudConfig server读取这些配置,并可以提供给其他所有springCloudConfig Client来读取。使用VCS不仅可以让我们可以追溯所有的历史版本的配置文件,而且也实现了统一管理。 config serverdemo在/config/config-server内 dependencies {
compile('org.springframework.cloud:spring-cloud-config-server')
} com.example.ConfigServerApplication.java加入@EnableConfigServer注解 @EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
} application.properties: spring.application.name=config-server
server.port=8888
##spring.cloud.config.server.git.uri
# Please change the following configuration to point to your own configuration git repo url.
spring.cloud.config.server.git.uri=https://github.com/happyyangyuan/springcloud-configuration.git
# Local git repo url for test only.
# spring.cloud.config.server.git.uri=${HOME}/ideaProjects/spring/configurations-demo-git
# in case of the default /tmp dir deletion.
spring.cloud.config.server.git.basedir=config-repo
#Branch name for the repository.
spring.cloud.config.label=master 这里配置文件注意几点:
config client在实际分布式应用里面,很多微服务应用都有自己独立的配置文件的,由于分布式应用比较分散,管理麻烦,因此我们可以考虑把微服务连接到spring cloud config server上,从config server读取集中配置。 一个简单的config readerdemo在 /config/config-reader路径内 依赖引入: dependencies {
compile "org.springframework.cloud:spring-cloud-starter-config"
compile "org.springframework.cloud:spring-cloud-starter-eureka"
} bootstrap.properties spring.application.name=config-reader
spring.cloud.config.label=master
spring.cloud.config.profile=profileName
spring.cloud.config.uri=http://localhost:8888/ application.yml server:
port: 8881
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/ 注意事项:
@SpringBootApplication
@RestController
@EnableDiscoveryClient
public class ConfigReaderApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigReaderApplication.class, args);
}
@Value("${message}")
private String value;
@RequestMapping(value = "/")
public String read() {
return value;
}
} 启动application,然后访问http://localhost:8881 查看效果吧。 spring cloud bus 消息总线不知道你有没有发现,即使你把git内的配置修改了,以上config-reader是没法自动刷新配置的,必须重启服务才可以。spring cloud bus可以解决这个问题,让我们的配置可以动态刷新。 这里以/config/config-reader-with-bus为例来讲解。 引入依赖,build.gradle: dependencies {
compile "org.springframework.cloud:spring-cloud-starter-bus-amqp"
compile "org.springframework.cloud:spring-cloud-starter-config"
compile "org.springframework.cloud:spring-cloud-starter-eureka"
} 这里引入了一个spring-cloud-starter-bus-amqp,它是spring cloud bus规范的一种实现,基于amqp协议。接入我们比较熟悉的rabbitMQ队列服务。 bootstrap.yml配置如下: server:
port: 8882
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
spring:
application:
name: config-reader
cloud:
config:
label: master
profile: dev
uri: http://localhost:8888/
rabbitmq:
host: yourRabbitMqHost
port: 000 #yourRabbitPort
username: rabbitUserName
password: rabbitUserPwd
management:
security:
enabled: false 注意事项:
@SpringBootApplication
@EnableDiscoveryClient
@RestController
@RefreshScope
public class ConfigReaderWithBusApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigReaderWithBusApplication.class, args);
}
/**
* Waning: {@link RefreshScope} does not support private properties
*/
@Value("${message}")
String message;
@RequestMapping("/")
public String home() {
return message;
}
} 注意事项:
启动application,然后访问http://localhost:8882 看看配置是否读取出来。然后修改你的git对应的配置文件,然后用postman/curl等http客户端工具调用如下API:http://localhost:8882/bus/refresh 触发配置更新,如果提示无权限调用此接口,可以配置为禁用management.security.enabled=false,然后再次访问http://localhost:8882 看看配置是否有更新。 -/config/config-reader-with-bus0是另外一个config client的demo,它是用来验证一次刷新/bus/refresh则所有支持了消息总线的客户端都统一自动刷新配置的功能。亲,动手试试吧。 服务网关/api-gateway本demo /api-gateway/zuul 展示的是使用spring cloud Zuul实现的网关服务。Zuul的主要功能是路由转发和过滤器,路由功能是微服务的一部分,比如/api/user转发到到user服务,/api/shop转发到到shop服务。zuul默认和Ribbon结合实现了负载均衡的功能。 依赖管理build.gradle: dependencies {
compile "org.springframework.cloud:spring-cloud-starter-zuul"
compile "org.springframework.cloud:spring-cloud-starter-eureka"
} 注意这里,ribbon的依赖不需要加入,因为它会被zuul传递依赖得到,服务发现客户端依赖spring-cloud-starter-eureka必须要加入。 application.yml server:
port: 8769
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
spring:
application:
name: zuul
zuul:
routes:
api0:
path: /api0/**
serviceId: eureka-demo-client 根据配置的转发规则可以看到,对zuul的/api0/** 的请求将全部转发到服务eureka-demo-client上,我们可以在这里配置多个路由转发规则。 com.example.ZuulApplication @EnableDiscoveryClient
@EnableZuulProxy
@SpringBootApplication
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
} 启动ZuulApplication查看效果: http://localhost:8769/api0/hi?name=happyyangyuan 断路器 待补充待补充 容器化运行方案
关于容器化构建的附加说明
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论