原文地址:http://blog.csdn.net/yp090416/article/details/78017552
springcloud微服务实战:Eureka+Zuul+Ribbon+Hystrix+SpringConfig
相信现在已经有很多小伙伴已经或者准备使用springcloud微服务了,接下来为大家搭建一个微服务框架,后期可以自己进行扩展。会提供一个小案例: 服务提供者和服务消费者 ,消费者会调用提供者的服务,新建的项目都是用springboot,附源码下载。
coding仓库地址: coding地址 csdn下载地址: csdn下载地址
如果有问题请在下边评论,或者200909980加群交流。
Eureka:服务发现
Hystrix:断路器
Zuul:智能路由
Ribbon:客户端负载均衡
Turbine:集群监控
Springcloud-config:远程获取配置文件
接下来,我们开始搭建项目,首先我们到spring为我们提供的一个网站快速搭建springboot项目,点击访问,我这里用的是gradle,如果各位客官喜欢用maven,好吧你可以到http://mvnrepository.com/查看对应的依赖,点我访问。
一、搭建eureka-server服务springcloud-eureka-server
eureka-server作为服务发现的核心,第一个搭建,后面的服务都要注册到eureka-server上,意思是告诉eureka-server自己的服务地址是啥。当然还可以用zookeeper或者springconsul。
- 1.修改build.gradle文件
如果是maven项目请对应的修改pom.xml
//加入阿里的私服仓库地址
maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
- 1
- 2
//加入依赖
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-eureka-server', version: '1.3.4.RELEASE'
//加入security,是因为访问eureka-server需要用户名和密码访问,为了安全
compile group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: '1.5.6.RELEASE'
- 1
- 2
- 3
- 4
还有几点需要修改的,大家对应图片看看,就是springboot打包的时候会提示找不到主累。
- 2.修改 application.yml,建议用yml。
server:
port: 8761
eureka:
datacenter: trmap
environment: product
client:
healthcheck:
enabled: true
service-url:
defaultZone: http://root:booszy@localhost:8761/eureka
register-with-eureka: false #关闭自己作为客户端注册
fetch-registry: false
security:
basic:
enabled: true
user:
name: root #用户名和密码,等会访问的时候,会要求你登录,服务注册的时候也需要带着用户名和密码
password: booszy
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 3.修改程序的主类,建议修改类名,要加如eureka的 @EnableEurekaServer 注解,然后运行main方法。
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
http://localhost:8761/ 这个是eureka-server的页面地址,到这里,说明eureka-server搭建好了,简单吧,这一步一定要成功,否则后面的就不能继续进行下去了,后边基本类似。
二、搭建config-server服务springcloud-config-server
springcloud-config-server是用来将远程git仓库的配置文件动态拉下来,这样配置文件就可以动态的维护了。
新建一个springboot项目,修改maven私服地址,并加入一下依赖。
- 1.修改build.gradle文件
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'
//连接config-server也需要用户名和密码
compile group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: '1.5.6.RELEASE'
- 1
- 2
- 3
- 4
- 5
- 2.修改application.yml文件
server:
port: 8500
eureka:
client:
service-url:
#注册服务到eureka上,记住这里要加上eureka-server的用户名和密码
defaultZone: http://root:booszy@localhost:8761/eureka
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://git.coding.net/yirenyishi/springcloud-config-profile
searchPaths: '{application}'
security:
basic:
enabled: true
user:
#这是config-server的用户名和密码
name: root
password: booszy
- 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
- 3.修改启动类
修改启动类,要加入这三个注解,因为要注册到eureka-server上,所以需要@EnableEurekaClient这个注解
@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
然后运行启动springboot项目,等启动成功后访问eureka的页面,会发现springcloud-config-server已经注册到上面了,如果启动报错,请检查错误信息。
三、搭建服务提供者服务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')
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 2.编写配置文件bootstrap.yml
* 注意 : 这里除了application.xml,还需要一个bootstrap.yml
application.xml我是放到远程仓库地址的,大家可以直接到我的远程仓库,根据项目名(springcloud-provider-config)查询。配置文件的仓库地址:点击访问。
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://root:booszy@localhost:8761/eureka
instance:
prefer-ip-address: true
instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
appname: springcloud-provider-config
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 3.编写代码
编写主类
@SpringBootApplication
@EnableEurekaClient
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
新建UserController, 考虑篇幅 UserService 和 UserRepository就不贴代码了,想看的可以下载我的代码。
@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;
}
}
- 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
运行springboot项目,去eureka-server查看,有没有注册上。
我们的springcloud-provider-config已经注册到eureka上了,访问接口,成功。
四、搭建消费者服务springcloud-consumer-config-swagger
消费者要访问服务提供者的服务,这里用的是通过RestTemplate请求resetful接口,使用ribbon做客户端负载均衡,hystrix做错误处理,swagger生成接口文档。
还是熟悉的配方,熟悉的味道,新建springboot项目,添加项目依赖。
- 1.修改build.gradle文件
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"
)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 2.修改bootstrap.yml文件
application.yml 在git仓库,请前往git仓库查看。
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://root:booszy@localhost:8761/eureka
instance:
prefer-ip-address: true
instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
appname: springcloud-consumer-config
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 3.编写代码
启动类代码
@RibbonClient 指定服务使用的负载均衡类型,name不指定服务则为所有的服务打开负载均衡,也可以在用yml中进行配置。
@EnableHystrix 是支持hystrix打开断路器,在规定时间内失败参数超过一定参数,就会打开断路器,不会发起请求,而是直接进入到错误处理方法。
@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);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
新建UserController
ribbon一个坑,不能接受List类型,要使用数组接收。
@Api xxx 是swagger的注解
@HystrixCommand(fallbackMethod=”userFallbackMethod”)
如果请求失败,会进入userFallbackMethod这个方法,userFallbackMethod这个方法要求参数和返回值与回调他的方法保持一致。
ribbon这个方法就是通过service-id获取获取服务实际的地址,这样服务的地址就不用硬编码了。
@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();
}
}
- 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
运行springboot项目,先看有没有注册到eureka-server上。
注册成功后,访问接口,测试是否正确。
测试swagger-ui,访问localhost:8200/swagger-ui.html
到这里消费者服务就算是完成了,后边大家自己进行扩展。
五、用zuul做路由转发和负载均衡
这些微服务都是隐藏在后端的,用户是看不到,或者不是直接接触,可以用nginx或者zuul进行路由转发和负载均衡,zuul负载均衡默认用的是ribbon。
- 1.修改build.gradle文件
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'
- 1
- 2
- 3
- 4
- 2.修改bootstrap.yml
还是原来的配方,application.yml在git仓库
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://root:booszy@localhost:8761/eureka
instance:
prefer-ip-address: true
instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
appname: springcloud-zuul
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 3.启动类
@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);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
启动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/**
- 1
- 2
- 3
- 4
在application.yml中加入这样一段配置,其实就是nginx中的反向代理,使用一下简短的可以代理这个微服务。这个时候我们就可以这样去访问了http://192.168.89.89:8400/consumer/user/list,是不是简短了很多