微服务是什么?

微服务是指开发一个单个小型的但有业务功能的服务,每个服务都有自己的处理和轻量通讯机制,可以部署在单个或多个服务器上。微服务也指一种种松耦合的、有一定的有界上下文的面向服务架构。也就是说,如果每个服务都要同时修改,那么它们就不是微服务,因为它们紧耦合在一起;如果你需要掌握一个服务太多的上下文场景使用条件,那么它就是一个有上下文边界的服务,这个定义来自DDD领域驱动设计。简而言之,微服务就是将我们传统的MVC架构,所有的业务子模块都集成在一个很重的JVM进程当中。这种单体架构的好处就是便于管理,所有的代码在同一项目中,但是当产品规模越来越大,其坏处也很明显。
缺点一:项目过于臃肿当大大小小的功能模块都集中在同一项目的时候,整个项目必然会变得臃肿,让开发者难以维护。
缺点二:资源无法隔离就像刚刚小灰的经历一样,整个单体系统的各个功能模块都依赖于同样的数据库、内存等资源,一旦某个功能模块对资源使用不当,整个系统都会被拖垮。
缺点三:无法灵活扩展当系统的访问量越来越大的时候,单体系统固然可以进行水平扩展,部署在多台机器上组成集群。但是这种扩展并非灵活的扩展。比如我们现在的性能瓶颈是支付模块,希望只针对支付模块做水平扩展,这一点在单体系统是做不到的。

微服务的优点:

1.独立部署,灵活扩展传统的单体架构是以整个系统为单位进行部署,而微服务则是以每一个独立组件(例如用户服务,商品服务)为单位进行部署。

2.资源的有效隔离微服务设计的原则之一,就是每一个微服务拥有独立的数据源,假如微服务A想要读写微服务B的数据库,只能调用微服务B对外暴露的接口来完成。这样有效避免了服务之间争用数据库和缓存资源所带来的问题。

3.团队组织架构的调整微服务设计的思想也改变了原有的企业研发团队组织架构。传统的研发组织架构是水平架构,前端有前端的团队,后端有后端的团队,DBA有DBA的团队,测试有测试的团队。

下图是小型的微服务架构图:

推荐的微服务项目 什么是微服务项目_微服务


spring-cloud的注册中心是用的REST协议(远程调用,传json):基于http的一种规范。所有的服务与调用者(网官)都会去注册中心注册

第一步:写一个注册服务
spring-regist:工程名
导包

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<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>
		 <!-- Jackson Json处理工具包 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.9.0</version>
        </dependency>

写主类
Regist.java

package com.main;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
//注册服务器
public class Register {

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

}

application.properties

#服务器端口号
server.port=1110
#服务名称
spring.application.name=eureka-server

eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
#该服务的地址
eureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/

然后再浏览器中将地址输入回车

推荐的微服务项目 什么是微服务项目_微服务_02


第二步:写服务工程

导包

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>
		<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>
		  <!-- Jackson Json处理工具包 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.9.0</version>
        </dependency>

主类(在创建工程的时候会自动创建该类)

package com.main;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@EnableEurekaClient
//注册客户端
@ComponentScan("com.action")
//扫描com.action包
public class Server {

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

}

控制层

package com.action;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Add {
	
	@Value("${server.port}")
	private String port;
	
	@RequestMapping("/add")
	public String add(@RequestParam(defaultValue="1") int x,@RequestParam(defaultValue="1") int y) {
//		int n=x+y;
//		return n+"";
//		if(true)
//			throw new RuntimeException();
			return x+y+"-"+port;
	}

}

属性文件

SEspring.application.name=service-add
server.port=2222
eureka.client.serviceUrl.defaultZone=http://localhost:1110/eureka/

可以注册多个客户端,只需要修改端口号。

再次打开注册中心的界面,此时会出现客户端的端口号

推荐的微服务项目 什么是微服务项目_xml_03


将客服端的地址输入地址栏,如图:


第三步:写网官类(springcloud-getway)

导包

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		  <!-- Jackson Json处理工具包 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.9.0</version>
        </dependency>

主类:

package com.main;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@EnableEurekaClient
//注册为客户端
@EnableDiscoveryClient
//去注册中心发现客户端
@ComponentScan("com.action")
@EnableHystrix
//熔断
public class Getway {

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

}

RestTemplateConfig类:

package com.action;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {
	
	@Bean
	@Primary
	@LoadBalanced
	//负载均衡
	public RestTemplate restTemplate(){
		RestTemplate restTemplate = new RestTemplate();
		return restTemplate;
	}

}

测试类:

package com.action;

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 com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

@RestController
public class Test {
	
	@Autowired
	private RestTemplate  restTemplate;
	
	@RequestMapping("/add")
	@HystrixCommand(fallbackMethod="error")//如果有客户端挂掉 就告诉他调用这个方法
	public String add(int x, int y)
	{
		 //http://127.0.0.1:2220/add?x=1&y=2
		String url = "http://你的注册中心里你要访问的客户端的名字(注册中心客户端上的注册名称)/add?x="+x+"&y="+y;
		String response =restTemplate.getForObject(url, String.class);
		return response;
		
		
	}
	public String error(int x, int y)
	{
	  return "500";	
	}

}

然后在浏览器输入网官的地址,就可以调用在注册中心有注册的客户端的地址。

完毕。