Spring Cloud Netflix之Eureka多个服务之间调用(不使用负载均衡,使用简单的RestTemplate实现)

1.声明

当前内容用于本人学习和复习之用,当前内容为,一个服务注册中心,多个服务(权限服务,用户信息服务,支付服务,以及一个app门面),通过app门面方式实现调用多个服务实现操作

2.pom依赖

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>1.3.7.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>Brixton.SR5</spring-cloud.version>
	<!-- <springboot.version>1.3.7.RELEASE</springboot.version> -->
</properties>

<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>
		<!-- <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> 
			<version>${springboot.version}</version> <type>pom</type> <scope>import</scope> 
			</dependency> -->

	</dependencies>
</dependencyManagement>

<dependencies>
	<!-- spring cloud 的基本配置 -->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-eureka</artifactId>
		<!-- <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> -->
	</dependency>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-eureka-server</artifactId>
		<!-- <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> -->
	</dependency>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-config</artifactId>
	</dependency>
	<!-- spring boot 的基本配置 -->
	<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>

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
	</plugins>
</build>

2.创建服务治理中心(采用Eureka方式实现)

@EnableEurekaServer
@SpringBootApplication
public class AppServiceRegisteryCenter {
	public static void main(String[] args) {
		SpringApplication.run(AppServiceRegisteryCenter.class, args);
	}
}

配置文件application.properties

server.port=1111
server.application.name=eureka-server
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.serverUrl.defaultZone=http://127.0.0.1:1112/eureka/
eureka.server.enable-self-preservation=false
eureka.instance.prefer-ip-address=false

3.创建用户信息服务、用户注册服务、权限服务、支付服务

1.用户信息服务

实体类

public class UserInfo {
	private String name;
	private Integer id;
	private List<String> roles;

}

入口类

@RestController
@EnableEurekaClient
@SpringBootApplication
public class UserInfoServiceApp {
	// 这里模拟数据库操作
	static Map<String, UserInfo> datas = new HashMap<String, UserInfo>();
	static {
		datas.put("admin", new UserInfo("admin", 1, Arrays.asList("ROLE_ADMIN", "ROLE_USER")));
		datas.put("user", new UserInfo("user", 2, Arrays.asList("ROLE_USER")));
		datas.put("guest", new UserInfo("guest", 3, Arrays.asList("ROLE_GUEST")));
	}

	@RequestMapping("/getUserInfoByName")
	public String getUserInfoByName(String name) {
		System.out.println("调用用户信息服务提供者的内容---》【通过用户名获取用户信息】");
		System.out.println("执行当前的通过用户名查询的操作--->" + name);
		return datas.get(name).toString();
	}

	@RequestMapping("/addUserInfo")
	public String addUserInfo(UserInfo userInfo) {
		System.out.println("调用用户信息服务提供者的内容---》【添加用户信息】");
		datas.put(userInfo.getName(), userInfo);
		return "添加成功";
	}

	@RequestMapping("/login")
	public String login(String name) {
		System.out.println("调用用户信息服务提供者的内容---》【登录操作】");
		return "登录" + (datas.containsKey(name) ? "成功" : "失败");
	}

	public static void main(String[] args) {
		SpringApplication.run(UserInfoServiceApp.class, args);
	}
}

用户信息模块的配置文件

server.port=2001
spring.application.name=userinfo-service-provider
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

2.用户注册服务

@RestController
@EnableEurekaClient
@SpringBootApplication
public class RegisterServiceApp {

	@Autowired
	DiscoveryClient client;

	// 启用注册验证操作
	private boolean validateRegister(String name) {
		return name != null;
	}

	@RequestMapping("/registerUserInfo")
	public String registerUserInfo(String name) {
		System.out.println("调用用户注册服务提供者的内容");
		List<ServiceInstance> instances = client.getInstances("userinfo-service-provider");
		ServiceInstance serviceInstance = instances.get(0);
		URI uri = serviceInstance.getUri();
		String url = uri.toString() + "/addUserInfo";
		if (validateRegister(name)) {
			ResponseEntity<String> postForEntity = restTemplate.getForEntity(url + "?name={1}", String.class, name);
			return postForEntity.getBody();
		}
		return "注册用户信息失败!";
	}

	@Autowired
	RestTemplate restTemplate;

	@Bean
	public RestTemplate template() {
		return new RestTemplate();
	}

	public static void main(String[] args) {
		SpringApplication.run(RegisterServiceApp.class, args);
	}
}

配置文件

server.port=2002
spring.application.name=register-service-provider
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

3.权限服务

@RestController
@EnableEurekaClient
@SpringBootApplication
public class PermissServiceApp {

	// 模拟数据库操作
	private static Map<String, String> permissesData = new HashMap<String, String>();

	static {
		permissesData.put("ROLE_ADMIN", "INSERT,UPDATE,DELETE,SELECT");
		permissesData.put("ROLE_USER", "SELECT,UPDATE");
		permissesData.put("ROLE_GUEST", "SELECT");

	}
	// 一个非常简单的服务,通过角色名称获取权限字符串
	@RequestMapping("/getPermissByRoleName")
	public String getPermissByRoleName(String roleName) {
		System.out.println("调用权限注册服务提供者的内容");
		return permissesData.get(roleName);
	}

