基于Eureka搭建服务注册与发现中心
前言
不推荐继续使用NetFlix Eureka作为注册中心
- spring团队确认会使用其他Spring Cloud产品代替Netflix的解决方案
- Eureka2.0已经停止开发。而Eureka1.x架构存在问题,如客户端采用pull模式拉取服务数据时,导致实时性不足和无谓的拉取性能消耗问题;eureka集群每一个实例都可以接收客户端的写请求,并且各个实例会进行数据复制,从而导致一些性能问题
- 其他注册中心Nacos,Consul等一直在发展,差距会越来越大
一、工程目录及父工程pom文件
-
工程目录
-
父工程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> <packaging>pom</packaging> <modules> <module>eureka-service</module> <module>lsc-service-provider</module> <module>lsc-service-consumer</module> </modules> <parent> <artifactId>spring-boot-starter-parent</artifactId> <groupId>org.springframework.boot</groupId> <version>2.2.2.RELEASE</version> </parent> <groupId>com.gitee.maojian</groupId> <artifactId>learn-springcloud-eureka</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR8</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>
二、注册中心(eureka-service)
-
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"> <parent> <artifactId>learn-springcloud-eureka</artifactId> <groupId>com.gitee.maojian</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>eureka-service</artifactId> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <!--security--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project>
-
配置文件:bootstrap.yml
server: port: 8761 spring: application: name: eureka-service security: user: name: lsc password: lsc eureka: instance: hostname: localhost client: # 是否向注册中心注册实例(不注册,该实例本身就是注册中心) register-with-eureka: false # 是否从eureka拉取注册实例信息 fetch-registry: false service-url: defaultZone: http://lsc:lsc@${eureka.instance.hostname}:${server.port}/eureka server: # 自我保护模式 关闭 enable-self-preservation: false # 清理无效节点的时间间隔,默认60s eviction-interval-timer-in-ms: 60000
-
启动类:EurekaServiceApplication
package com.gitee.maojian; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class EurekaServiceApplication { public static void main(String[] args) { SpringApplication.run(EurekaServiceApplication.class, args); } }
-
安全机制配置类:WebSecurityConfig
package com.gitee.maojian.config; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/actuator/**").permitAll() .anyRequest() .authenticated().and().httpBasic(); } }
三、服务提供方(lsc-service-provider)
-
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"> <parent> <artifactId>learn-springcloud-eureka</artifactId> <groupId>com.gitee.maojian</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>lsc-service-provider</artifactId> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <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> </project>
-
配置文件:bootstrap.yml
server: port: 8770 spring: application: name: lsc-service-provider eureka: instance: client: service-url: defaultZone: http://lsc:lsc@localhost:8761/eureka
-
启动类:LscServiceProviderApplication
package com.gitee.maojian; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class LscServiceProviderApplication { public static void main(String[] args) { SpringApplication.run(LscServiceProviderApplication.class, args); } }
-
测试服务:ServiceProviderController
package com.gitee.maojian.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/service-provider") public class ServiceProviderController { @RequestMapping("/sayHi") public String sayHi(String name){ return "hi," + name; } }
四、服务消费方(lsc-service-consumer)
-
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"> <parent> <artifactId>learn-springcloud-eureka</artifactId> <groupId>com.gitee.maojian</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>lsc-service-consumer</artifactId> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <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> </project>
-
配置文件:bootstrap.yml
server: port: 8780 spring: application: name: lsc-service-consumer eureka: instance: client: service-url: defaultZone: http://lsc:lsc@localhost:8761/eureka
-
启动类:LscServiceConsumerApplication
package com.gitee.maojian; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class LscServiceConsumerApplication { public static void main(String[] args) { SpringApplication.run(LscServiceConsumerApplication.class, args); } }
-
RestTemplate配置:Config
package com.gitee.maojian.config; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class Config { @Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); } }
-
服务消费:ServiceConsumerController
package com.gitee.maojian.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import java.util.HashMap; import java.util.Map; @RestController @RequestMapping("/service-consumer") public class ServiceConsumerController { @Autowired private RestTemplate restTemplate; @RequestMapping("/sayHi") public String sayHi(String name) { Map<String,String> param = new HashMap<>(); param.put("name",name); String url = "http://LSC-SERVICE-PROVIDER/service-provider/sayHi?name={name}"; return restTemplate.getForEntity(url, String.class, param).getBody(); } }
五、安全机制
上面的搭建过程已经集成了Eureka安全机制,这里我们单独看一下eureka安全机制实现需要的操作
-
引人SpringSecurity依赖包
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-security</artifactId> </dependency>
-
在配置文件中添加用户密码验证
spring: security: user: name: lsc password: lsc
-
修改配置文件中的验证信息
eureka: client: service-url: defaultZone: http://lsc:lsc@${eureka.instance.hostname}:${server.port}/eureka
-
关闭csrf
package com.gitee.maojian.config; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/actuator/**").permitAll() .anyRequest() .authenticated().and().httpBasic(); } }
六、Eureka高可用
在hosts文件中添加
127.0.0.1 eureka-service-1
127.0.0.1 eureka-service-2
127.0.0.1 eureka-service-3
可以启动多个eureka服务,每个eureka服务都是可以相互复制的,会把客户端注册进来的服务复制到eureka集群中的其他节点里面来;各个节点之间是相互复制的
配置文件修改
-
修改端口号
-
修改eureka.client.service-url.defaultZone
eureka: instance: hostname: eureka-service-1 client: service-url: defaultZone: http://lsc:lsc@eureka-service-1:8761/eureka, http://lsc:lsc@eureka-service-2:8762/eureka, http://lsc:lsc@eureka-service-3:8763/eureka
启动三个实例后访问http://localhost:8761