直接搭建项目,来使用上篇讲解的组件
环境:idea、jdk1.8、Spring Boot(2.0.6.RELEASE)、Spring Cloud(Finchley.SR1)
注意!后续application.yml中的spring.application.name
需使用驼峰命名或其他,名称中不可存在符号,如provider-user
,需改成providerUser
,不然后面讲到的Config组件中,git中的配置文件命名也会带-,然后就会出现无法自动加载配置的bug。
1、Eureka注册中心
如果使用idea去创建注册中心的话,如图所示
依赖如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Cloud Eureka Server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
application.yml
server:
port: 7001 #项目端口号
eureka:
client:
register-with-eureka: false #false表示不向注册中心注册自己
fetch-registry: false #false表示自己端就是注册中心,职责就是维护服务实例,不需要去检索服务
service-url:
defaultZone: http://localhost:7001/eureka/ #设置与Eureka Server交互的地址查询服务和注册服务
server:
enable-self-preservation: false #false表示在此eureka服务器中关闭自我保护模式,所谓自我保护模式是指,出现网络分区、eureka在短时间内丢失过多客户端时,会进入自我保护模式,即一个服务长时间没有发送心跳,eureka也不会将其删除
spring:
application:
name: eurekaServer7001 #项目对外名称
启动类
@SpringBootApplication
@EnableEurekaServer
public class Eureka7001Application {
public static void main(String[] args) {
SpringApplication.run(Eureka7001Application.class, args);
}
}
接下来搭建两个服务
依赖相关
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Cloud Eureka Client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
application.yml
server:
port: 8001
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
spring:
application:
name: providerUser
启动类
@SpringBootApplication
@EnableDiscoveryClient
public class ProviderUser8001Application {
public static void main(String[] args) {
SpringApplication.run(ProviderUser8001Application.class, args);
}
}
同理,创建另外一个服务,并在每个服务里创建一个测试接口
OK,注册中心和两个服务创建完毕,接下来开始测试,先启动Eureka,再启动两个服务
这里我修改了本地HOST文件127.0.0.1 eureka7001.com
分别调用两个服务的接口
2、Eureka以及各个微服务如何做集群呢?只需修改application.yml文件即可
Eureka application.yml
只需修改server.port
、eureka.client.service-url.defaultZone
、spring.application.name
,其他属性照搬
server:
port: 7001 #项目端口号
eureka:
client:
register-with-eureka: false #false表示不向注册中心注册自己
fetch-registry: false #false表示自己端就是注册中心,职责就是维护服务实例,不需要去检索服务
service-url:
defaultZone: http://localhost:7002/eureka/,http://localhost:7003/eureka/ #设置与Eureka Server交互的地址查询服务和注册服务,做集群时将各个Eureka的地址以,隔开的形式写在defaultZone后面即可
server:
enable-self-preservation: false #false表示在此eureka服务器中关闭自我保护模式,所谓自我保护模式是指,出现网络分区、eureka在短时间内丢失过多客户端时,会进入自我保护模式,即一个服务长时间没有发送心跳,eureka也不会将其删除
spring:
application:
name: eurekaServer7001 #项目对外名称
微服务提供者 application.yml
只需修改server.port
、eureka.client.service-url.defaultZone
,其他属性照搬。
注意!spring.application.name
该属性不可更改,集群内的服务提供者实例名必须保持一致
server:
port: 8001
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka,http://localhost:7002/eureka,http://localhost:7003/eureka
spring:
application:
name: providerUser
测试和上面一致,接口照常调用。
3、Feign组件
依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Cloud Eureka Client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- Spring Cloud Feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
application.yml
server:
port: 80
spring:
application:
name: consumerUser
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/
启动类
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class ConsumerUser80Application {
public static void main(String[] args) {
SpringApplication.run(ConsumerUser80Application.class, args);
}
}
A调用B服务需要在A服务中添加以下接口
@FeignClient(name="providerUser")
的name
value值必须和B服务的spring.application.name
一致
@RequestMapping(value = "user",method = RequestMethod.GET)
的必须和想要调用的B服务的接口一致,并且返回类型也必须保持一致
@FeignClient(name="providerUser")
public interface UserClientService {
@RequestMapping(value = "user",method = RequestMethod.GET)
String user();
}
A服务的Controller
@RestController
public class UserConsumerController {
@Autowired
UserClientService userClientService;
@RequestMapping(value="/userByFeign",method = RequestMethod.GET)
public String user(){
return userClientService.user();
}
}
测试下,按顺序启动Eureka、A服务、B服务,调用 http://localhost/userByFeign
调用成功,B服务被调用时是无感知的,只需添加一个注解,就可以随意访问其他服务的接口,很舒服。
4、Zuul网关
依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Cloud Eureka Client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- Spring Cloud Zuul -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.zhao</groupId>
<artifactId>common-core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
application.yml
server:
port: 9527
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka,http://localhost:7002/eureka,http://localhost:7003/eureka
spring:
application:
name: zuulGateway9527
启动类
@SpringBootApplication
@EnableZuulProxy
public class ZuulGateway9527Application {
public static void main(String[] args) {
SpringApplication.run(ZuulGateway9527Application.class, args);
}
}
按顺序启动Eureka、Zuul、服务提供者
查看Eureka,网关已加入注册中心
通过网关调用服务提供者的接口
http://zuul的IP:zuul的端口/服务提供者的spring.application.name
/接口
这里我修改了HOST的zuul本地映射
此时,我们可以发现,这里对外暴露了真实的微服务实例名称,为了加固安全性,可以对微服务实例名进行一个路由映射反射规则
修改zuul的application.yml
server:
port: 9527
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka,http://localhost:7002/eureka,http://localhost:7003/eureka
zuul:
routes:
myuser.serviceId: provideruser
myuser.path: /myuser/**
spring:
application:
name: zuulGateway9527
Before:http://myzuul.com:9527/provideruser/user
After:http://myzuul.com:9527/myuser/user
这个时候又会发现以前的通过微服务实例名去调用接口,还是能访问通的,于是,再次加强安全性
修改application.yml
server:
port: 9527
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka,http://localhost:7002/eureka,http://localhost:7003/eureka
zuul:
routes:
myuser.serviceId: provideruser
myuser.path: /myuser/**
ignored-services: "*" #*表示所有真实微服务实例名都被拦截,也可修改为具体的某个实例名
spring:
application:
name: zuulGateway9527
可以看到除了zuul.routes.myuser.path
以外的都被拦截了
还可以设置统一的公共前缀,修改application.yml
server:
port: 9527
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka,http://localhost:7002/eureka,http://localhost:7003/eureka
zuul:
routes:
myuser.serviceId: provideruser
myuser.path: /myuser/**
ignored-services: "*"
prefix: /cloud #统一公共前缀
spring:
application:
name: zuulGateway9527