	public static void main(String[] args) {
		SpringApplication.run(PermissServiceApp.class, args);
	}
}

配置文件

server.port=2003
spring.application.name=permiss-service-provider
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

4.支付服务

@RestController
@EnableEurekaClient
@SpringBootApplication
public class PayServiceApp {
	@RequestMapping("/pay")
	public String pay(String name, Integer money) {
		return "用户【" + name + "】,支付【" + money + "】成功!";
	}

	public static void main(String[] args) {
		SpringApplication.run(PayServiceApp.class, args);
	}
}

配置文件

server.port=2004
spring.application.name=pay-service-provider
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

4.创建app门面服务(主要通过整个地址访问其他地址的服务)

@RestController
@EnableEurekaClient
@SpringBootApplication
public class AppDemo {
	private static final String SUFIX_STRING = "-service-provider";
	@Autowired
	DiscoveryClient client;

	@RequestMapping("getPermiss")
	public String getPermiss(String roleName) {
		System.out.println("访问App门面中通过角色名称获取用户权限");
		List<ServiceInstance> instances = client.getInstances("permiss" + SUFIX_STRING);
		ServiceInstance serviceInstance = instances.get(0);
		String string = serviceInstance.getUri().toString();
		ResponseEntity<String> postForEntity = restTemplate.getForEntity(string + "/getPermissByRoleName?roleName={1}",
				String.class, roleName);
		String body = postForEntity.getBody();
		return body;
	}

	@RequestMapping("/getUserInfo")
	// 用户信息模块
	public String getUserInfo(String name) {
		System.out.println("访问App门面中通过用户名称获取用户信息");
		List<ServiceInstance> instances = client.getInstances("userinfo" + SUFIX_STRING);
		ServiceInstance serviceInstance = instances.get(0);
		String string = serviceInstance.getUri().toString();
		ResponseEntity<String> postForEntity = restTemplate.getForEntity(string + "/getUserInfoByName?name={1}",
				String.class, name);
		String body = postForEntity.getBody();
		return body;
	}

	@RequestMapping("/login")
	public String login(String username) {
		System.out.println("访问App门面中通过用户名称来检查登录");
		List<ServiceInstance> instances = client.getInstances("userinfo" + SUFIX_STRING);
		ServiceInstance serviceInstance = instances.get(0);
		String string = serviceInstance.getUri().toString();
		ResponseEntity<String> postForEntity = restTemplate.getForEntity(string + "/login?name={1}", String.class,
				username);
		String body = postForEntity.getBody();
		return body;
	}

	@RequestMapping("/register")
	public String register(String name) {
		System.out.println("访问App门面中注册用户信息");
		List<ServiceInstance> instances = client.getInstances("register" + SUFIX_STRING);
		ServiceInstance serviceInstance = instances.get(0);
		String string = serviceInstance.getUri().toString();
		ResponseEntity<String> postForEntity = restTemplate.getForEntity(string + "/registerUserInfo?name={1}",
				String.class, name);
		String body = postForEntity.getBody();
		return body;
	}

	@RequestMapping("/pay")
	public String pay(String name, Integer money) {
		System.out.println("访问App门面中支付服务");
		List<ServiceInstance> instances = client.getInstances("pay" + SUFIX_STRING);
		ServiceInstance serviceInstance = instances.get(0);
		String string = serviceInstance.getUri().toString();
		ResponseEntity<String> postForEntity = restTemplate.getForEntity(string + "/pay?name={1}&money={2}",
				String.class, name, money);
		String body = postForEntity.getBody();
		return body;
	}

	@Autowired
	RestTemplate restTemplate;

	@Bean
	public RestTemplate restTemplate() {
		return new RestTemplate();
	}

	public static void main(String[] args) {
		SpringApplication.run(AppDemo.class, args);
	}
}

配置文件

server.port=2008
spring.application.name=app-service
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

5.测试访问app门面服务

在这里插入图片描述
通过app门面访问注册服务
在这里插入图片描述
通过app门面访问支付服务
在这里插入图片描述
通过app门面访问用户信息服务
在这里插入图片描述
通过app门面访问权限服务
在这里插入图片描述
以上都访问成功,通过一个地址实现当前的其他服务的访问操作

6.思考当前的项目中存在的问题

  1. 我们使用DiscoveryClient的方式实现了手动选择需要的服务实例(如果当前的服务刚好一个都没有或者都宕机了,一定会出现问题),这里还显示提供了服务名称
  2. 我们使用了RestTemplate方式实现调用,这里还手动编写了访问的url,耦合度太大

如果我们将当前的服务获取方式采用指定方式,但是不是手动选择第一个(采用轮询或者其他方式实现,就可以实现负载均衡(所有服务都不宕机))

如果restTemplate能自动创建url应该是不可能的,并且还需要创建参数并匹配(因为它并不知道这个服务中哪个是我们需要调用的)

7.总结

1.当前项目中使用门面的方式实现了功能的聚集,通过门面方式调用各个服务

2.虽然实现了操作,但是存在一定的问题

以上纯属个人见解,如有问题请联本人!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值