最近接着spring框架学习了微服务相关内容,结合spring cloud官方文档入手了下。下面把搭建框架的过程以及使用中的个人一些感悟分享一下。
以前有听说过微服务,也知道微服务,就是将原来集中在一个系统或进程的应用依据服务功能将他们组件化分离开来,可以使用不同的语言,底层存储管理和其他技术,分别部署不同服务器或成为单独的进程实现功能的隔离为外界所调用。也一直都听说微服务的重点和难点是服务的治理,管理。带着这样的疑问,开始从spring cloud来了解学习微服务。
一,eureka服务注册中心。
作为服务注册中心,eureka能够为微服务提供注册和发现的功能,换言之,服务(提供者)可以在这里注册,然后服务调用者(消费者)到注册中心去找需要的服务然后从注册中心获取到服务访问路径以访问服务。你可以想象到,在应用上线或发生一些变动后,很可能会发生服务迁移行为,那么这个时候,你需要去所有调用你这个变动的服务的地方去修改访问url,当你的系统特别庞大和服务的时候,这不仅很麻烦而且容易出错。所以,eureka需要解决url变动的时候,调用者无修改问题,这也算是刚开始提到的服务治理吧。eureka中有域的概念,服务调用者和服务提供者所在应用都会事先定义一个域,服务调用者只会去通过注册中心去查询同一个域下的服务提供者有没有提供调用者查找的服务。域是在yml中配置的,等下会说。下面给出服务提供方配置。
先实现eureka client(服务提供方应用)引入pom
org.springframework.boot
spring-boot-starter-tomcat
provided
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
1.4.2.RELEASE
org.springframework.boot
spring-boot-starter-actuator
org.springframework.cloud
spring-cloud-dependencies
Finchley.BUILD-SNAPSHOT
pom
import
然后,编写启动类:
@SpringBootApplication
@EnableDiscoveryClient
public class EurekaclientApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(EurekaclientApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(EurekaclientApplication.class);
}
}
然后,配置application.yml:
server:
tomcat:
uri-encoding: UTF-8
max-threads: 1000
min-spare-threads: 30
port: 8003
servlet:
context-path: /
eureka:
client:
serviceUrl:
defaultZone: http://root:123456@localhost:8001/eureka,http://root:123456@localhost:8002/eureka
spring:
application:
name: eureka-client1
解释一下,这里的defaultZone就是注册中心的地址,url后面的“/eureka”这个是默认的不能更改,前面的url可以根据实际情况变动url里的root:123456则算是一种plaintext认证吧,服务提供者和调用者都需要有,不然无法调用。这里我们提供了两个zone,算是一个小集群吧,他们互为备份,可实现注册中心高可用(等下我们会通过profile来启动两个eureka server)。name 则是应用名称这个用于在调用时确定调用服务所在应用,等下会在调用者里指定。
服务实现,这个和你平时写controller是一样的。
@RestController
@RequestMapping("/user")
public class FirstMicroServiceController {
@Value("${server.port}")
String port;
@RequestMapping("/getInfo")
public String getInfor() {
return "testInfo"+port;
}
}
这样,我们的服务提供方应用就算完成了。
实现注册中心(eureka server)
再新建一个spring boot应用,pom文件和client一模一样,不在写了。
启动类如下:
@EnableEurekaServer
@SpringBootApplication
public class EurekaserverApplication extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(EurekaserverApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(EurekaserverApplication.class);
}
}
配置文件application.yml
server:
tomcat:
uri-encoding: UTF-8
max-threads: 1000
min-spare-threads: 30
port: 8001
servlet:
context-path: /
---
spring:
profiles: peer1
eureka:
client:
registerWithEureka: false
serviceUrl:
defaultZone: http://localhost:8002/eureka/
instance:
hostname: localhost
spring:
application:
name: eureka-server1
---
spring:
profiles: peer2
eureka:
client:
registerWithEureka: false
serviceUrl:
defaultZone: http://localhost:8001/eureka/
instance:
hostname: localhost
spring:
application:
name: eureka-server2
解释下,application.yml中
---
spring:
profiles:
是配置多环境用的,我们平时在开发的时候会有开发环境,测试的时候有测试环境,上线后有线上环境,有了这些配置,我们只要在启动的时候添加启动参数-Dspring.profiles=***就可以设置环境了,上面说了,这里启动了两个server以实现高可用,让他们互为备份,那么peer1的defaultZone则是peer2的地址,peer2对应的defaultZone则是peer1的网址。这样,就配置好了eureka server,然后启动应用,在eclipse的run 中配置run conficure
在VM argument中配置 -Dspring.port=8001 -Dspring.profiles=peer1,然后,点击run,再次进入这个界面,配置-Dspring.port=8002 -Dspring.profiles=peer2 再次点击run(启动第一个server的时候会报错连接不上服务器这是因为第二个服务器没启动,不用管它),这样,就启动了两个eureka server(服务注册中心)。好了,eureka server搞定。
eureka client 服务消费端
pom文件和第一个一模一样
application.yml如下:
server:
tomcat:
uri-encoding: UTF-8
max-threads: 1000
min-spare-threads: 30
port: 8004
servlet:
context-path: /
eureka:
client:
serviceUrl:
defaultZone: http://root:123456@localhost:8001/eureka,http://root:123456@localhost:8002/eureka
启动类如下:
@SpringBootApplication
//@ComponentScan(value="com")
@EnableDiscoveryClient
public class Eurekaclient2Application {
public static void main(String[] args) {
SpringApplication.run(Eurekaclient2Application.class, args);
}
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
这里配置了一个RestTmpalte,@LoadBalance则是后面要讲的Ribbon,用于在客户端(服务消费者端)的负载均衡,一方面他可以将对服务的访问的流量分发到提供相同服务服务器(只要注册在注册中心的应用名相同以及RequestMapping中的路径也相同)而且在结合熔断器hystrix后,可以实现服务熔断以及访问服务的故障自动切换,这个以后讲。
调用服务的类:
@RestController
@RequestMapping("/test")
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/getInfo")
public String test() {
//ServiceInstance si = balanceClient.choose("eureka-client1");
// System.out.println("host:"+si.getHost()+" port:"+si.getPort());
// return "host:"+si.getHost()+" port:"+si.getPort();
return restTemplate.getForEntity("http://eureka-client1/user/getInfo", String.class).getBody().toString();
}
}
如你说见,这里用RestTemplate封装了访问,这里给出的访问链接只有提供服务(provider)的应用名称和我们访问服务的RequestMapping里的信息,至于服务提供者的主机信息或者说ip端口信息,则没有提供,RestTemplate封装的会自动向注册中心去获取,这也实现了服务的管理。
完成上面配置后,依次启动两个eureka server,erureka client(provider),consumer。首先访问你的eureka server,查看是否上面有两个eurekaclient的注册信息。然后,访问消费端服务的路径,查看界面是否有返回值,暨验证eureka的管理服务功能。