Spring Cloud Netflix Eureka
传统的服务治理
通讯协议
XML-RPC -> XML 方法描述、方法参数 -> WSDL(WebServices 定义语言)
WebServices -> SOAP(HTTP、SMTP) -> 文本协议(头部分、体部分)
REST -> 通常是JSON/XML( Schema :类型、结构) -> 文本协议(HTTP Header、Body)
W3C Schema :xsd:string 原子类型,自定义自由组合原子类型
Java POJO : int、String
Response Header -> Content-Type: application/json;charset=UTF-8
Dubbo:Hession、 Java Serialization(二进制),跨语言不变,一般通过 Client(Java、C++)
二进制的性能是非常好(字节流,免去字符流(字符编码),免去了字符解释,机器友好、对人不友好)
序列化:把编程语言数据结构转换成字节流、反序列化:字节流转换成编程语言的数据结构(原生类型的组合)
Eureka服务端
第一步:先是pom.xml相关引用
<?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.lawt</groupId><artifactId>spring-cloud-eureka-server-demo</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging>
<name>spring-cloud-eureka-server-demo</name><description>Demo project for Spring Boot</description>
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.8.RELEASE</version><relativePath/></parent>
<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><spring-cloud.version>Dalston.SR4</spring-cloud.version></properties>
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka-server</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>
<dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
第二步:启动类SpringCloudEurekaServerApplication
package com.lawt;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication@EnableEurekaServerpublic class SpringCloudEurekaServerApplication {
public static void main(String[] args) {SpringApplication.run(SpringCloudEurekaServerApplication.class, args);}
}
第三步:配置修改application.properties
### Eureka Server 应用名称spring.application.name = spring-cloud-eureka-server### Eureka Server 服务端口server.port= 9090### 取消服务器自我注册eureka.client.register-with-eureka=false### 注册中心的服务器,没有必要再去检索服务eureka.client.fetch-registry = false## Eureka Server 服务 URL,用于客户端注册eureka.client.serviceUrl.defaultZone=\http://localhost:${server.port}/eureka
启动 SpringCloudEurekaServerApplication
启动成功后访问http://localhost:9090/
到此,Eureka的服务端就启动完毕。
Eureka客户端
创建provider
父pom.xml
<?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.lawt</groupId><artifactId>spring-cloud-eureka-client-demo</artifactId><version>0.0.1-SNAPSHOT</version><!-- 创建三个module--><modules><module>user-api</module><module>user-service-consumer</module><module>user-service-provider</module></modules><packaging>pom</packaging>
<name>spring-cloud-eureka-client-demo</name><description>Demo project for Spring Boot</description>
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.8.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent>
<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><spring-cloud.version>Dalston.SR4</spring-cloud.version></properties>
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>
user-api的pom.xml
<?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>spring-cloud-eureka-client-demo</artifactId><groupId>com.lawt</groupId><version>0.0.1-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>user-api</artifactId></project>
User实体类创建
package com.lawt.user.domain;public class User {private Long id;private String name;public Long getId() {return id;
}
public void setId(Long id) {this.id = id;
}
public String getName() {return name;
}
public void setName(String name) {this.name = name;
}
@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';
}
}
UserServic接口创建
package com.lawt.user.service;import com.lawt.user.domain.User;import java.util.Collection;
/*** 用户服务*/public interface UserService {
/*** 保存用户** @param user* @return 如果保存成功的话,返回<code>true</code>,* 否则返回<code>false</code>*/boolean save(User user);/*** 查询所有的用户对象** @return 不会返回<code>null</code>*/Collection<User> findAll();
}
user-service-provider的pom.xml
<?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>spring-cloud-eureka-client-demo</artifactId><groupId>com.lawt</groupId><version>0.0.1-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>user-service-provider</artifactId><dependencies><!-- 增加 用户 API 的依赖 --><dependency><groupId>com.gupao</groupId><artifactId>user-api</artifactId><version>${project.version}</version></dependency></dependencies></project>
模拟持久层UserRepository
package com.lawt.user.repository;
import com.lawt.user.domain.User;import org.springframework.stereotype.Repository;
import java.util.Collection;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ConcurrentMap;import java.util.concurrent.atomic.AtomicLong;
/*** {@link User 用户} 仓储*/@Repositorypublic class UserRepository {private ConcurrentMap<Long, User> repository = new ConcurrentHashMap<>();private static final AtomicLong idGenerator = new AtomicLong(0);public Collection<User> findAll() {return repository.values();
}
public boolean save(User user) {Long id = idGenerator.incrementAndGet();user.setId(id);return repository.putIfAbsent(id, user) == null;
}
}
UserService接口具体实现类
package com.lawt.user.service;
import com.lawt.user.domain.User;import com.lawt.user.repository.UserRepository;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.Collection;
/*** {@link UserService 用户服务} 提供者实现*/@Servicepublic class UserServiceImpl implements UserService {
@Autowiredprivate UserRepository userRepository;@Overridepublic boolean save(User user) {return userRepository.save(user);
}
@Overridepublic Collection<User> findAll() {return userRepository.findAll();
}
}
修改application.properties
## Eureka 注册中心服务器端口eureka.server.port = 9090## 服务提供方端口server.port = 7070## Eureka Server 服务 URL,用于客户端注册eureka.client.serviceUrl.defaultZone=\http://localhost:${eureka.server.port}/eureka## Management 安全失效management.security.enabled = false
创建一个controller
package com.lawt.user.web.controller;
import com.lawt.user.domain.User;import com.lawt.user.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RestController;
import java.util.Collection;
/*** {@link UserService 用户服务} 提供方 REST API {@link RestController}*/@RestControllerpublic class UserServiceProviderRestApiController {
@Autowiredprivate UserService userService;
/*** @param user User* @return 如果保存成功的话,返回{@link User},否则返回<code>null</code>*/@PostMapping("/user/save")public User saveUser(@RequestBody User user) {if (userService.save(user)) {System.out.println("UserService 服务方:保存用户成功!" + user);return user;} else {return null;
}
}
/*** 罗列所有的用户数据* @return 所有的用户数据*/@GetMapping("/user/list")public Collection<User> list() {return userService.findAll();
}
}
创建provider服务启动类
package com.lawt.user;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication@EnableDiscoveryClientpublic class UserServiceProviderApplication {public static void main(String[] args) {SpringApplication.run(UserServiceProviderApplication.class, args);
}
}
启动UserServiceProviderApplication
类
再次刷新http://localhost:9090/
自此,provider注册成功。
创建consumer
创建consumer的pom.xml
<?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>spring-cloud-eureka-client-demo</artifactId><groupId>com.lawt</groupId><version>0.0.1-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>user-consumer</artifactId><dependencies><!-- 增加 用户 API 的依赖 --><dependency><groupId>com.gupao</groupId><artifactId>user-api</artifactId><version>${project.version}</version></dependency></dependencies></project>
修改application.properties
spring.application.name = user-service-consumer## Eureka 注册中心服务器端口eureka.server.port = 9090## 服务消费方端口server.port = 8080## Eureka Server 服务 URL,用于客户端注册eureka.client.serviceUrl.defaultZone=\http://localhost:${eureka.server.port}/eureka## Management 安全失效management.security.enabled = false
创建代理类UserServiceProxy
package com.lawt.user.service;
import com.lawt.user.domain.User;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.web.client.RestTemplate;
import java.util.Collection;
/*** {@link UserService} Proxy 实现*/@Servicepublic class UserServiceProxy implements UserService {
private static final String PROVIDER_SERVER_URL_PREFIX = "http://user-service-provider";
/*** 通过 REST API 代理到服务器提供者*/@Autowiredprivate RestTemplate restTemplate;
@Overridepublic boolean save(User user) {User returnValue =restTemplate.postForObject(PROVIDER_SERVER_URL_PREFIX + "/user/save", user, User.class);return returnValue != null;
}
@Overridepublic Collection<User> findAll() {return restTemplate.getForObject(PROVIDER_SERVER_URL_PREFIX + "/user/list", Collection.class);
}
}
创建UserRestApiController供app、pc、或者其他调用
package com.lawt.user.web.controller;
import com.lawt.user.domain.User;import com.lawt.user.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;
import java.util.Collection;
/*** 用户服务 REST API*/@RestControllerpublic class UserRestApiController {
@Autowiredprivate UserService userService;
/*** @param name 请求参数名为“name”的数据* @return 如果保存成功的话,返回{@link User},否则返回<code>null</code>*/@PostMapping("/user/save")public User saveUser(@RequestParam String name) {User user = new User();user.setName(name);if (userService.save(user)) {return user;} else {return null;
}
}
/*** 罗列所有的用户数据* @return 所有的用户数据*/@GetMapping("/user/list")public Collection<User> list() {return userService.findAll();
}
}
启动类UserServiceConsumerApplication
package com.lawt.user;
import com.lawt.user.service.UserService;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.cloud.client.loadbalancer.LoadBalanced;import org.springframework.context.annotation.Bean;import org.springframework.web.client.RestTemplate;
/*** {@link UserService 用户服务} 消费引导类*/@SpringBootApplication@EnableDiscoveryClientpublic class UserServiceConsumerApplication {
public static void main(String[] args) {SpringApplication.run(UserServiceConsumerApplication.class, args);
}
@LoadBalanced@Beanpublic RestTemplate restTemplate(){return new RestTemplate();
}
}
启动,再次刷新http://localhost:9090/
以post访问http://localhost:8080/user/save
参数:name=zzzz
请求相应结果
到此为止,一个完整的Spring Cloud Netflix Eureka的demo已经完成。