1.什么是服务注册与发现
服务注册与发现组件、服务提供者、服务消费者这三者之间依赖关系
- 每个服务在启动的时候会将自己的一些信息(如ip、port、server-name等)注册到注册中心,服务发现这个组件会会存储这些信息。
- 客户端调用是从注册中心根据server-name获取服务的信息进行通信操作。当然不是每次都是客户端都是从注册中心查询服务信息,客户端它也会缓存这个服务信息到内存中,这样也减少了注册中心的压力,即使注册中心宕机也不影响其它服务之间的调用关系。
本文以Eureka作为注册中心进行讲解,虽然现在eureka已经闭源,但是不影响我们学习。SpringCloud提供了多种服务发现的组件,如Eureka、Consul和ZooKeeper。
2.Eureka介绍
Eureka是Eetflix开源的服务注册与发现组件。它主要包含Server和Client两个端。SpringCloud将它集成在子项目SpringCloudNetflix中,从而可以实现服务的注册与发现功能。
- Application Service:相对于提供者。
- Application Client:相对于消费者。
- Eureka Server提供服务注册与发现,每个服务启动都会注册到Eureka Server。
- Eureka Client相对于Java客户端。Eureka Client启动后会每隔30秒向Eureka Server发送心跳包,Eureka Server如果90秒内没有收到心跳包则会踢出对应服务,这也是Eureka的服务保护机制。
3.SpringCloud整合Eureka Server
3.1 创建一个Eureka-server的 Maven工程,并且添加pom依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lk</groupId>
<artifactId>microservice-discovery-eureka</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<!-- 管理依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.M7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
3.2 在Resource目录创建application.yml文件
###服务端口号
server:
port: 8761
###eureka 基本信息配置
eureka:
instance:
###注册到eureka的ip地址
hostname: 127.0.0.1
client:
serviceUrl:
# 设置与eureka server交互的地址,后续查询服务都是通过这个地址 这个就是注册中心地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
###因为自己是为注册中心,不需要自己注册自己
register-with-eureka: false
###因为自己是为注册中心,不需要检索服务
fetch-registry: false
3.3 编写启动类
package com.lk.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* @Auther: lk
* @Date: 2019/5/11 16:00
* @Description:
*/
@SpringBootApplication
//@EnableEurekaServer 表示自己是Eureka Servevr
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
4.将服务注册到Eureka Server
4.1 创建一个项目名为microservice-provider-user的Maven工程,并且添加pom依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lk</groupId>
<artifactId>microservice-discovery-user</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<dependencies>
<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-web</artifactId>
</dependency>
</dependencies>
<!-- 管理依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.M7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
4.2 在Resource目录添加application.yml配置
###服务启动端口号
server:
port: 9901
###服务名称(服务注册到eureka名称)
spring:
application:
#服务名称
name: microservice-discovery-user
###服务注册到eureka地址
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
###因为该应用为注册中心,不会注册自己
register-with-eureka: true
###是否需要从eureka上获取注册信息
fetch-registry: true
4.3 编写启动类
package com.lk.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* @Auther: lk
* @Date: 2019/5/11 16:13
* @Description:
*/
@SpringBootApplication
//@EnableEurekaClient 表示自己是Eureka Client端
@EnableEurekaClient
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
接着我们启动Eureka Server,浏览器中服务http://localhost:8761
由图可知,Eureka Server可以显示很多信息,如当前示例的运行状态、注册到Eureka Server 上的服务实例、常用信息、实例信息等。但是现在仅仅只启动了Eureka Servver端,此时还没有Eureka Clientd端注册,所以此时列表为空。
接下来我们启动microservice-provider-user项目。此时我们在浏览器中访问http://localhost:8761
此时列表中已经显示有服务注册上来,并且我们可以看到server-name、服务个数、服务状态、服务其他信息等。
5.用户认证
在实际项目中,一般会配置用户认证才能允许访问Eureka Server
5.1 为Eureka Server服务添加用户认证
在之前的Eureka Server项目的pom文件引入以下依赖信息
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
在之前的application.yml文件添加一下内容,把之前文件覆盖
###服务端口号
server:
port: 8761
###eureka 基本信息配置
eureka:
instance:
###注册到eureka的ip地址
hostname: 127.0.0.1
client:
serviceUrl:
# 设置与eureka server交互的地址,后续查询服务都是通过这个地址 这个就是注册中心地址
# 因为加了用户认证 所以需要格式必须是http://用户名:密码@eurekahost:eurekaport/
defaultZone: http://user:666666@${eureka.instance.hostname}:${server.port}/eureka/
###因为自己是为注册中心,不需要自己注册自己
register-with-eureka: false
###因为自己是为注册中心,不需要检索服务
fetch-registry: false
spring:
security:
user:
# 账号
name: user
# 密码
password: 666666
接着重新启动Eureka Server服务,浏览器输入http://localhost:8761访问
由于配置了用户认证,如果没有登录首先会重定向到login页面进行登录
这个页面是security框架自带的,我们可以看下相关源码配置
这个类是默认的登录页面,我们可以点击进去看看
init()方法初始化了一些url,接下来我们看下为什么没有登录没被进行拦截
看到doFilter()方法,这不是servlet里面的过滤器吗,这个方法主要就是判断用户是否登录了没,如果登录了则放行,没有登录的会则进入else,this.generateLoginPageHtml方法则是生成一串html字符串,然后使用流的方式返回给client端。
由于security框架默认开启csrf校验,但是在Eureka Client端注册到Eureka Server端时,如果没有带crsf信息会报错,所以我们要禁用csrf校验。
创建WebSecurityConfig类重写configure方法
package com.lk.app;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
super.configure(http);
}
}
当我们登录成功之后变可以看到Eureka的ui界面,此时是没有服务注册的,因为我把其它服务停止了,而且其它服在注册到注册中心也需要进行用户认证.
5.2 为microservice-provider-user服务配置用户认证
在application.yml文件中加入如图配置
如果不加入用户认证,在服务注册的时候一直报Cannot execute request on any known server错误。
接下来启动项目,我们可以看到Eureka Server的UI界面会有服务注册的信息