2,将子业务service单独垂直切分,在web和service之间加入一个服务分发层HA dispacher-layer集群,在协议涉及时加入服务号,通过服务号做分发,web调用方依赖于分发层,传入服务号,分发层依赖于service层,通过服务号参数分发,1个表对应1个service,表之间相互耦解,服务之间均可以独立部署,扩缩容方便,有利于资源利用率,拆的越细,越解耦,缺点是复杂依赖也很复杂,问题监控定位难。
3,service A 由欧洲团队提供服务,java实现;service B由美洲团队提供服务,C++实现,service C由中国团队提供,用go实现。如果没有统一的服务框架,则应需要统一RPC服务框架,多个进程约定1个协议格式,使用socket通信,请求报文是一个11字节的字节流,前面三个字节是函数名字,中间4个字节是第一个参数,中间4个字节是第2个参数,末尾4个字节是第2个参数,将传入参数变为字节流,将字节流发给服务B ,从服务B接受返回字节流,将返回参数变为传出参数。提供补偿功能,与主服务分开部署,依赖服务也使用独立实例保证高可用性。
4,RPC框架是大大降低服务化成本,提高调用方与服务方研发效率,屏蔽进程调用函数细节的各类复杂细节,client包含序列化反序列化,连接池,均衡,故障,队列,超时,异步,server包含收发包队列,IO,工作线程,上下文管理,超时,异步回调。开发接口先行,语言中立,并行开发,用docker部署线上线下一致,高性能多租户,云化后也敏捷动态,可用paas实现微服务自动化与生命周期管理。
5,分布式服务调用可以实现跟踪系统,可以在业务日志中添加调用链ID,各个环节RPC均添加调用时延,QPS等。
非业务组件应该少加入业务代码,服务调用采用买点,也会采用配置采样率方式,买点即当前节点的上下文信息,包含TraceId,RPCId,开始结束时间,类型,协议,调用方IP,端口,服务名等,以及其他异常信息,报文等扩展,日志采用离线+实时的如flume结合kafka等,应按照TraceId汇总日志后按RPCId顺序整理。
6,服务治理,阈值上基于趋势配置来判断,一段时间发现趋势在偏离了就做报警,一个业务的所有调用展示成1个调用树,如1个节点上发生的错误一致往上报,导致整个调用链失败,那这个节点就是rootcause,修复即可,但链路和监控都是可以降级的。
7,有些服务在一段时间内成功率有波动(如95到100之间),可以自动降级,人工降级,并发送告警,DB连接池被打爆,访问量暴增到系统可以承受的最大阈值,据情况自动降级,页面降级,页面片段降级,页面异步请求降级,不重要服务。
8,dubbo作三层,web,service提供者,dao层封装,facache-service(dubbo接口提供),多个服务多种类型工程,工程之间相互调用,对工程进行解耦,大的业务流程可以转化为几个小时的业务流程,如果在dubbo service封装不错,则可以在web调用,封装不好则在service调用dubbo。
9,服务划分不要出现A服务的SQL,需要链接到B服务中表的情况,服务子系统之间避免出现环状的依赖调用,服务之间的调用链依赖不应该过长,避免分布式事务,简单数据查询可以使用action facade dao,带有业务逻辑的查询写入接口,action facade biz dao,每个服务方法代表1个功能,而非1个功能的1个步骤,否则将面临分布式事务,不适用过于抽象的通用接口,如Map query(Map) ,每个接口应该定义版本号,服务提供方不应该将Dao/sql等异常抛给消费者,应在服务实现中对消费方不关心的异常进行包装,否则消费方可能无法序列化,使用异常报错误比返回码要好,语义更友好。
10,一个系统中不同微服务可能在不同的平台上 erlang或者net,分配练货路线微服务,从何另外一个协作微服务收到的请求,当指定员工设定下一次的练货路线,另外一个微服务则完成计算最优路线,分配练货路线微服务,只需要收到练货路线,通知并且确定如何为雇员分配路线,负责单个功能,单独部署,1个/多个进程,拥有自己的数据存储,一个团队就能维护几个微服务,如电商,每次购物车微服务发生变化都应该立即部署,同时价格计算、推荐、产品目录等微服务应当继续运行并满足用户请求,每个微服务须打爆到不同的构件/程序包中,推荐算法会在微服务中运行并提供推荐需要的data,可能在硬盘也在DB,每个微服务可以使用最适合的DB。
11,springboot和springcloud微服务,创建springBoot程序主类,并添加注解EnableConfigServer注解,开启ConfigServer,添加注解EnableDiscoveryClient,激活Discovery实现,才能实现Countroller中对服务信息的输出,Controller用于url响应用户,注解RestController指定,应用可用mvn Spring-Boot.run启动,也可以扩展成jar,以java方式运行,开箱即用,在pom文件中引入Spring-boot-starter-actuator,无spring配置文件,调试项目,引入spring-starter-web即可,在实现controller加上注解EnableConfiguration,Main函数类加上注解SpringBootApplication。SpringCloud服务注册发现,默认为eureka,也可以支持zookeeper和Consul,Spring封装了eureka,使用EnableEurokaServer注解即可让应用变为euroka服务器,注解EnableDiscoveryClient,服务defaultZone= http://localhost:8761/eureka,服务启动后会自动注册到eureka,直接使用服务名称构成url即可。使用restTemplate去eureka服务器查找服务并调用。诸如SolrServer,ElastisSearchTemplate,JmsTemplate, 注解SpringBootApplication相当于Spring中注解 Configuration EnableAutoConfiguration ComponentScan表示自动配置。SpringCloud做分布式配置管理,不用的话也可以使用redis zookeeper ldap clb来存统一配置文件,存放仓库可用git,可用公网git,oschina,在工程中创建文件夹cloud-config-repo存放配置文件,创建2个配置文件cloud-config-dev.properties和cloud-config-test.properties,分别对应开发和测试环境,创建配置管理服务器,只是将配置文件转化为rest接口服务,使用ConfigServerApplication注解,用注解EnbaleConfigServer激活应用为配置文件服务器即可。使用EnableDiscoveryClient注解配置本应用使用服务注册和服务发现,用注解EnbaleClientBreaker表示启用断路层,如果使用了断路层,即HystlixCommand注解的方法失败后自动切换到注解 的failback方法执行,具备回退机制、请求缓存和请求打爆等。如果需要创造1个分层的ApplicationContext多个父子关系的上下文,可以使用SpringApplicationBuilder。
12,那么多个版本到底该如何维护?所有受支持的版本应共存于同一份基准代码和同一个服务实例中。此时可使用结构版本化(Versioning scheme)确定请求的到底是哪个版本。可行的情况下,老的端点应当更新以将修改后的请求中继至对应新端点。虽然同一个服务中多版本共存的局面不会降低复杂度,但可避免无意中增加复杂度,导致本就复杂的环境变得更复杂。
一个服务如果超负荷运转,那么让它直接快速的失败,要好过拖累其他服务。所有类型的请求需要对不同情况下的使用进行一定的限制。通过合理设置连接池规模,即可即可对在任意时间内向下游发出的请求数量做出限制。可为每个需要通信的服务设置一个独立连接池。如果无法从池中获得连接,此时最好能快速失败,而不要无限期堵塞。如果预计某个服务的响应时间为10-50毫秒,那么超时值只要大于500毫秒就已经不合适了。要将超时值设置为下游服务认为合理的时间。
断路开关可防止发起注定会失败的请求。该机制的实现非常简单:如果到某个服务的请求出现较多失败,添加一个标记并停止在接下来一段时间里继续向这个服务发请求。但同时也要定期允许发起一个请求,借此确认该服务是否重新上线,确认上线即可取消这样的标记。
在服务请求中包含一个关联ID。关联ID是一种唯一标识符,可用于区分每个服务传递给任意下游请求的请求来源。通过与集中化日志机制配合使用,可轻松看到请求在整个基础架构中的前进路径。
功能开关(Feature Flag)是在运行过程中打开或关闭特定功能的代码,借此可有效地实现代码部署和功能部署间的解耦。
此时可通过平台为服务团队提供集中化的日志系统。所有服务可通过标准化日志格式,将自己的日志发送至同一个日志系统。这种方法为服务团队带来更大灵活性,可跨越所有服务、特定的某个服务,或服务的某个实例搜索日志。