springcloud微服务实战:Eureka+Zuul+Ribbon+Hystrix+SpringConfig
相信如今已经有不少小伙伴已经或者准备使用springcloud微服务了,接下来为你们搭建一个微服务框架,后期能够本身进行扩展。会提供一个小案例: 服务提供者和服务消费者 ,消费者会调用提供者的服务,新建的项目都是用springboot,附源码下载。css
coding仓库地址: coding地址 csdn下载地址: csdn下载地址html
若是有问题请在下边评论,或者200909980加群交流。java
Eureka:服务发现
Hystrix:断路器
Zuul:智能路由
Ribbon:客户端负载均衡
Turbine:集群监控
Springcloud-config:远程获取配置文件mysql

接下来,咱们开始搭建项目,首先咱们到spring为咱们提供的一个网站快速搭建springboot项目,点击访问,我这里用的是gradle,若是各位客官喜欢用maven,好吧你能够到http://mvnrepository.com/查看对应的依赖,点我访问。nginx
1、搭建eureka-server服务springcloud-eureka-server
eureka-server做为服务发现的核心,第一个搭建,后面的服务都要注册到eureka-server上,意思是告诉eureka-server本身的服务地址是啥。固然还能够用zookeeper或者springconsul。git

若是是maven项目请对应的修改pom.xmlweb
maven { url
"http://maven.aliyun.com/nexus/content/groups/public/" }
compile
group:
'org.springframework.cloud', name:
'spring-cloud-starter-eureka-server', version:
'1.3.4.RELEASE'
compile
group:
'org.springframework.boot', name:
'spring-boot-starter-security', version:
'1.5.6.RELEASE'
还有几点须要修改的,你们对应图片看看,就是springboot打包的时候会提示找不到主累。
redis
- 2.修改 application.yml,建议用yml。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
server:
port:
8761
eureka:
datacenter: trmap
environment: product
client:
healthcheck:
enabled:
true
service-url:
defaultZone: http:
register-with-eureka:
false #关闭本身做为客户端注册
fetch-registry:
false
security:
basic:
enabled:
true
user:
name: root
#用户名和密码,等会访问的时候,会要求你登陆,服务注册的时候也须要带着用户名和密码
password: booszy
- 3.修改程序的主类,建议修改类名,要加如eureka的 @EnableEurekaServer 注解,而后运行main方法。
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}

http://localhost:8761/ 这个是eureka-server的页面地址,到这里,说明eureka-server搭建好了,简单吧,这一步必定要成功,不然后面的就不能继续进行下去了,后边基本相似。spring
2、搭建config-server服务springcloud-config-server
springcloud-config-server是用来将远程git仓库的配置文件动态拉下来,这样配置文件就能够动态的维护了。
新建一个springboot项目,修改maven私服地址,并加入一下依赖。
compile
group:
'org.springframework.cloud', name:
'spring-cloud-starter-eureka', version:
'1.3.4.RELEASE'
compile
group:
'org.springframework.cloud', name:
'spring-cloud-config-server', version:
'1.3.2.RELEASE'
compile
group:
'org.springframework.boot', name:
'spring-boot-actuator', version:
'1.5.6.RELEASE'
compile
group:
'org.springframework.boot', name:
'spring-boot-starter-security', version:
'1.5.6.RELEASE'
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
server:
port:
8500
eureka:
client:
service-url:
#注册服务到eureka上,记住这里要加上eureka-server的用户名和密码
defaultZone: http:
instance:
prefer-ip-address:
true
#可能比较长,复制的时候请写在一行
instance-id: ${spring.application.name}:${spring.cloud.
client.ipAddress}:${spring.application.instance_id:${
server.port}}
appname: springcloud-config-
server
spring:
application:
name: springcloud-config-
server
cloud:
config:
server:
git:
#这是其余项目配置文件的git仓库地址
uri: https:
searchPaths:
'{application}'
security:
basic:
enabled:
true
user:
#这是config-server的用户名和密码
name: root
password: booszy
修改启动类,要加入这三个注解,由于要注册到eureka-server上,因此须要@EnableEurekaClient这个注解
@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
而后运行启动springboot项目,等启动成功后访问eureka的页面,会发现springcloud-config-server已经注册到上面了,若是启动报错,请检查错误信息。

3、搭建服务提供者服务springcloud-provider-config
编写一个服务提供者,提供两个接口,即获取单个用户的信息和获取一个用户列表。用到了spring-data-jpa 和 spring-webmvc ,固然大家公司用什么你仍是继续用什么。
-
- 注意 : 这里除了application.xml,还须要一个bootstrap.yml*
-
- 修改build.gradle文件
compile(
'org.springframework.boot:spring-boot-starter-data-jpa')
compile(
'org.springframework.boot:spring-boot-starter-web')
compile(
"com.alibaba:druid-spring-boot-starter:1.1.2")
compile
group:
'org.springframework.cloud', name:
'spring-cloud-starter-eureka', version:
'1.3.4.RELEASE'
compile
group:
'org.springframework.boot', name:
'spring-boot-actuator', version:
'1.5.6.RELEASE'
compile
group:
'org.springframework.cloud', name:
'spring-cloud-starter-config', version:
'1.3.2.RELEASE'
compile
group:
'org.springframework.session', name:
'spring-session-data-redis', version:
'1.3.1.RELEASE'
runtime(
'mysql:mysql-connector-java')
* 注意 : 这里除了application.xml,还须要一个bootstrap.yml
application.xml我是放到远程仓库地址的,你们能够直接到个人远程仓库,根据项目名(springcloud-provider-config)查询。配置文件的仓库地址:点击访问。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
spring:
application:
name: springcloud
-provider-config
cloud:
config:
#config-server的配置,不须要硬编码config
-server的地址,使用service
-id去eureka
-server获取cong
-server的地址
discovery:
enabled:
true
service
-id: springcloud
-config-server
fail
-fast:
true
username: root
password: booszy
profile: dev
eureka:
client:
service
-url:
defaultZone: http:
instance:
prefer
-ip-address:
true
instance
-id: ${spring
.application
.name}:${spring
.cloud
.client
.ipAddress}:${spring
.application
.instance_id:${server
.port}}
appname: springcloud
-provider-config
编写主类
@SpringBootApplication
@EnableEurekaClient
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
新建UserController, 考虑篇幅 UserService 和 UserRepository就不贴代码了,想看的能够下载个人代码。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
@RequestMapping(
"user")
@RestController
public class UserController {
@Autowired
private UserService userService;
/** * @param id * @return */
@GetMapping(
"{id}")
public User
getuser(@PathVariable String id) {
User user =
null;
try {
System.out.println(id);
user = userService.find(id);
}
catch (Exception e) {
e.printStackTrace();
}
return user;
}
/** * @return */
@GetMapping(
"list")
public List<User>
users() {
try {
List<User> user = userService.findAll();
if (user !=
null && user.size() !=
0) {
return user;
}
return null;
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
运行springboot项目,去eureka-server查看,有没有注册上。

咱们的springcloud-provider-config已经注册到eureka上了,访问接口,成功。

4、搭建消费者服务springcloud-consumer-config-swagger
消费者要访问服务提供者的服务,这里用的是经过RestTemplate请求resetful接口,使用ribbon作客户端负载均衡,hystrix作错误处理,swagger生成接口文档。
仍是熟悉的配方,熟悉的味道,新建springboot项目,添加项目依赖。
compile(
'org.springframework.boot:spring-boot-starter-web')
compile
group:
'org.springframework.cloud', name:
'spring-cloud-starter-eureka', version:
'1.3.4.RELEASE'
compile
group:
'org.springframework.boot', name:
'spring-boot-actuator', version:
'1.5.6.RELEASE'
compile
group:
'org.springframework.cloud', name:
'spring-cloud-starter-config', version:
'1.3.2.RELEASE'
compile
group:
'org.springframework.cloud', name:
'spring-cloud-starter-hystrix', version:
'1.3.4.RELEASE'
compile(
"io.springfox:springfox-swagger2:2.7.0",
"io.springfox:springfox-swagger-ui:2.7.0"
)
application.yml 在git仓库,请前往git仓库查看。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
spring:
application:
name: springcloud
-consumer-config
cloud:
config:
discovery:
enabled:
true
service
-id: springcloud
-config-server
fail
-fast:
true
username: root
password: booszy
profile: dev
eureka:
client:
service
-url:
defaultZone: http:
instance:
prefer
-ip-address:
true
instance
-id: ${spring
.application
.name}:${spring
.cloud
.client
.ipAddress}:${spring
.application
.instance_id:${server
.port}}
appname: springcloud
-consumer-config
启动类代码
@RibbonClient 指定服务使用的负载均衡类型,name不指定服务则为全部的服务打开负载均衡,也能够在用yml中进行配置。
@EnableHystrix 是支持hystrix打开断路器,在规定时间内失败参数超过必定参数,就会打开断路器,不会发起请求,而是直接进入到错误处理方法。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name =
"springcloud-provider-config", configuration = RibbonConfiguration.class)
@ComponentScan(excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, value = ExtendRibbon.class)})
@EnableHystrix
public class ConsumerApplication {
@Autowired
private RestTemplateBuilder builder;
@Bean
@LoadBalanced
public RestTemplate
restTemplate() {
return builder.build();
}
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
新建UserController
ribbon一个坑,不能接受List类型,要使用数组接收。
@Api xxx 是swagger的注解
@HystrixCommand(fallbackMethod=”userFallbackMethod”)
若是请求失败,会进入userFallbackMethod这个方法,userFallbackMethod这个方法要求参数和返回值与回调他的方法保持一致。
ribbon这个方法就是经过service-id获取获取服务实际的地址,这样服务的地址就不用硬编码了。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
@Api(
"springcloud consumer user 控制器")
@RequestMapping(
"user")
@RestController
public class UserController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient;
/** * @param id * @return */
@ApiOperation(value =
"根据用户id查询用户信息", httpMethod =
"GET", produces =
"application/json")
@ApiResponse(code =
200, message =
"success", response = User.class)
@GetMapping(
"{id}")
@HystrixCommand(fallbackMethod=
"userFallbackMethod")
public User
getUser(@
ApiParam(name =
"id", required =
true, value =
"用户Id")
@PathVariable String id) {
return this.restTemplate.getForObject(
"http://springcloud-provider-config/user/" + id, User.class);
}
public User
userFallbackMethod(String id){
return null;
}
/** * 这块ribbon不支持复杂数据类型list,因此要用数组接受,而后转list * @return */
@GetMapping(
"list")
@HystrixCommand(fallbackMethod =
"userList")
public List<User>
users(HttpServletRequest request) {
try {
User[] forObject =
this.restTemplate.getForObject(
"http://springcloud-provider-config/user/list", User[].class);
List<User> users = Arrays.asList(forObject);
return users ==
null ?
new ArrayList<User>() : users;
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
public List<User>
userList(HttpServletRequest request) {
return null;
}
/** * 经过服务id获取服务的地址 * @return */
@GetMapping(
"ribbon")
public String
ribbon(){
ServiceInstance serviceInstance = loadBalancerClient.choose(
"springcloud-provider-config");
return serviceInstance.getUri().toString();
}
}
运行springboot项目,先看有没有注册到eureka-server上。

注册成功后,访问接口,测试是否正确。

测试swagger-ui,访问localhost:8200/swagger-ui.html

到这里消费者服务就算是完成了,后边你们本身进行扩展。
5、用zuul作路由转发和负载均衡
这些微服务都是隐藏在后端的,用户是看不到,或者不是直接接触,能够用nginx或者zuul进行路由转发和负载均衡,zuul负载均衡默认用的是ribbon。
compile
group:
'org.springframework.cloud', name:
'spring-cloud-starter-eureka', version:
'1.3.4.RELEASE'
compile
group:
'org.springframework.cloud', name:
'spring-cloud-starter-zuul', version:
'1.3.4.RELEASE'
compile
group:
'org.springframework.boot', name:
'spring-boot-actuator', version:
'1.5.6.RELEASE'
compile
group:
'org.springframework.cloud', name:
'spring-cloud-starter-config', version:
'1.3.2.RELEASE'
仍是原来的配方,application.yml在git仓库
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
spring:
application:
name: springcloud
-zuul
cloud:
config:
discovery:
enabled:
true
service
-id: springcloud
-config-server
fail
-fast:
true
username: root
password: booszy
profile: dev
eureka:
client:
service
-url:
defaultZone: http:
instance:
prefer
-ip-address:
true
instance
-id: ${spring
.application
.name}:${spring
.cloud
.client
.ipAddress}:${spring
.application
.instance_id:${server
.port}}
appname: springcloud
-zuul
@RefreshScope这个注解是当application.yml配置文件发生变化的时候,不须要手动的进行重启,调用localhost:8400/refresh,就会加载新的配置文件,固然正在访问的客户并不影响仍是使用旧的配置文件,由于不是重启,后来的用户会使用新的配置文件。注意这块的刷新要用post请求。
@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
@RefreshScope
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
启动springboot项目,访问eureka-server

这时候,咱们就要经过zuul访问微服务了,而不是直接去访问微服务。
应该访问地址http://192.168.89.89:8400/springcloud-consumer-config/user/list,这块你要换成你的zuul地址。
可是有些人就会说,这样之后用户请求会不会太长,比较反感,因此能够经过配置进行修改访问地址。
zuul:
routes:
springcloud-consumer-config:
/consumer/**
springcloud-provider-config:
/provider/**
在application.yml中加入这样一段配置,其实就是nginx中的反向代理,使用一下简短的能够代理这个微服务。这个时候咱们就能够这样去访问了http://192.168.89.89:8400/consumer/user/list,是否是简短了不少
